diff --git a/CMakeLists.txt b/CMakeLists.txt index f875f8f5e..a53baad5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,23 +18,15 @@ cmake_minimum_required(VERSION 3.11) project(iEDA) -# option setting -option(BUILD_PR_FLOW "If ON, build PR flow." ON) option(BUILD_STATIC_LIB "If ON, build static lib." ON) -if(NOT BUILD_STATIC_LIB) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -endif() - -option(BUILD_PYTHON "If ON, build python interface." OFF) +# option(BUILD_PYTHON "If ON, build python lib." ON) if(BUILD_PYTHON) set(BUILD_STATIC_LIB OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() option(BUILD_GUI "If ON, build GUI." ON) -# add_subdirectory(src/third_party/mt-kahypar) - set(CMAKE_CXX_STANDARD 20) set(CMAKE_VERBOSE_MAKEFILE OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -42,12 +34,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(FORT_ENABLE_TESTING OFF CACHE INTERNAL "") # Disable building tests and examples in libfort project -# SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -fPIC") set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") set(CMAKE_BUILD_TYPE "Release") -# set(CMAKE_BUILD_TYPE "Debug") -#set(BUILD_SHARED_LIBS ON) if(NOT DEFINED CMD_BUILD) set(SANITIZER OFF) @@ -62,6 +51,11 @@ if(SANITIZER) message("address sanitizer load") endif() +set(USE_GPU OFF) +if (USE_GPU) + add_definitions(-DUSE_GPU) +endif() + include(cmake/setting.cmake) include(cmake/third_party.cmake) include(cmake/operation/ista.cmake) diff --git a/build.sh b/build.sh index 199983bce..1da4d6d4e 100755 --- a/build.sh +++ b/build.sh @@ -123,7 +123,7 @@ install_dependencies_apt() apt-get update && apt-get install -y \ g++-10 cmake ninja-build \ tcl-dev libgflags-dev libgoogle-glog-dev libboost-all-dev libgtest-dev flex\ - libeigen3-dev libyaml-cpp-dev libunwind-dev libmetis-dev libgmp-dev bison rustc cargo\ + libeigen3-dev libunwind-dev libmetis-dev libgmp-dev bison rustc cargo\ libhwloc-dev libcairo2-dev exit 0 else diff --git a/scripts/design/sky130_gcd/iEDA_config/to_default_config_drv.json b/scripts/design/sky130_gcd/iEDA_config/to_default_config_drv.json index 382ba3eba..fecfac806 100644 --- a/scripts/design/sky130_gcd/iEDA_config/to_default_config_drv.json +++ b/scripts/design/sky130_gcd/iEDA_config/to_default_config_drv.json @@ -44,5 +44,6 @@ "number_of_decreasing_slack_iter": 5, "max_allowed_buffering_fanout": 20, "min_divide_fanout": 8, - "optimize_endpoints_percent": 1.0 + "optimize_endpoints_percent": 1.0, + "drv_optimize_iter_number": 5 } \ No newline at end of file diff --git a/scripts/design/sky130_gcd/iEDA_config/to_default_config_hold.json b/scripts/design/sky130_gcd/iEDA_config/to_default_config_hold.json index 43739eafd..a3f69b1b1 100644 --- a/scripts/design/sky130_gcd/iEDA_config/to_default_config_hold.json +++ b/scripts/design/sky130_gcd/iEDA_config/to_default_config_hold.json @@ -44,5 +44,6 @@ "number_of_decreasing_slack_iter": 5, "max_allowed_buffering_fanout": 20, "min_divide_fanout": 8, - "optimize_endpoints_percent": 1.0 + "optimize_endpoints_percent": 1.0, + "drv_optimize_iter_number": 5 } \ No newline at end of file diff --git a/scripts/design/sky130_gcd/iEDA_config/to_default_config_setup.json b/scripts/design/sky130_gcd/iEDA_config/to_default_config_setup.json index 210f77eef..e548178d1 100644 --- a/scripts/design/sky130_gcd/iEDA_config/to_default_config_setup.json +++ b/scripts/design/sky130_gcd/iEDA_config/to_default_config_setup.json @@ -44,5 +44,6 @@ "number_of_decreasing_slack_iter": 5, "max_allowed_buffering_fanout": 20, "min_divide_fanout": 8, - "optimize_endpoints_percent": 1.0 + "optimize_endpoints_percent": 1.0, + "drv_optimize_iter_number": 5 } \ No newline at end of file diff --git a/scripts/design/sky130_gcd/script/DB_script/run_def_to_json_text.tcl b/scripts/design/sky130_gcd/script/DB_script/run_def_to_json_text.tcl index 123883969..3a27002a1 100755 --- a/scripts/design/sky130_gcd/script/DB_script/run_def_to_json_text.tcl +++ b/scripts/design/sky130_gcd/script/DB_script/run_def_to_json_text.tcl @@ -29,7 +29,7 @@ def_init -path [expr {[info exists ::env(INPUT_DEF)]? $::env(INPUT_DEF) : $DEFAU ## Full layer information instance:(-discard li/mcon/nwell/pwell/met/via) ## use (-discard null) to choose all layer #=========================================================== -json_save -path $::env(GDS_JSON_FILE) -discard li +json_save -path $::env(LAYOUT_JSON_FILE) -discard li #=========================================================== ## Exit diff --git a/scripts/design/sky130_gcd/script/iRT_script/run_iRT.tcl b/scripts/design/sky130_gcd/script/iRT_script/run_iRT.tcl index 6415c2a83..e64c88a7a 100755 --- a/scripts/design/sky130_gcd/script/iRT_script/run_iRT.tcl +++ b/scripts/design/sky130_gcd/script/iRT_script/run_iRT.tcl @@ -31,8 +31,8 @@ source $::env(TCL_SCRIPT_DIR)/DB_script/db_init_lef.tcl #=========================================================== ## read def #=========================================================== -set DEFAULT_OUTPUT_DEF "$::env(RESULT_DIR)/iPL_lg_result.def" -def_init -path [expr {[info exists ::env(OUTPUT_DEF)] ? $::env(OUTPUT_DEF) : $DEFAULT_OUTPUT_DEF}] +set DEFAULT_INPUT_DEF "$::env(RESULT_DIR)/iPL_lg_result.def" +def_init -path [expr {[info exists ::env(INPUT_DEF)] ? $::env(INPUT_DEF) : $DEFAULT_INPUT_DEF}] #=========================================================== ## run Router diff --git a/src/database/data/design/db_design/IdbPins.cpp b/src/database/data/design/db_design/IdbPins.cpp index 0787dcfa9..be706539c 100644 --- a/src/database/data/design/db_design/IdbPins.cpp +++ b/src/database/data/design/db_design/IdbPins.cpp @@ -423,11 +423,21 @@ void IdbPin::set_port_vias() for_each(_via_list.begin(), _via_list.end(), [](IdbVia*& via) { delete via; }); _via_list.clear(); - auto cloneVia = [](IdbVia* via, int32_t x_off = 0, int32_t y_off = 0) { + auto cloneVia = [&](IdbVia* via, int32_t x_off = 0, int32_t y_off = 0) { auto* pin_via = via->clone(); auto* coord = pin_via->get_coordinate(); coord->get_x() += x_off; coord->get_y() += y_off; + + if (!is_io_pin()) { + IdbOrientTransform db_transform(_instance->get_orient(), _instance->get_coordinate(), _instance->get_cell_master()->get_width(), + _instance->get_cell_master()->get_height()); + db_transform.transformCoordinate(coord); + } else { + IdbOrientTransform db_transform(this->get_orient(), this->get_location(), 0, 0); + db_transform.transformCoordinate(coord); + } + return pin_via; }; if (is_io_pin()) { diff --git a/src/database/manager/builder/verilog_builder/verilog_read.cpp b/src/database/manager/builder/verilog_builder/verilog_read.cpp index 87775e695..5fc914ca5 100644 --- a/src/database/manager/builder/verilog_builder/verilog_read.cpp +++ b/src/database/manager/builder/verilog_builder/verilog_read.cpp @@ -733,8 +733,11 @@ int32_t RustVerilogRead::build_components() net_name = rust_convert_verilog_id(net_id)->id; } else if (rust_is_bus_index_id(net_id)) { net_name = rust_convert_verilog_index_id(net_id)->id; - } else { + } else if (rust_is_bus_slice_id(net_id)) { net_name = rust_convert_verilog_slice_id(net_id)->id; + } else { + static int index = 0; + net_name = ieda::Str::printf("IEDA_CONST_%d", index++); } add_pin(net_name, idb_pin); } diff --git a/src/database/manager/parser/json/GJWriter.cpp b/src/database/manager/parser/json/GJWriter.cpp index d2a134daf..1973ecad2 100644 --- a/src/database/manager/parser/json/GJWriter.cpp +++ b/src/database/manager/parser/json/GJWriter.cpp @@ -20,7 +20,7 @@ #include // #include "/home/shuyuz/iEDA/src/platform/data_manager/idm.h" #include -#define sref_expension 1 +#define sref_expension 0 namespace idb { JsonTextWriter::JsonTextWriter() @@ -519,9 +519,10 @@ void JsonTextWriter::write_struct_element(JsonElemBase* e,int i,bool out) const case JsonElemType::kPath: write_path(dynamic_cast(e),i+1,out); break; - case JsonElemType::kSref: - write_sref(dynamic_cast(e),i+1,out); - break; + // block sref printing for json + // case JsonElemType::kSref: + // write_sref(dynamic_cast(e),i+1,out); + // break; case JsonElemType::kAref: write_aref(dynamic_cast(e),i+1,out); break; diff --git a/src/database/manager/parser/liberty/LibParserRustC.cc b/src/database/manager/parser/liberty/LibParserRustC.cc index f279c3883..f0d131c48 100644 --- a/src/database/manager/parser/liberty/LibParserRustC.cc +++ b/src/database/manager/parser/liberty/LibParserRustC.cc @@ -22,13 +22,12 @@ * @date 2023-10-13 * */ -#include "LibParserRustC.hh" - #include #include "BTreeMap.hh" #include "BTreeSet.hh" #include "Lib.hh" +#include "LibParserRustC.hh" #include "log/Log.hh" namespace ista { @@ -653,9 +652,14 @@ unsigned RustLibertyReader::visitComplexAttri( if (process_attri.contains(attri_name)) { process_attri[attri_name](); - } else { + } else if (Str::startWith(attri_name, "index") || + Str::equal(attri_name, "values")) { is_ok = visitAxisOrValues(attri); } + else { + LOG_INFO_EVERY_N(10) << "unkown attri name: " << attri_name << " in " + << attri->file_name << " line no " << attri->line_no; + } return is_ok; } @@ -1236,6 +1240,7 @@ unsigned RustLibertyReader::visitGroup(RustLibertyGroupStmt* group) { {"leakage_power", std::bind(&RustLibertyReader::visitLeakagePower, this, _1)}, {"bus", std::bind(&RustLibertyReader::visitBus, this, _1)}, + {"bundle", std::bind(&RustLibertyReader::visitBus, this, _1)}, {"pin", std::bind(&RustLibertyReader::visitPin, this, _1)}, {"timing", std::bind(&RustLibertyReader::visitTiming, this, _1)}, {"internal_power", @@ -1277,13 +1282,12 @@ unsigned RustLibertyReader::readLib() { LOG_INFO << "load liberty file " << _file_name << " success."; return 1; - } /** * @brief link the lib to construct the data. - * - * @return unsigned + * + * @return unsigned */ unsigned RustLibertyReader::linkLib() { LOG_INFO << "link liberty file " << _file_name << " start."; diff --git a/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/grammar/liberty.pest b/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/grammar/liberty.pest index 7b6a296ff..4e24809f4 100644 --- a/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/grammar/liberty.pest +++ b/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/grammar/liberty.pest @@ -24,9 +24,9 @@ multiline_string = !{ "\\"? ~ oneline_string ~ ("," ~ "\\" ~ oneline_string)* } semicolon = _{ ";" } -expr_operator = _{ "+" | "-" | "*" | "/" } +expr_operator = { "+" | "-" | "*" | "/" | "!" } expr_token = ${ float ~ string? | string } -simple_attribute_value = _{ expr_token ~ (expr_operator ~ expr_token)? } +simple_attribute_value = _{ expr_operator? ~ expr_token ~ (expr_operator ~ expr_operator? ~ expr_token)* } id = { lib_id ~ bus_index? ~ (bus_index | bus_slice)? } diff --git a/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/mod.rs b/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/mod.rs index 483d87d99..5bff8d238 100644 --- a/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/mod.rs +++ b/src/database/manager/parser/liberty/lib-rust/liberty-parser/src/liberty_parser/mod.rs @@ -66,6 +66,8 @@ fn process_multiline_string( fn process_string(pair: Pair) -> Result> { let pair_span = pair.as_span(); + // let pair_clone = pair.clone(); + // println!("Rule: {:?}", pair_clone.as_rule()); // println!("Span: {:?}", pair_clone.as_span()); // println!("Text: {}", pair_clone.as_str()); @@ -127,11 +129,28 @@ fn process_simple_attribute( let attribute_value = parser_queue.pop_front().unwrap(); match attribute_value { liberty_data::LibertyParserData::String(s) => { + // maybe more string value as expr. + let mut expr_value = s.get_string_value().to_string(); + while !parser_queue.is_empty() { + let string_value = parser_queue.pop_front().unwrap(); + + match string_value { + liberty_data::LibertyParserData::String(more_str) => { + expr_value = expr_value + more_str.get_string_value(); + } + liberty_data::LibertyParserData::Float(more_str) => { + let the_float_str_value = more_str.get_float_value().to_string(); + expr_value = expr_value + the_float_str_value.as_str(); + } + _ => panic!("should be string type"), + } + } + let simple_stmt = liberty_data::LibertySimpleAttrStmt::new( file_name, line_no, lib_id, - Box::new(s) as Box, + Box::new(liberty_data::LibertyStringValue{value: expr_value}) as Box, ); Ok(liberty_data::LibertyParserData::SimpleStmt(simple_stmt)) } @@ -236,6 +255,7 @@ fn process_pair( parser_queue.push_back(pair_result.unwrap()); } + // let pair_clone = pair.clone(); // println!("Rule: {:?}", pair_clone.as_rule()); // println!("Span: {:?}", pair_clone.as_span()); // println!("Text: {}", pair_clone.as_str()); @@ -248,6 +268,7 @@ fn process_pair( match pair.as_rule() { Rule::float => process_float(pair), Rule::string_text => process_string_text(pair), + Rule::expr_operator => process_string(pair), Rule::id => process_string(pair), Rule::multiline_string => process_multiline_string(&mut substitute_queue), Rule::expr_token => process_expr_token(pair, &mut substitute_queue), @@ -362,7 +383,7 @@ mod tests { Ok(pairs) => { for pair in pairs { let data = process_pair(pair, "tbd", &mut parser_queue); - println!("Error: {:#?}", data); + println!("OK: {:#?}", data); } } Err(err) => { @@ -468,7 +489,7 @@ mod tests { #[test] fn test_parse_simple_attribute() { - let input_str = r#"leakage_power_unit : 1nW;"#; + let input_str = r#"power_down_function : !VDD+!VDDD+VSSD;"#; let parse_result = LibertyParser::parse(Rule::simple_attribute, input_str); test_process_parse_result(parse_result); diff --git a/src/database/manager/parser/spef/SpefParserRustC.hh b/src/database/manager/parser/spef/SpefParserRustC.hh index 6cd406aa2..d6a42c520 100644 --- a/src/database/manager/parser/spef/SpefParserRustC.hh +++ b/src/database/manager/parser/spef/SpefParserRustC.hh @@ -29,8 +29,8 @@ void rust_free_spef_net_cap_res(void*); typedef struct RustSpefCoord { - double _x; - double _y; + double _x = 0.0; + double _y = 0.0; } RustSpefCoord; enum RustConnectionDirection diff --git a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/grammar/grammar.pest b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/grammar/grammar.pest index 4dacde641..7d7e13894 100644 --- a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/grammar/grammar.pest +++ b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/grammar/grammar.pest @@ -11,13 +11,16 @@ header_text = _{ (!"$" ~ ANY)+ } date_text = { header_text } date = _{ "$date" ~ date_text ~ "$end" } +version_text = { header_text } +version = _{ "$version" ~ version_text ~ "$end" } + timescale = _{ "$timescale" ~ scale_text ~ "$end" } comment_text = { header_text } vcd_comment = _{ "$comment" ~ comment_text ~ "$end" } header_section = _{ - date ~ timescale ~ vcd_comment + date ~ version? ~ timescale ~ vcd_comment? } /* definition */ @@ -65,12 +68,12 @@ close_scope = { "$upscope" ~ "$end" } scope = _{ open_scope ~ (scope | variable)+ ~ close_scope } scopes = _{ scope+ } -variable_definition_section = _{ scopes ~ "$enddefinitions" ~ "$end" } +variable_definition_section = _{ scopes ~ "$enddefinitions" ~ "$end" ~ vcd_comment?} /* change */ scalar_num = { "0" | "1" | "x" | "X" | "z" | "Z" } -bin_num_text = { scalar_num+ } +bin_num_text = @{ scalar_num+ } bin_num = _{ ("b" | "B") ~ bin_num_text } real_num = { ("r" | "R") ~ ("-")? ~ ASCII_DIGIT+ ~ (("e" | "E") ~ ("+" | "-")? ~ ASCII_DIGIT+)? @@ -87,7 +90,7 @@ vector_value_change = _{ bitvector_value_change | real_value_change } signal_value_change = _{ scalar_value_change | vector_value_change } value_change = _{ - simulation_time ~ simulation_keyword ~ (signal_value_change)* ~ "$end" + simulation_time? ~ simulation_keyword ~ (signal_value_change)* ~ "$end" | simulation_time ~ (signal_value_change)* } value_change_section = _{ value_change+ } diff --git a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/mod.rs b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/mod.rs index 3df5899ea..25260cb32 100644 --- a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/mod.rs +++ b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/mod.rs @@ -22,6 +22,12 @@ fn process_date(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) vcd_file.set_date(date_text); } +fn process_version(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) { + let version_text = pair.as_str().parse::().unwrap(); + let vcd_file = vcd_file_parser.get_vcd_file(); + vcd_file.set_date(version_text); +} + /// process scale number. fn process_scale_number(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) { let scale_number = pair.as_str().parse::().unwrap(); @@ -63,6 +69,8 @@ fn process_open_scope(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileP let pair_module = inner_pairs.next_back().unwrap(); let module_name = pair_module.as_str(); + println!("scope module: {}", module_name); + let new_scope: Rc> = Rc::new(RefCell::new( vcd_data::VCDScope::new(String::from(module_name)), )); @@ -78,10 +86,12 @@ fn process_open_scope(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileP .set_parent_scope(Rc::clone(&*parent_scope)); parent_scope.borrow_mut().add_child_scope(new_scope); + scope_stack.push_back(new_scope_copy); } else { vcd_file_parser.set_root_scope(new_scope); } + } /// process signal variable. @@ -126,7 +136,10 @@ fn process_variable(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFilePar /// process close scope. fn process_close_scope(_pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) { let scope_stack = vcd_file_parser.get_scope_stack(); - scope_stack.pop_back(); + if !scope_stack.is_empty() { + scope_stack.pop_back(); + } + } /// process simulate time. @@ -146,7 +159,7 @@ fn process_scalar_value_change(pair: Pair, vcd_file_parser: &mut vcd_data: "1" => vcd_data::VCDBit::BitOne, "x" | "X" => vcd_data::VCDBit::BitX, "z" | "Z" => vcd_data::VCDBit::BitZ, - _ => panic!("unkown value"), + _ => panic!("unkown value {}", scalar_value_pair.as_str()), }; let hash_pair = scalar_value_change_pairs.next_back().unwrap(); let hash_str = String::from(hash_pair.as_str()); @@ -165,9 +178,16 @@ fn process_scalar_value_change(pair: Pair, vcd_file_parser: &mut vcd_data: /// process vector value change. fn process_bitvector_value_change(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) { + let line_no = pair.line_col().0; + // let pair_clone = pair.clone(); + // println!("Rule: {:?}", pair_clone.as_rule()); + // println!("Span: {:?}", pair_clone.as_span()); + // println!("Text: {}", pair_clone.as_str()); + let mut bitvector_value_change_pairs = pair.into_inner().into_iter(); let bitvector_value_pair = bitvector_value_change_pairs.next().unwrap(); let bitvector_value_str = bitvector_value_pair.as_str(); + // println!("bitvector_value_str {} len {}", bitvector_value_str,bitvector_value_str.len()); let mut vcd_bit_vec: Vec = Vec::with_capacity(bitvector_value_str.len()); for bit in bitvector_value_str.chars() { @@ -176,7 +196,7 @@ fn process_bitvector_value_change(pair: Pair, vcd_file_parser: &mut vcd_da '1' => vcd_data::VCDBit::BitOne, 'x' | 'X' => vcd_data::VCDBit::BitX, 'z' | 'Z' => vcd_data::VCDBit::BitZ, - _ => panic!("unkown value"), + _ => panic!("unkown value {} in {}", bit, line_no), }; vcd_bit_vec.push(bit_value); @@ -221,14 +241,15 @@ fn process_real_value_change(pair: Pair, vcd_file_parser: &mut vcd_data::V /// process vcd data. fn process_vcd(pair: Pair, vcd_file_parser: &mut vcd_data::VCDFileParser) { - let pair_clone = pair.clone(); - println!("Rule: {:?}", pair_clone.as_rule()); - println!("Span: {:?}", pair_clone.as_span()); - println!("Text: {}", pair_clone.as_str()); + // let pair_clone = pair.clone(); + // println!("Rule: {:?}", pair_clone.as_rule()); + // println!("Span: {:?}", pair_clone.as_span()); + // println!("Text: {}", pair_clone.as_str()); for inner_pair in pair.into_inner() { match inner_pair.as_rule() { Rule::date_text => process_date(inner_pair, vcd_file_parser), + Rule::version_text => process_version(inner_pair, vcd_file_parser), Rule::scale_text => process_scale(inner_pair, vcd_file_parser), Rule::comment_text => process_comment(inner_pair, vcd_file_parser), Rule::open_scope => process_open_scope(inner_pair, vcd_file_parser), diff --git a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_calc_tc_sp.rs b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_calc_tc_sp.rs index f1db69414..703edf788 100644 --- a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_calc_tc_sp.rs +++ b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_calc_tc_sp.rs @@ -74,14 +74,19 @@ pub trait VcdCounter { return false; } + let default_bit_value = VCDBit::BitZero; + let pre_bit_value = match &pre_time_value.value { VCDValue::BitScalar(bit) => Ok(bit), - VCDValue::BitVector(vec) => { - if let Some(index) = bus_index { - Ok(&vec[index as usize]) + VCDValue::BitVector(bit_vec) => { + let index = bus_index.unwrap() as usize; + + let bit_value = if index < bit_vec.len() { + &bit_vec[index as usize] } else { - Err("No bus index provided") - } + &default_bit_value + }; + Ok(bit_value) } _ => Err("Unmatched value"), } @@ -89,12 +94,15 @@ pub trait VcdCounter { let cur_bit_value = match &cur_time_value.value { VCDValue::BitScalar(bit) => Ok(bit), - VCDValue::BitVector(vec) => { - if let Some(index) = bus_index { - Ok(&vec[index as usize]) + VCDValue::BitVector(bit_vec) => { + let index = bus_index.unwrap() as usize; + + let bit_value = if index < bit_vec.len() { + &bit_vec[index as usize] } else { - Err("No bus index provided") - } + &default_bit_value + }; + Ok(bit_value) } _ => Err("Unmatched value"), } @@ -328,6 +336,7 @@ impl<'a> VcdBusCounter<'a> { let signal_time_values = self.vcd_file.get_signal_values().get(signal_hash); let signal_name = self.signal.get_name().to_string(); + // println!("signal name {}", signal_name); // count the toggle, if current signal value is rise transition or fall // transition, count add one. diff --git a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_data.rs b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_data.rs index 866f031bb..073146e37 100644 --- a/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_data.rs +++ b/src/database/manager/parser/vcd/vcd_parser/src/vcd_parser/vcd_data.rs @@ -45,10 +45,22 @@ impl VCDValue { } pub fn get_vector_bit(&self, index: usize) -> VCDBit { + match self { - VCDValue::BitVector(vec) => vec[index], + VCDValue::BitVector(bit_vec) => { + let default_bit_value = VCDBit::BitZero; + let bit_value = if index < bit_vec.len() { + bit_vec[index as usize] + } else { + default_bit_value + }; + + bit_value + } _ => panic!("Not a BitVector"), } + + } } @@ -333,6 +345,10 @@ impl VCDFile { self.date = date_text; } + pub fn set_version(&mut self, version_text: String) { + self.version = version_text; + } + pub fn set_time_unit(&mut self, time_unit: &str) { match time_unit { "s" => self.time_unit = VCDTimeUnit::UnitSecond, diff --git a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest index e3ab15f2b..0f5fe5e90 100644 --- a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest +++ b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest @@ -4,7 +4,7 @@ range_from = { decimal_digits+ } range_to = { decimal_digits+ } bus_slice = { "[" ~ range_from ~ ":" ~ range_to ~ "]" } -scalar_constant = { "1'b0" | "1'b1" | "1'B0" | "1'B1" | "'b0" | "'b1" | "'B0" | "'B1" | "1" | "0" } +scalar_constant = { "1'b0" | "1'b1" | "1'B0" | "1'B1" | "'b0" | "'b1" | "'B0" | "'B1" | "1" | "0" | "2'b00"} line_comment = _{ "//" ~ (!("\n") ~ ASCII)* ~ ("\n" | EOI) } multiline_comment = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" } diff --git a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/mod.rs b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/mod.rs index 93cd6a644..a28e4b378 100644 --- a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/mod.rs +++ b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/mod.rs @@ -325,6 +325,13 @@ fn process_first_port_connection_single_connect( } } +fn extract_bitwidth_value(input: &str) -> Option<(u32, String)> { + // Split the input string by the character `'` and collect into a tuple(2'b00->(2,b'00)) + input.split_once('\'').and_then(|(bw, val)| { + bw.parse::().ok().map(|bit_width| (bit_width, val.to_string())) + }) +} + fn process_first_port_connection_multiple_connect( pair: Pair, ) -> Result, pest::error::Error> { @@ -338,8 +345,13 @@ fn process_first_port_connection_multiple_connect( Rule::scalar_constant => { let net_connect_line_no = inner_pair.line_col().0; let net_connect = inner_pair.as_str(); - let verilog_id = verilog_data::VerilogID::new(net_connect); - let verilog_virtual_base_id: Box = Box::new(verilog_id); + let verilog_constant_id: verilog_data::VerilogConstantID; + if let Some((bit_width, value)) = extract_bitwidth_value(net_connect) { + verilog_constant_id = verilog_data::VerilogConstantID::new(bit_width, &value); + } else { + panic!("Error: invalid format"); + } + let verilog_virtual_base_id: Box = Box::new(verilog_constant_id); let verilog_net_constant_expr = verilog_data::VerilogConstantExpr::new(net_connect_line_no, verilog_virtual_base_id); let verilog_virtual_base_net_expr: Box = diff --git a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/verilog_data.rs b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/verilog_data.rs index f2af3c4f8..29be5527c 100644 --- a/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/verilog_data.rs +++ b/src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/verilog_data.rs @@ -16,6 +16,10 @@ pub trait VerilogVirtualBaseID: Debug + VerilogVirtualBaseIDClone { false } + fn is_constant_id(&self) -> bool { + false + } + fn get_name(&self) -> &str { panic!("This is unknown value."); } @@ -213,6 +217,56 @@ impl VerilogVirtualBaseID for VerilogSliceID { } } +#[derive(Debug, Clone)] +pub struct VerilogConstantID { + bit_width: u32, + value: VerilogID, + formatted_constant_id: String, +} + +impl VerilogConstantID { + pub fn new(bit_width: u32, value: &str) -> VerilogConstantID { + let formatted_constant_id = format!("{}'{}", bit_width, value); + VerilogConstantID { + bit_width: bit_width, + value: VerilogID::new(value), + formatted_constant_id: formatted_constant_id, + } + } + + pub fn get_bit_width(&self) -> u32 { + self.bit_width + } + + pub fn get_value(&self) -> &VerilogID { + &self.value + } +} + +impl VerilogVirtualBaseID for VerilogConstantID { + fn is_constant_id(&self) -> bool { + true + } + + fn get_name(&self) -> &str { + &self.formatted_constant_id + } + + fn get_base_name(&self) -> &str { + &self.value.get_base_name() + } + + + fn set_base_name(&mut self, id: &str) { + self.value.set_base_name(id); + self.formatted_constant_id = format!("{}'{}", self.bit_width,self.value.get_base_name()); + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + pub trait VerilogVirtualBaseNetExpr: Debug + VerilogVirtualBaseNetExprClone { fn is_id_expr(&self) -> bool { false @@ -534,12 +588,23 @@ impl VerilogInst { // bus_range_max is the bus max beyond range. let mut bus_range_max = std::cmp::max(port_bus_wide_range.unwrap().0, port_bus_wide_range.unwrap().1) + 1; + let mut const_net_bit_index: Option = None; let mut net_index: Option = None; let mut connect_net_expr: Option> = None; for expr_net in concat_expr_nets { if expr_net.get_verilog_id().is_bus_index_id() { bus_range_max -= 1; + } else if expr_net.get_verilog_id().is_constant_id() { + let mut bit_width = expr_net.get_verilog_id().as_any().downcast_ref::().unwrap().get_bit_width(); + while bit_width > 0 { + bus_range_max -= 1; + if bus_range_max == port_index { + const_net_bit_index = Some(bit_width-1); + break; + } + bit_width -= 1; + } } else if expr_net.get_verilog_id().is_bus_slice_id() { let slice_id = expr_net.get_verilog_id().as_any().downcast_ref::().unwrap(); let from = slice_id.get_range_from(); @@ -617,6 +682,17 @@ impl VerilogInst { let net_id_expr = VerilogNetIDExpr::new(0, dyn_index_verilog_id); let dyn_net_id_expr: Box = Box::new(net_id_expr); dyn_net_id_expr + } else if let Some(const_net_bit_index) = const_net_bit_index { + let connect_net_id = connect_net_expr.as_ref().unwrap().get_verilog_id(); + let net_value = connect_net_id.get_base_name(); + let new_net_value = &net_value[1..]; + let bit_value = new_net_value.chars().nth(const_net_bit_index as usize).unwrap(); + let value= format!("{}{}", 'b', bit_value); + let const_verilog_id = VerilogConstantID::new(1, &value); + let dyn_const_verilog_id: Box = Box::new(const_verilog_id); + let net_id_expr = VerilogConstantExpr::new(0, dyn_const_verilog_id); + let dyn_net_id_expr: Box = Box::new(net_id_expr); + dyn_net_id_expr } else { connect_net_expr.as_ref().unwrap().clone() } diff --git a/src/evaluation/CMakeLists.txt b/src/evaluation/CMakeLists.txt index 0d941d927..76bd5c498 100644 --- a/src/evaluation/CMakeLists.txt +++ b/src/evaluation/CMakeLists.txt @@ -9,6 +9,6 @@ set(EVAL_SOURCE ${HOME_EVALUATION}/src) ## build add_subdirectory(${EVAL_API}) -add_subdirectory(${EVAL_APPS}) +# add_subdirectory(${EVAL_APPS}) add_subdirectory(${EVAL_DATA}) add_subdirectory(${EVAL_SOURCE}) diff --git a/src/evaluation/api/CMakeLists.txt b/src/evaluation/api/CMakeLists.txt index e874b2c08..e79dfe43d 100644 --- a/src/evaluation/api/CMakeLists.txt +++ b/src/evaluation/api/CMakeLists.txt @@ -68,3 +68,21 @@ target_include_directories(eval_wirelength_api PUBLIC ${EVAL_API} ) + + +# union API +add_library(eval_union_api + ${EVAL_API}/union_api.cpp +) + +target_link_libraries(eval_union_api + PRIVATE + eval_util_init_flute + eval_util_init_egr + eval_util_init_idb +) + +target_include_directories(eval_union_api + PUBLIC + ${EVAL_DATA} +) diff --git a/src/evaluation/api/congestion_api.cpp b/src/evaluation/api/congestion_api.cpp index 925134fef..62d6c2f41 100644 --- a/src/evaluation/api/congestion_api.cpp +++ b/src/evaluation/api/congestion_api.cpp @@ -40,96 +40,120 @@ void CongestionAPI::destroyInst() } } -EGRMapSummary CongestionAPI::egrMap() +EGRMapSummary CongestionAPI::egrMap(std::string stage) { - return egrMap(EVAL_CONGESTION_INST->getEGRDirPath()); + return egrMap(stage, EVAL_CONGESTION_INST->getEGRDirPath()); } -EGRMapSummary CongestionAPI::egrMap(std::string rt_dir_path) +EGRMapSummary CongestionAPI::egrMapPure(std::string stage) +{ + return egrMapPure(stage, EVAL_CONGESTION_INST->getEGRDirPath()); +} + +EGRMapSummary CongestionAPI::egrMap(std::string stage, std::string rt_dir_path) { EGRMapSummary egr_map_summary; EVAL_CONGESTION_INST->initEGR(); - egr_map_summary.horizontal_sum = EVAL_CONGESTION_INST->evalHoriEGR(rt_dir_path); - egr_map_summary.vertical_sum = EVAL_CONGESTION_INST->evalVertiEGR(rt_dir_path); - egr_map_summary.union_sum = EVAL_CONGESTION_INST->evalUnionEGR(rt_dir_path); + egr_map_summary.horizontal_sum = EVAL_CONGESTION_INST->evalHoriEGR(stage, rt_dir_path); + egr_map_summary.vertical_sum = EVAL_CONGESTION_INST->evalVertiEGR(stage, rt_dir_path); + egr_map_summary.union_sum = EVAL_CONGESTION_INST->evalUnionEGR(stage, rt_dir_path); EVAL_CONGESTION_INST->destroyEGR(); return egr_map_summary; } -RUDYMapSummary CongestionAPI::rudyMap(int32_t grid_size) +EGRMapSummary CongestionAPI::egrMapPure(std::string stage, std::string rt_dir_path) +{ + EGRMapSummary egr_map_summary; + + egr_map_summary.horizontal_sum = EVAL_CONGESTION_INST->evalHoriEGR(stage, rt_dir_path); + egr_map_summary.vertical_sum = EVAL_CONGESTION_INST->evalVertiEGR(stage, rt_dir_path); + egr_map_summary.union_sum = EVAL_CONGESTION_INST->evalUnionEGR(stage, rt_dir_path); + + return egr_map_summary; +} + +RUDYMapSummary CongestionAPI::rudyMap(std::string stage, int32_t grid_size) { RUDYMapSummary rudy_map_summary; EVAL_CONGESTION_INST->initIDB(); - rudy_map_summary = rudyMap(EVAL_CONGESTION_INST->getCongestionNets(), EVAL_CONGESTION_INST->getCongestionRegion(), + rudy_map_summary = rudyMap(stage, EVAL_CONGESTION_INST->getCongestionNets(), EVAL_CONGESTION_INST->getCongestionRegion(), grid_size * EVAL_CONGESTION_INST->getRowHeight()); EVAL_CONGESTION_INST->destroyIDB(); return rudy_map_summary; } -RUDYMapSummary CongestionAPI::rudyMap(CongestionNets nets, CongestionRegion region, int32_t grid_size) +RUDYMapSummary CongestionAPI::rudyMapPure(std::string stage, int32_t grid_size) +{ + RUDYMapSummary rudy_map_summary; + rudy_map_summary = rudyMap(stage, EVAL_CONGESTION_INST->getCongestionNets(), EVAL_CONGESTION_INST->getCongestionRegion(), + grid_size * EVAL_CONGESTION_INST->getRowHeight()); + return rudy_map_summary; +} + +RUDYMapSummary CongestionAPI::rudyMap(std::string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { RUDYMapSummary rudy_map_summary; - rudy_map_summary.rudy_horizontal = EVAL_CONGESTION_INST->evalHoriRUDY(nets, region, grid_size); - rudy_map_summary.rudy_vertical = EVAL_CONGESTION_INST->evalVertiRUDY(nets, region, grid_size); - rudy_map_summary.rudy_union = EVAL_CONGESTION_INST->evalUnionRUDY(nets, region, grid_size); + rudy_map_summary.rudy_horizontal = EVAL_CONGESTION_INST->evalHoriRUDY(stage, nets, region, grid_size); + rudy_map_summary.rudy_vertical = EVAL_CONGESTION_INST->evalVertiRUDY(stage, nets, region, grid_size); + rudy_map_summary.rudy_union = EVAL_CONGESTION_INST->evalUnionRUDY(stage, nets, region, grid_size); - rudy_map_summary.lutrudy_horizontal = EVAL_CONGESTION_INST->evalHoriLUTRUDY(nets, region, grid_size); - rudy_map_summary.lutrudy_vertical = EVAL_CONGESTION_INST->evalVertiLUTRUDY(nets, region, grid_size); - rudy_map_summary.lutrudy_union = EVAL_CONGESTION_INST->evalUnionLUTRUDY(nets, region, grid_size); + rudy_map_summary.lutrudy_horizontal = EVAL_CONGESTION_INST->evalHoriLUTRUDY(stage, nets, region, grid_size); + rudy_map_summary.lutrudy_vertical = EVAL_CONGESTION_INST->evalVertiLUTRUDY(stage, nets, region, grid_size); + rudy_map_summary.lutrudy_union = EVAL_CONGESTION_INST->evalUnionLUTRUDY(stage, nets, region, grid_size); return rudy_map_summary; } -OverflowSummary CongestionAPI::egrOverflow() +OverflowSummary CongestionAPI::egrOverflow(std::string stage) { - return egrOverflow(EVAL_CONGESTION_INST->getEGRDirPath()); + return egrOverflow(stage, EVAL_CONGESTION_INST->getEGRDirPath()); } -OverflowSummary CongestionAPI::egrOverflow(std::string rt_dir_path) +OverflowSummary CongestionAPI::egrOverflow(std::string stage, std::string rt_dir_path) { OverflowSummary overflow_summary; - overflow_summary.total_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriTotalOverflow(rt_dir_path); - overflow_summary.total_overflow_vertical = EVAL_CONGESTION_INST->evalVertiTotalOverflow(rt_dir_path); - overflow_summary.total_overflow_union = EVAL_CONGESTION_INST->evalUnionTotalOverflow(rt_dir_path); + overflow_summary.total_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriTotalOverflow(stage, rt_dir_path); + overflow_summary.total_overflow_vertical = EVAL_CONGESTION_INST->evalVertiTotalOverflow(stage, rt_dir_path); + overflow_summary.total_overflow_union = EVAL_CONGESTION_INST->evalUnionTotalOverflow(stage, rt_dir_path); - overflow_summary.max_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriMaxOverflow(rt_dir_path); - overflow_summary.max_overflow_vertical = EVAL_CONGESTION_INST->evalVertiMaxOverflow(rt_dir_path); - overflow_summary.max_overflow_union = EVAL_CONGESTION_INST->evalUnionMaxOverflow(rt_dir_path); + overflow_summary.max_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriMaxOverflow(stage, rt_dir_path); + overflow_summary.max_overflow_vertical = EVAL_CONGESTION_INST->evalVertiMaxOverflow(stage, rt_dir_path); + overflow_summary.max_overflow_union = EVAL_CONGESTION_INST->evalUnionMaxOverflow(stage, rt_dir_path); - overflow_summary.weighted_average_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriAvgOverflow(rt_dir_path); - overflow_summary.weighted_average_overflow_vertical = EVAL_CONGESTION_INST->evalVertiAvgOverflow(rt_dir_path); - overflow_summary.weighted_average_overflow_union = EVAL_CONGESTION_INST->evalUnionAvgOverflow(rt_dir_path); + overflow_summary.weighted_average_overflow_horizontal = EVAL_CONGESTION_INST->evalHoriAvgOverflow(stage, rt_dir_path); + overflow_summary.weighted_average_overflow_vertical = EVAL_CONGESTION_INST->evalVertiAvgOverflow(stage, rt_dir_path); + overflow_summary.weighted_average_overflow_union = EVAL_CONGESTION_INST->evalUnionAvgOverflow(stage, rt_dir_path); return overflow_summary; } -UtilizationSummary CongestionAPI::rudyUtilization(bool use_lut) +UtilizationSummary CongestionAPI::rudyUtilization(std::string stage, bool use_lut) { UtilizationSummary utilization_summary; std::string rudy_dir_path = EVAL_CONGESTION_INST->getDefaultOutputDir() + "/RUDY_map"; - utilization_summary = rudyUtilization(rudy_dir_path, use_lut); + utilization_summary = rudyUtilization(stage, rudy_dir_path, use_lut); return utilization_summary; } -UtilizationSummary CongestionAPI::rudyUtilization(std::string rudy_dir_path, bool use_lut) +UtilizationSummary CongestionAPI::rudyUtilization(std::string stage, std::string rudy_dir_path, bool use_lut) { UtilizationSummary utilization_summary; - utilization_summary.max_utilization_horizontal = EVAL_CONGESTION_INST->evalHoriMaxUtilization(rudy_dir_path, use_lut); - utilization_summary.max_utilization_vertical = EVAL_CONGESTION_INST->evalVertiMaxUtilization(rudy_dir_path, use_lut); - utilization_summary.max_utilization_union = EVAL_CONGESTION_INST->evalUnionMaxUtilization(rudy_dir_path, use_lut); + utilization_summary.max_utilization_horizontal = EVAL_CONGESTION_INST->evalHoriMaxUtilization(stage, rudy_dir_path, use_lut); + utilization_summary.max_utilization_vertical = EVAL_CONGESTION_INST->evalVertiMaxUtilization(stage, rudy_dir_path, use_lut); + utilization_summary.max_utilization_union = EVAL_CONGESTION_INST->evalUnionMaxUtilization(stage, rudy_dir_path, use_lut); - utilization_summary.weighted_average_utilization_horizontal = EVAL_CONGESTION_INST->evalHoriAvgUtilization(rudy_dir_path, use_lut); - utilization_summary.weighted_average_utilization_vertical = EVAL_CONGESTION_INST->evalVertiAvgUtilization(rudy_dir_path, use_lut); - utilization_summary.weighted_average_utilization_union = EVAL_CONGESTION_INST->evalUnionAvgUtilization(rudy_dir_path, use_lut); + utilization_summary.weighted_average_utilization_horizontal = EVAL_CONGESTION_INST->evalHoriAvgUtilization(stage, rudy_dir_path, use_lut); + utilization_summary.weighted_average_utilization_vertical = EVAL_CONGESTION_INST->evalVertiAvgUtilization(stage, rudy_dir_path, use_lut); + utilization_summary.weighted_average_utilization_union = EVAL_CONGESTION_INST->evalUnionAvgUtilization(stage, rudy_dir_path, use_lut); return utilization_summary; } @@ -141,6 +165,11 @@ void CongestionAPI::evalNetInfo() EVAL_CONGESTION_INST->destroyIDB(); } +void CongestionAPI::evalNetInfoPure() +{ + EVAL_CONGESTION_INST->evalNetInfo(); +} + int CongestionAPI::findPinNumber(std::string net_name) { return EVAL_CONGESTION_INST->findPinNumber(net_name); @@ -156,4 +185,49 @@ float CongestionAPI::findLness(std::string net_name) return EVAL_CONGESTION_INST->findLness(net_name); } +int32_t CongestionAPI::findBBoxWidth(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxWidth(net_name); +} + +int32_t CongestionAPI::findBBoxHeight(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxHeight(net_name); +} + +int64_t CongestionAPI::findBBoxArea(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxArea(net_name); +} + +int32_t CongestionAPI::findBBoxLx(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxLx(net_name); +} + +int32_t CongestionAPI::findBBoxLy(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxLy(net_name); +} + +int32_t CongestionAPI::findBBoxUx(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxUx(net_name); +} + +int32_t CongestionAPI::findBBoxUy(std::string net_name) +{ + return EVAL_CONGESTION_INST->findBBoxUy(net_name); +} + +std::string CongestionAPI::egrUnionMap(std::string stage, std::string rt_dir_path) +{ + EVAL_CONGESTION_INST->setEGRDirPath(rt_dir_path + "/rt/rt_temp_directory"); + EVAL_CONGESTION_INST->initEGR(); + std::string union_egr_map_path = EVAL_CONGESTION_INST->evalUnionEGR(stage, rt_dir_path + "/rt/rt_temp_directory"); + EVAL_CONGESTION_INST->destroyEGR(); + + return union_egr_map_path; +} + } // namespace ieval diff --git a/src/evaluation/api/congestion_api.h b/src/evaluation/api/congestion_api.h index 7adebcd37..7f4fac64d 100644 --- a/src/evaluation/api/congestion_api.h +++ b/src/evaluation/api/congestion_api.h @@ -21,20 +21,33 @@ class CongestionAPI static CongestionAPI* getInst(); static void destroyInst(); - EGRMapSummary egrMap(); - OverflowSummary egrOverflow(); - RUDYMapSummary rudyMap(int32_t grid_size = 1); - UtilizationSummary rudyUtilization(bool use_lut = false); + EGRMapSummary egrMap(std::string stage); + EGRMapSummary egrMapPure(std::string stage); + OverflowSummary egrOverflow(std::string stage); + RUDYMapSummary rudyMap(std::string stage, int32_t grid_size = 1); + RUDYMapSummary rudyMapPure(std::string stage, int32_t grid_size = 1); + UtilizationSummary rudyUtilization(std::string stage, bool use_lut = false); - EGRMapSummary egrMap(std::string rt_dir_path); - OverflowSummary egrOverflow(std::string rt_dir_path); - RUDYMapSummary rudyMap(CongestionNets congestion_nets, CongestionRegion region, int32_t grid_size); - UtilizationSummary rudyUtilization(std::string rudy_dir_path, bool use_lut = false); + EGRMapSummary egrMap(std::string stage, std::string rt_dir_path); + EGRMapSummary egrMapPure(std::string stage, std::string rt_dir_path); + OverflowSummary egrOverflow(std::string stage, std::string rt_dir_path); + RUDYMapSummary rudyMap(std::string stage, CongestionNets congestion_nets, CongestionRegion region, int32_t grid_size); + UtilizationSummary rudyUtilization(std::string stage, std::string rudy_dir_path, bool use_lut = false); void evalNetInfo(); + void evalNetInfoPure(); int findPinNumber(std::string net_name); int findAspectRatio(std::string net_name); float findLness(std::string net_name); + int32_t findBBoxWidth(std::string net_name); + int32_t findBBoxHeight(std::string net_name); + int64_t findBBoxArea(std::string net_name); + int32_t findBBoxLx(std::string net_name); + int32_t findBBoxLy(std::string net_name); + int32_t findBBoxUx(std::string net_name); + int32_t findBBoxUy(std::string net_name); + + std::string egrUnionMap(std::string stage, std::string rt_dir_path); private: static CongestionAPI* _congestion_api_inst; diff --git a/src/evaluation/api/density_api.cpp b/src/evaluation/api/density_api.cpp index 52c1738a0..9e0897266 100644 --- a/src/evaluation/api/density_api.cpp +++ b/src/evaluation/api/density_api.cpp @@ -40,87 +40,96 @@ void DensityAPI::destroyInst() } } -DensityMapSummary DensityAPI::densityMap(int32_t grid_size, bool neighbor) +DensityMapSummary DensityAPI::densityMap(std::string stage, int32_t grid_size, bool neighbor) { DensityMapSummary density_map_summary; EVAL_DENSITY_INST->initIDB(); - density_map_summary.cell_map_summary = cellDensityMap(grid_size); - density_map_summary.pin_map_summary = pinDensityMap(grid_size, neighbor); - density_map_summary.net_map_summary = netDensityMap(grid_size, neighbor); + density_map_summary.cell_map_summary = cellDensityMap(stage, grid_size); + density_map_summary.pin_map_summary = pinDensityMap(stage, grid_size, neighbor); + density_map_summary.net_map_summary = netDensityMap(stage, grid_size, neighbor); EVAL_DENSITY_INST->destroyIDB(); return density_map_summary; } -CellMapSummary DensityAPI::cellDensityMap(int32_t grid_size) +DensityMapSummary DensityAPI::densityMapPure(std::string stage, int32_t grid_size, bool neighbor) +{ + DensityMapSummary density_map_summary; + density_map_summary.cell_map_summary = cellDensityMap(stage, grid_size); + density_map_summary.pin_map_summary = pinDensityMap(stage, grid_size, neighbor); + density_map_summary.net_map_summary = netDensityMap(stage, grid_size, neighbor); + return density_map_summary; +} + +CellMapSummary DensityAPI::cellDensityMap(std::string stage, int32_t grid_size) { CellMapSummary cell_map_summary; EVAL_DENSITY_INST->initIDBRegion(); EVAL_DENSITY_INST->initIDBCells(); cell_map_summary = cellDensityMap(EVAL_DENSITY_INST->getDensityCells(), EVAL_DENSITY_INST->getDensityRegion(), - grid_size * EVAL_DENSITY_INST->getRowHeight()); + grid_size * EVAL_DENSITY_INST->getRowHeight(), stage); return cell_map_summary; } -PinMapSummary DensityAPI::pinDensityMap(int32_t grid_size, bool neighbor) +PinMapSummary DensityAPI::pinDensityMap(std::string stage, int32_t grid_size, bool neighbor) { PinMapSummary pin_map_summary; EVAL_DENSITY_INST->initIDBRegion(); EVAL_DENSITY_INST->initIDBCells(); pin_map_summary = pinDensityMap(EVAL_DENSITY_INST->getDensityPins(), EVAL_DENSITY_INST->getDensityRegion(), - grid_size * EVAL_DENSITY_INST->getRowHeight(), neighbor); + grid_size * EVAL_DENSITY_INST->getRowHeight(), stage, neighbor); return pin_map_summary; } -NetMapSummary DensityAPI::netDensityMap(int32_t grid_size, bool neighbor) +NetMapSummary DensityAPI::netDensityMap(std::string stage, int32_t grid_size, bool neighbor) { NetMapSummary net_map_summary; EVAL_DENSITY_INST->initIDBRegion(); EVAL_DENSITY_INST->initIDBNets(); net_map_summary = netDensityMap(EVAL_DENSITY_INST->getDensityNets(), EVAL_DENSITY_INST->getDensityRegion(), - grid_size * EVAL_DENSITY_INST->getRowHeight(), neighbor); + grid_size * EVAL_DENSITY_INST->getRowHeight(), stage, neighbor); return net_map_summary; } -CellMapSummary DensityAPI::cellDensityMap(DensityCells cells, DensityRegion region, int32_t grid_size) +CellMapSummary DensityAPI::cellDensityMap(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage) { CellMapSummary cell_map_summary; DensityEval density_eval; - cell_map_summary.macro_density = density_eval.evalMacroDensity(cells, region, grid_size); - cell_map_summary.stdcell_density = density_eval.evalStdCellDensity(cells, region, grid_size); - cell_map_summary.allcell_density = density_eval.evalAllCellDensity(cells, region, grid_size); + cell_map_summary.macro_density = density_eval.evalMacroDensity(cells, region, grid_size, stage); + cell_map_summary.stdcell_density = density_eval.evalStdCellDensity(cells, region, grid_size, stage); + cell_map_summary.allcell_density = density_eval.evalAllCellDensity(cells, region, grid_size, stage); return cell_map_summary; } -PinMapSummary DensityAPI::pinDensityMap(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor) +PinMapSummary DensityAPI::pinDensityMap(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { PinMapSummary pin_map_summary; DensityEval density_eval; - pin_map_summary.macro_pin_density = density_eval.evalMacroPinDensity(pins, region, grid_size, neighbor); - pin_map_summary.stdcell_pin_density = density_eval.evalStdCellPinDensity(pins, region, grid_size, neighbor); - pin_map_summary.allcell_pin_density = density_eval.evalAllCellPinDensity(pins, region, grid_size, neighbor); + pin_map_summary.macro_pin_density = density_eval.evalMacroPinDensity(pins, region, grid_size, stage, neighbor); + pin_map_summary.stdcell_pin_density = density_eval.evalStdCellPinDensity(pins, region, grid_size, stage, neighbor); + pin_map_summary.allcell_pin_density = density_eval.evalAllCellPinDensity(pins, region, grid_size, stage, neighbor); return pin_map_summary; } -NetMapSummary DensityAPI::netDensityMap(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor) +NetMapSummary DensityAPI::netDensityMap(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { NetMapSummary net_map_summary; DensityEval density_eval; - net_map_summary.local_net_density = density_eval.evalLocalNetDensity(nets, region, grid_size, neighbor); - net_map_summary.global_net_density = density_eval.evalGlobalNetDensity(nets, region, grid_size, neighbor); - net_map_summary.allnet_density = density_eval.evalAllNetDensity(nets, region, grid_size, neighbor); + net_map_summary.local_net_density = density_eval.evalLocalNetDensity(nets, region, grid_size, stage, neighbor); + net_map_summary.global_net_density = density_eval.evalGlobalNetDensity(nets, region, grid_size, stage, neighbor); + net_map_summary.allnet_density = density_eval.evalAllNetDensity(nets, region, grid_size, stage, neighbor); return net_map_summary; } diff --git a/src/evaluation/api/density_api.h b/src/evaluation/api/density_api.h index c1e3257ca..635704a29 100644 --- a/src/evaluation/api/density_api.h +++ b/src/evaluation/api/density_api.h @@ -20,14 +20,15 @@ class DensityAPI static DensityAPI* getInst(); static void destroyInst(); - DensityMapSummary densityMap(int32_t grid_size = 1, bool neighbor = false); - CellMapSummary cellDensityMap(int32_t grid_size = 1); - PinMapSummary pinDensityMap(int32_t grid_size = 1, bool neighbor = false); - NetMapSummary netDensityMap(int32_t grid_size = 1, bool neighbor = false); + DensityMapSummary densityMap(std::string stage, int32_t grid_size = 1, bool neighbor = false); + DensityMapSummary densityMapPure(std::string stage, int32_t grid_size = 1, bool neighbor = false); + CellMapSummary cellDensityMap(std::string stage, int32_t grid_size = 1); + PinMapSummary pinDensityMap(std::string stage, int32_t grid_size = 1, bool neighbor = false); + NetMapSummary netDensityMap(std::string stage, int32_t grid_size = 1, bool neighbor = false); - CellMapSummary cellDensityMap(DensityCells cells, DensityRegion region, int32_t grid_size); - PinMapSummary pinDensityMap(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor); - NetMapSummary netDensityMap(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor); + CellMapSummary cellDensityMap(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage); + PinMapSummary pinDensityMap(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); + NetMapSummary netDensityMap(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); MacroMarginSummary macroMarginMap(int32_t grid_size = 1); MacroMarginSummary macroMarginMap(DensityCells cells, DensityRegion die, DensityRegion core, int32_t grid_size); diff --git a/src/evaluation/api/timing_api.cc b/src/evaluation/api/timing_api.cc index 7347fb515..1606138b4 100644 --- a/src/evaluation/api/timing_api.cc +++ b/src/evaluation/api/timing_api.cc @@ -29,6 +29,11 @@ void TimingAPI::runSTA() EVAL_STA_INST->runSTA(); } +void TimingAPI::evalTiming(const std::string& routing_type, const bool& rt_done) +{ + EVAL_STA_INST->evalTiming(routing_type, rt_done); +} + void TimingAPI::destroyInst() { ieval::TimingEval::destroyInst(); @@ -94,4 +99,9 @@ void TimingAPI::updateTiming(const std::vector& timing_net_list, con EVAL_STA_INST->updateTiming(timing_net_list, name_list, propagation_level, dbu_unit); } +bool TimingAPI::isClockNet(const std::string& net_name) const +{ + return EVAL_STA_INST->isClockNet(net_name); +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/api/timing_api.hh b/src/evaluation/api/timing_api.hh index 5998a301c..dbeb2c056 100644 --- a/src/evaluation/api/timing_api.hh +++ b/src/evaluation/api/timing_api.hh @@ -24,7 +24,8 @@ class TimingAPI static TimingAPI* getInst(); - static void runSTA(); + void runSTA(); + void evalTiming(const std::string& routing_type, const bool& rt_done = false); static void destroyInst(); @@ -45,6 +46,8 @@ class TimingAPI void updateTiming(const std::vector& timing_net_list, const std::vector& name_list, const int& propagation_level, int32_t dbu_unit); + bool isClockNet(const std::string& net_name) const; + private: static TimingAPI* _timing_api; }; diff --git a/src/evaluation/api/union_api.cpp b/src/evaluation/api/union_api.cpp new file mode 100644 index 000000000..4b56ae4eb --- /dev/null +++ b/src/evaluation/api/union_api.cpp @@ -0,0 +1,79 @@ +/* + * @FilePath: union_api.cpp + * @Author: Yihang Qiu (qiuyihang23@mails.ucas.ac.cn) + * @Date: 2024-10-11 15:37:27 + * @Description: + */ + +#include "union_api.h" + +#include "init_egr.h" +#include "init_flute.h" +#include "init_idb.h" + +namespace ieval { + +#define UNION_EVAL_INIT_IDB_INST (ieval::InitIDB::getInst()) +#define UNION_EVAL_INIT_FLUTE_INST (ieval::InitFlute::getInst()) +#define UNION_EVAL_INIT_EGR_INST (ieval::InitEGR::getInst()) + +UnionAPI* UnionAPI::_union_api_inst = nullptr; + +UnionAPI::UnionAPI() +{ +} + +UnionAPI::~UnionAPI() +{ +} + +UnionAPI* UnionAPI::getInst() +{ + if (_union_api_inst == nullptr) { + _union_api_inst = new UnionAPI(); + } + + return _union_api_inst; +} + +void UnionAPI::destroyInst() +{ + if (_union_api_inst != nullptr) { + delete _union_api_inst; + _union_api_inst = nullptr; + } +} + +void UnionAPI::initIDB() +{ + UNION_EVAL_INIT_IDB_INST->initPointSets(); + UNION_EVAL_INIT_IDB_INST->initDensityDB(); + UNION_EVAL_INIT_IDB_INST->initCongestionDB(); +} + +void UnionAPI::initEGR(bool enable_timing) +{ + UNION_EVAL_INIT_EGR_INST->runEGR(enable_timing); +} + +void UnionAPI::initFlute() +{ + UNION_EVAL_INIT_FLUTE_INST->readLUT(); +} + +void UnionAPI::destroyIDB() +{ + UNION_EVAL_INIT_IDB_INST->destroyInst(); +} + +void UnionAPI::destroyEGR() +{ + UNION_EVAL_INIT_EGR_INST->destroyInst(); +} + +void UnionAPI::destroyFlute() +{ + UNION_EVAL_INIT_FLUTE_INST->destroyInst(); +} + +} // namespace ieval diff --git a/src/evaluation/api/union_api.h b/src/evaluation/api/union_api.h new file mode 100644 index 000000000..8b329b735 --- /dev/null +++ b/src/evaluation/api/union_api.h @@ -0,0 +1,34 @@ +/* + * @FilePath: union_api.h + * @Author: Yihang Qiu (qiuyihang23@mails.ucas.ac.cn) + * @Date: 2024-10-11 15:37:27 + * @Description: + */ + +#pragma once + +namespace ieval { + +#define UNION_API_INST (ieval::UnionAPI::getInst()) + +class UnionAPI +{ + public: + UnionAPI(); + ~UnionAPI(); + static UnionAPI* getInst(); + static void destroyInst(); + + void initIDB(); + void initEGR(bool enable_timing = false); + void initFlute(); + + void destroyIDB(); + void destroyEGR(); + void destroyFlute(); + + private: + static UnionAPI* _union_api_inst; +}; + +} // namespace ieval \ No newline at end of file diff --git a/src/evaluation/api/wirelength_api.cpp b/src/evaluation/api/wirelength_api.cpp index 054da74dc..7b1d63878 100644 --- a/src/evaluation/api/wirelength_api.cpp +++ b/src/evaluation/api/wirelength_api.cpp @@ -70,6 +70,19 @@ TotalWLSummary WirelengthAPI::totalWL() return total_wirelength_summary; } +TotalWLSummary WirelengthAPI::totalWLPure() +{ + TotalWLSummary total_wirelength_summary; + + total_wirelength_summary.HPWL = EVAL_WIRELENGTH_INST->evalTotalHPWL(); + total_wirelength_summary.FLUTE = EVAL_WIRELENGTH_INST->evalTotalFLUTE(); + total_wirelength_summary.HTree = EVAL_WIRELENGTH_INST->evalTotalHTree(); + total_wirelength_summary.VTree = EVAL_WIRELENGTH_INST->evalTotalVTree(); + total_wirelength_summary.GRWL = EVAL_WIRELENGTH_INST->evalTotalEGRWL() * EVAL_WIRELENGTH_INST->getDesignUnit(); + + return total_wirelength_summary; +} + NetWLSummary WirelengthAPI::netWL(std::string net_name) { NetWLSummary net_wirelength_summary; @@ -80,7 +93,7 @@ NetWLSummary WirelengthAPI::netWL(std::string net_name) net_wirelength_summary = netWL(EVAL_WIRELENGTH_INST->getNetPointSet(net_name)); net_wirelength_summary.GRWL - = EVAL_WIRELENGTH_INST->evalNetEGRWL(EVAL_WIRELENGTH_INST->getEGRDirPath() + "/initial_router/route.guide", net_name) + = EVAL_WIRELENGTH_INST->evalNetEGRWL(EVAL_WIRELENGTH_INST->getEGRDirPath() + "/early_router/route.guide", net_name) * EVAL_WIRELENGTH_INST->getDesignUnit(); EVAL_WIRELENGTH_INST->destroyIDB(); @@ -142,6 +155,11 @@ void WirelengthAPI::evalNetInfo() EVAL_WIRELENGTH_INST->destroyFlute(); } +void WirelengthAPI::evalNetInfoPure() +{ + EVAL_WIRELENGTH_INST->evalNetInfo(); +} + int32_t WirelengthAPI::findNetHPWL(std::string net_name) { return EVAL_WIRELENGTH_INST->findHPWL(net_name); diff --git a/src/evaluation/api/wirelength_api.h b/src/evaluation/api/wirelength_api.h index a3822c5b8..1e3969c39 100644 --- a/src/evaluation/api/wirelength_api.h +++ b/src/evaluation/api/wirelength_api.h @@ -22,6 +22,7 @@ class WirelengthAPI static void destroyInst(); TotalWLSummary totalWL(); + TotalWLSummary totalWLPure(); NetWLSummary netWL(std::string net_name); TotalWLSummary totalWL(PointSets point_sets); @@ -33,6 +34,7 @@ class WirelengthAPI float pathEGRWL(std::string guide_path, std::string net_name, std::string load_name); void evalNetInfo(); + void evalNetInfoPure(); int32_t findNetHPWL(std::string net_name); int32_t findNetFLUTE(std::string net_name); int32_t findNetGRWL(std::string net_name); diff --git a/src/evaluation/apps/CMakeLists.txt b/src/evaluation/apps/CMakeLists.txt index d510a3cd1..412897a40 100644 --- a/src/evaluation/apps/CMakeLists.txt +++ b/src/evaluation/apps/CMakeLists.txt @@ -71,3 +71,23 @@ target_include_directories(wirelength_app ${HOME_EVALUATION}/database ) +# Union Evaluation APP +add_executable(union_app + union_app.cpp +) + +target_link_libraries(union_app + PRIVATE + eval_wirelength_api + eval_timing_api + eval_congestion_api + eval_union_api + idm +) + +target_include_directories(union_app + PRIVATE + ${HOME_EVALUATION}/api + ${HOME_EVALUATION}/database +) + diff --git a/src/evaluation/apps/congestion_app.cpp b/src/evaluation/apps/congestion_app.cpp index d30fde729..cfbba8c4a 100644 --- a/src/evaluation/apps/congestion_app.cpp +++ b/src/evaluation/apps/congestion_app.cpp @@ -13,17 +13,17 @@ void TestEgrMap(); void TestRudyMap(); void TestEgrOverflow(); void TestRudyUtilization(); -//void TestRudyMapFromIDB(); +// void TestRudyMapFromIDB(); void TestRudyMapFromIDB(const std::string& file_path); void TestEgrMapFromIDB(); -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { // TestEgrMap(); // TestRudyMap(); // TestEgrOverflow(); // TestRudyUtilization(); - + if (argc > 1) { std::string map_path(argv[1]); std::cout << "map_path: " << map_path << std::endl; @@ -39,8 +39,9 @@ void TestEgrMap() ieval::CongestionAPI congestion_api; std::string map_path = "./rt_temp_directory"; + std::string stage = "place"; - ieval::EGRMapSummary egr_map_summary = congestion_api.egrMap(map_path); + ieval::EGRMapSummary egr_map_summary = congestion_api.egrMap(stage, map_path); std::cout << "egr horizontal sum: " << egr_map_summary.horizontal_sum << std::endl; std::cout << "egr vertical sum: " << egr_map_summary.vertical_sum << std::endl; std::cout << "egr union sum: " << egr_map_summary.union_sum << std::endl; @@ -83,8 +84,9 @@ void TestRudyMap() region.uy = 7; int32_t grid_size = 2; + std::string stage = "place"; - ieval::RUDYMapSummary rudy_map_summary = congestion_api.rudyMap(congestion_nets, region, grid_size); + ieval::RUDYMapSummary rudy_map_summary = congestion_api.rudyMap(stage, congestion_nets, region, grid_size); std::cout << "rudy horizontal: " << rudy_map_summary.rudy_horizontal << std::endl; std::cout << "rudy vertical: " << rudy_map_summary.rudy_vertical << std::endl; std::cout << "rudy union: " << rudy_map_summary.rudy_union << std::endl; @@ -98,9 +100,10 @@ void TestEgrOverflow() ieval::CongestionAPI congestion_api; std::string map_path = "/home/yhqiu/benchmark/AiEDA/application/test/iEDA/rt_temp_directory"; + std::string stage = "place"; ieval::OverflowSummary overflow_summary; - overflow_summary = congestion_api.egrOverflow(map_path); + overflow_summary = congestion_api.egrOverflow(stage, map_path); std::cout << "total overflow horizontal: " << overflow_summary.total_overflow_horizontal << std::endl; std::cout << "total overflow vertical: " << overflow_summary.total_overflow_vertical << std::endl; std::cout << "total overflow union: " << overflow_summary.total_overflow_union << std::endl; @@ -115,10 +118,11 @@ void TestEgrOverflow() void TestRudyUtilization() { ieval::CongestionAPI congestion_api; + std::string stage = "place"; std::string map_path = "/home/yhqiu/benchmark/AiEDA/third_party/iEDA/bin"; ieval::UtilizationSummary utilization_summary; - utilization_summary = congestion_api.rudyUtilization(map_path, false); + utilization_summary = congestion_api.rudyUtilization(stage, map_path, false); std::cout << "max utilization horizontal: " << utilization_summary.max_utilization_horizontal << std::endl; std::cout << "max utilization vertical: " << utilization_summary.max_utilization_vertical << std::endl; std::cout << "max utilization union: " << utilization_summary.max_utilization_union << std::endl; @@ -126,7 +130,7 @@ void TestRudyUtilization() std::cout << "average utilization vertical: " << utilization_summary.weighted_average_utilization_vertical << std::endl; std::cout << "average utilization union: " << utilization_summary.weighted_average_utilization_union << std::endl; - utilization_summary = congestion_api.rudyUtilization(map_path, true); + utilization_summary = congestion_api.rudyUtilization(stage, map_path, true); std::cout << "max utilization horizontal: " << utilization_summary.max_utilization_horizontal << std::endl; std::cout << "max utilization vertical: " << utilization_summary.max_utilization_vertical << std::endl; std::cout << "max utilization union: " << utilization_summary.max_utilization_union << std::endl; @@ -139,8 +143,10 @@ void TestRudyMapFromIDB(const std::string& file_path) { dmInst->init(file_path); + std::string stage = "place"; + ieval::CongestionAPI congestion_api; - ieval::RUDYMapSummary rudy_map_summary = congestion_api.rudyMap(); + ieval::RUDYMapSummary rudy_map_summary = congestion_api.rudyMap(stage); std::cout << "rudy horizontal: " << rudy_map_summary.rudy_horizontal << std::endl; std::cout << "rudy vertical: " << rudy_map_summary.rudy_vertical << std::endl; @@ -150,7 +156,7 @@ void TestRudyMapFromIDB(const std::string& file_path) std::cout << "lut rudy union: " << rudy_map_summary.lutrudy_union << std::endl; ieval::UtilizationSummary utilization_summary; - utilization_summary = congestion_api.rudyUtilization(false); + utilization_summary = congestion_api.rudyUtilization(stage, false); std::cout << ">> RUDY " << std::endl; std::cout << "max utilization horizontal: " << utilization_summary.max_utilization_horizontal << std::endl; std::cout << "max utilization vertical: " << utilization_summary.max_utilization_vertical << std::endl; @@ -159,7 +165,7 @@ void TestRudyMapFromIDB(const std::string& file_path) std::cout << "average utilization vertical: " << utilization_summary.weighted_average_utilization_vertical << std::endl; std::cout << "average utilization union: " << utilization_summary.weighted_average_utilization_union << std::endl; - utilization_summary = congestion_api.rudyUtilization(true); + utilization_summary = congestion_api.rudyUtilization(stage, true); std::cout << ">> LUTRUDY " << std::endl; std::cout << "max utilization horizontal: " << utilization_summary.max_utilization_horizontal << std::endl; std::cout << "max utilization vertical: " << utilization_summary.max_utilization_vertical << std::endl; @@ -172,11 +178,12 @@ void TestRudyMapFromIDB(const std::string& file_path) void TestEgrMapFromIDB() { dmInst->init("/data/yhqiu/benchmark/AiEDA/application/benchmark/28nm/gcd/config/db_default_config_test.json"); + std::string stage = "place"; ieval::CongestionAPI congestion_api; ieval::OverflowSummary overflow_summary; - ieval::EGRMapSummary egr_map_summary = congestion_api.egrMap(); - overflow_summary = congestion_api.egrOverflow(); + ieval::EGRMapSummary egr_map_summary = congestion_api.egrMap(stage); + overflow_summary = congestion_api.egrOverflow(stage); std::cout << "egr horizontal sum: " << egr_map_summary.horizontal_sum << std::endl; std::cout << "egr vertical sum: " << egr_map_summary.vertical_sum << std::endl; diff --git a/src/evaluation/apps/density_app.cpp b/src/evaluation/apps/density_app.cpp index e23ab7244..43db463a7 100644 --- a/src/evaluation/apps/density_app.cpp +++ b/src/evaluation/apps/density_app.cpp @@ -25,6 +25,8 @@ int main() void TestDensityMap() { + std::string stage = "place"; + ieval::DensityAPI density_api; ieval::DensityRegion region; @@ -78,17 +80,17 @@ void TestDensityMap() nets.push_back(net1); nets.push_back(net2); - ieval::CellMapSummary cell_map_summary = density_api.cellDensityMap(cells, region, grid_size); + ieval::CellMapSummary cell_map_summary = density_api.cellDensityMap(cells, region, grid_size, stage); std::cout << "Macro density: " << cell_map_summary.macro_density << std::endl; std::cout << "StdCell density: " << cell_map_summary.stdcell_density << std::endl; std::cout << "AllCell density: " << cell_map_summary.allcell_density << std::endl; - ieval::PinMapSummary pin_map_summary = density_api.pinDensityMap(pins, region, grid_size, neighbor); + ieval::PinMapSummary pin_map_summary = density_api.pinDensityMap(pins, region, grid_size, stage, neighbor); std::cout << "Macro pin density: " << pin_map_summary.macro_pin_density << std::endl; std::cout << "StdCell pin density: " << pin_map_summary.stdcell_pin_density << std::endl; std::cout << "AllCell pin density: " << pin_map_summary.allcell_pin_density << std::endl; - ieval::NetMapSummary net_map_summary = density_api.netDensityMap(nets, region, grid_size, neighbor); + ieval::NetMapSummary net_map_summary = density_api.netDensityMap(nets, region, grid_size, stage, neighbor); std::cout << "Local net density: " << net_map_summary.local_net_density << std::endl; std::cout << "Global net density: " << net_map_summary.global_net_density << std::endl; std::cout << "All net density: " << net_map_summary.allnet_density << std::endl; @@ -98,9 +100,10 @@ void TestDensityMapFromIDB() { dmInst->init("/data/yhqiu/benchmark/AiEDA/application/benchmark/28nm/gcd/config/db_default_config_test.json"); int32_t grid_size = 2000; + std::string stage = "place"; ieval::DensityAPI density_api; - ieval::DensityMapSummary density_map_summary = density_api.densityMap(grid_size); + ieval::DensityMapSummary density_map_summary = density_api.densityMap(stage, grid_size); std::cout << "Macro density: " << density_map_summary.cell_map_summary.macro_density << std::endl; std::cout << "StdCell density: " << density_map_summary.cell_map_summary.stdcell_density << std::endl; @@ -112,7 +115,7 @@ void TestDensityMapFromIDB() std::cout << "Global net density: " << density_map_summary.net_map_summary.global_net_density << std::endl; std::cout << "All net density: " << density_map_summary.net_map_summary.allnet_density << std::endl; - ieval::NetMapSummary net_map = density_api.netDensityMap(grid_size); + ieval::NetMapSummary net_map = density_api.netDensityMap(stage, grid_size); std::cout << "Local net density: " << net_map.local_net_density << std::endl; std::cout << "Global net density: " << net_map.global_net_density << std::endl; std::cout << "All net density: " << net_map.allnet_density << std::endl; diff --git a/src/evaluation/apps/timing_app.cc b/src/evaluation/apps/timing_app.cc index e52c6fafd..60f8bb427 100644 --- a/src/evaluation/apps/timing_app.cc +++ b/src/evaluation/apps/timing_app.cc @@ -27,21 +27,22 @@ void TestTiming() // iPLAPIInst.initAPI("/data/project_share/dataset_baseline/gcd/workspace/config/iEDA_config/pl_default_config.json", // dmInst->get_idb_builder()); // iPLAPIInst.runFlow(); - - - dmInst->init("/home/liweiguo/project/AiEDA/application/benchmark/28nm/gcd/config/iEDA_config/db_default_config.json"); + dmInst->init("/data/project_share/dataset_baseline/s15850/workspace/config/iEDA_config/db_default_config.json"); auto config = dmInst->get_config(); config.set_output_path("/home/liweiguo/project/iEDA/scripts/design/eval/result"); dmInst->readLef(std::vector{config.get_tech_lef_path()}, true); dmInst->readLef(config.get_lef_paths()); - dmInst->readDef("/home/liweiguo/project/AiEDA/application/benchmark/28nm/gcd/output/iEDA/result/gcd_place.def"); + dmInst->readDef("/data/project_share/dataset_baseline/s15850/workspace/output/iEDA/result/s15850_place.def.gz"); - - auto timing_api = ieval::TimingAPI::getInst(); - timing_api->runSTA(); + auto* timing_api = ieval::TimingAPI::getInst(); + // timing_api->runSTA(); + timing_api->evalTiming("FLUTE"); auto summary = timing_api->evalDesign(); LOG_INFO << ">> Design Timing Evaluation: "; for (auto routing_type : {"HPWL", "FLUTE", "SALT", "EGR", "DR"}) { + if (summary.contains(routing_type) == false) { + continue; + } auto timing_summary = summary[routing_type]; LOG_INFO << "Routing type: " << routing_type; for (auto& clock_timing : timing_summary.clock_timings) { diff --git a/src/evaluation/apps/union_app.cpp b/src/evaluation/apps/union_app.cpp new file mode 100644 index 000000000..27efe185a --- /dev/null +++ b/src/evaluation/apps/union_app.cpp @@ -0,0 +1,85 @@ +#include + +#include "congestion_api.h" +#include "idm.h" +#include "timing_api.hh" +#include "union_api.h" +#include "wirelength_api.h" + +void TestBuildNetEval(); + +int main() +{ + TestBuildNetEval(); + + return 0; +} + +void TestBuildNetEval() +{ + dmInst->init("/data/project_share/dataset_baseline/jpeg_encoder/workspace/config/iEDA_config/db_default_config_tmp.json"); + UNION_API_INST->initIDB(); + UNION_API_INST->initEGR(true); + UNION_API_INST->initFlute(); + + std::cout << "Building net evaluation data...\n"; + + auto* idb_builder = dmInst->get_idb_builder(); + idb::IdbDesign* idb_design = idb_builder->get_def_service()->get_design(); + + CONGESTION_API_INST->evalNetInfoPure(); + WIRELENGTH_API_INST->evalNetInfoPure(); + ieval::TimingAPI::getInst()->evalTiming("EGR", true); + ieval::TimingAPI::getInst()->evalTiming("HPWL"); + ieval::TimingAPI::getInst()->evalTiming("FLUTE"); + auto net_power_data = ieval::TimingAPI::getInst()->evalNetPower(); + + for (size_t i = 0; i < idb_design->get_net_list()->get_net_list().size(); i++) { + auto* idb_net = idb_design->get_net_list()->get_net_list()[i]; + std::string net_name = idb_net->get_net_name(); + std::string net_type; + + + int pin_num = CONGESTION_API_INST->findPinNumber(net_name); + if (pin_num < 4) { + continue; + } + int aspect_ratio = CONGESTION_API_INST->findAspectRatio(net_name); + float l_ness = CONGESTION_API_INST->findLness(net_name); + int32_t bbox_width = CONGESTION_API_INST->findBBoxWidth(net_name); + int32_t bbox_height = CONGESTION_API_INST->findBBoxHeight(net_name); + int64_t bbox_area = CONGESTION_API_INST->findBBoxArea(net_name); + int32_t bbox_lx = CONGESTION_API_INST->findBBoxLx(net_name); + int32_t bbox_ly = CONGESTION_API_INST->findBBoxLy(net_name); + int32_t bbox_ux = CONGESTION_API_INST->findBBoxUx(net_name); + int32_t bbox_uy = CONGESTION_API_INST->findBBoxUy(net_name); + + int32_t hpwl = WIRELENGTH_API_INST->findNetHPWL(net_name); + int32_t flute = WIRELENGTH_API_INST->findNetFLUTE(net_name); + int32_t grwl = WIRELENGTH_API_INST->findNetGRWL(net_name); + + net_name.erase(std::remove(net_name.begin(), net_name.end(), '\\'), net_name.end()); + + if (ieval::TimingAPI::getInst()->isClockNet(net_name)) { + net_type = "clock"; + } else { + net_type = "signal"; + } + if (net_power_data["HPWL"].find(net_name) == net_power_data["HPWL"].end() + || net_power_data["FLUTE"].find(net_name) == net_power_data["FLUTE"].end() + || net_power_data["EGR"].find(net_name) == net_power_data["EGR"].end()) { + std::cerr << "Error: net_name '" << net_name << "' not found in net_power_data.\n"; + std::exit(EXIT_FAILURE); + } + + double hpwl_power = net_power_data["HPWL"][net_name]; + double flute_power = net_power_data["FLUTE"][net_name]; + double egr_power = net_power_data["EGR"][net_name]; + + if (net_name == "InvalidSymbol") { + std::cout << net_name << ',' << net_type << "," << pin_num << ',' << aspect_ratio << ',' << bbox_width << "," << bbox_height << "," + << bbox_area << "," << bbox_lx << "," << bbox_ly << "," << bbox_ux << "," << bbox_uy << "," << l_ness << ',' << hpwl << ',' + << flute << ',' << grwl << ',' << hpwl_power << ',' << flute_power << "," << egr_power << '\n'; + } + } +} \ No newline at end of file diff --git a/src/evaluation/apps/wirelength_app.cpp b/src/evaluation/apps/wirelength_app.cpp index 69bc8bac5..72adcbedb 100644 --- a/src/evaluation/apps/wirelength_app.cpp +++ b/src/evaluation/apps/wirelength_app.cpp @@ -21,7 +21,7 @@ int main(int argc, char* argv[]) // TestTotalWirelength(); // TestNetWirelength(); // TestPathWirelength(); - // TestEgrWirelength("./rt_temp_directory/initial_router/route.guide"); + // TestEgrWirelength("./rt_temp_directory/early_router/route.guide"); if (argc > 1) { std::string workspace_path(argv[1]); std::cout << "workspace_path: " << workspace_path << std::endl; diff --git a/src/evaluation/src/module/congestion/congestion_eval.cpp b/src/evaluation/src/module/congestion/congestion_eval.cpp index 059f676ab..5b09301a7 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.cpp +++ b/src/evaluation/src/module/congestion/congestion_eval.cpp @@ -53,201 +53,201 @@ void CongestionEval::destroyInst() } } -string CongestionEval::evalHoriEGR(string rt_dir_path) +string CongestionEval::evalHoriEGR(string stage, string rt_dir_path) { - return evalEGR(rt_dir_path, "horizontal", "egr_horizontal_overflow.csv"); + return evalEGR(rt_dir_path, "horizontal", stage + "_egr_horizontal_overflow.csv"); } -string CongestionEval::evalVertiEGR(string rt_dir_path) +string CongestionEval::evalVertiEGR(string stage, string rt_dir_path) { - return evalEGR(rt_dir_path, "vertical", "egr_vertical_overflow.csv"); + return evalEGR(rt_dir_path, "vertical", stage + "_egr_vertical_overflow.csv"); } -string CongestionEval::evalUnionEGR(string rt_dir_path) +string CongestionEval::evalUnionEGR(string stage, string rt_dir_path) { - return evalEGR(rt_dir_path, "union", "egr_union_overflow.csv"); + return evalEGR(rt_dir_path, "union", stage + "_egr_union_overflow.csv"); } -string CongestionEval::evalHoriRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalHoriRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalRUDY(nets, region, grid_size, "horizontal", "rudy_horizontal.csv"); + return evalRUDY(nets, region, grid_size, "horizontal", stage + "_rudy_horizontal.csv"); } -string CongestionEval::evalVertiRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalVertiRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalRUDY(nets, region, grid_size, "vertical", "rudy_vertical.csv"); + return evalRUDY(nets, region, grid_size, "vertical", stage + "_rudy_vertical.csv"); } -string CongestionEval::evalUnionRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalUnionRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalRUDY(nets, region, grid_size, "union", "rudy_union.csv"); + return evalRUDY(nets, region, grid_size, "union", stage + "_rudy_union.csv"); } -string CongestionEval::evalHoriLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalHoriLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalLUTRUDY(nets, region, grid_size, "horizontal", "lut_rudy_horizontal.csv"); + return evalLUTRUDY(nets, region, grid_size, "horizontal", stage + "_lut_rudy_horizontal.csv"); } -string CongestionEval::evalVertiLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalVertiLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalLUTRUDY(nets, region, grid_size, "vertical", "lut_rudy_vertical.csv"); + return evalLUTRUDY(nets, region, grid_size, "vertical", stage + "_lut_rudy_vertical.csv"); } -string CongestionEval::evalUnionLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size) +string CongestionEval::evalUnionLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size) { - return evalLUTRUDY(nets, region, grid_size, "union", "lut_rudy_union.csv"); + return evalLUTRUDY(nets, region, grid_size, "union", stage + "_lut_rudy_union.csv"); } -int32_t CongestionEval::evalHoriTotalOverflow(string rt_dir_path) +int32_t CongestionEval::evalHoriTotalOverflow(string stage, string rt_dir_path) { - return evalTotalOverflow(rt_dir_path, "horizontal"); + return evalTotalOverflow(stage, rt_dir_path, "horizontal"); } -int32_t CongestionEval::evalVertiTotalOverflow(string rt_dir_path) +int32_t CongestionEval::evalVertiTotalOverflow(string stage, string rt_dir_path) { - return evalTotalOverflow(rt_dir_path, "vertical"); + return evalTotalOverflow(stage, rt_dir_path, "vertical"); } -int32_t CongestionEval::evalUnionTotalOverflow(string rt_dir_path) +int32_t CongestionEval::evalUnionTotalOverflow(string stage, string rt_dir_path) { - return evalTotalOverflow(rt_dir_path, "union"); + return evalTotalOverflow(stage, rt_dir_path, "union"); } -int32_t CongestionEval::evalHoriMaxOverflow(string rt_dir_path) +int32_t CongestionEval::evalHoriMaxOverflow(string stage, string rt_dir_path) { - return evalMaxOverflow(rt_dir_path, "horizontal"); + return evalMaxOverflow(stage, rt_dir_path, "horizontal"); } -int32_t CongestionEval::evalVertiMaxOverflow(string rt_dir_path) +int32_t CongestionEval::evalVertiMaxOverflow(string stage, string rt_dir_path) { - return evalMaxOverflow(rt_dir_path, "vertical"); + return evalMaxOverflow(stage, rt_dir_path, "vertical"); } -int32_t CongestionEval::evalUnionMaxOverflow(string rt_dir_path) +int32_t CongestionEval::evalUnionMaxOverflow(string stage, string rt_dir_path) { - return evalMaxOverflow(rt_dir_path, "union"); + return evalMaxOverflow(stage, rt_dir_path, "union"); } -float CongestionEval::evalHoriAvgOverflow(string rt_dir_path) +float CongestionEval::evalHoriAvgOverflow(string stage, string rt_dir_path) { - return evalAvgOverflow(rt_dir_path, "horizontal"); + return evalAvgOverflow(stage, rt_dir_path, "horizontal"); } -float CongestionEval::evalVertiAvgOverflow(string rt_dir_path) +float CongestionEval::evalVertiAvgOverflow(string stage, string rt_dir_path) { - return evalAvgOverflow(rt_dir_path, "vertical"); + return evalAvgOverflow(stage, rt_dir_path, "vertical"); } -float CongestionEval::evalUnionAvgOverflow(string rt_dir_path) +float CongestionEval::evalUnionAvgOverflow(string stage, string rt_dir_path) { - return evalAvgOverflow(rt_dir_path, "union"); + return evalAvgOverflow(stage, rt_dir_path, "union"); } -float CongestionEval::evalHoriMaxUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalHoriMaxUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalMaxUtilization(rudy_dir_path, "horizontal", use_lut); + return evalMaxUtilization(stage, rudy_dir_path, "horizontal", use_lut); } -float CongestionEval::evalVertiMaxUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalVertiMaxUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalMaxUtilization(rudy_dir_path, "vertical", use_lut); + return evalMaxUtilization(stage, rudy_dir_path, "vertical", use_lut); } -float CongestionEval::evalUnionMaxUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalUnionMaxUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalMaxUtilization(rudy_dir_path, "union", use_lut); + return evalMaxUtilization(stage, rudy_dir_path, "union", use_lut); } -float CongestionEval::evalHoriAvgUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalHoriAvgUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalAvgUtilization(rudy_dir_path, "horizontal", use_lut); + return evalAvgUtilization(stage, rudy_dir_path, "horizontal", use_lut); } -float CongestionEval::evalVertiAvgUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalVertiAvgUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalAvgUtilization(rudy_dir_path, "vertical", use_lut); + return evalAvgUtilization(stage, rudy_dir_path, "vertical", use_lut); } -float CongestionEval::evalUnionAvgUtilization(string rudy_dir_path, bool use_lut) +float CongestionEval::evalUnionAvgUtilization(string stage, string rudy_dir_path, bool use_lut) { - return evalAvgUtilization(rudy_dir_path, "union", use_lut); + return evalAvgUtilization(stage, rudy_dir_path, "union", use_lut); } string CongestionEval::evalEGR(string rt_dir_path, string egr_type, string output_filename) { std::unordered_map layer_directions - = EVAL_INIT_EGR_INST->parseLayerDirection(rt_dir_path + "/initial_router/route.guide"); + = EVAL_INIT_EGR_INST->parseLayerDirection(rt_dir_path + "/early_router/route.guide"); // for (const auto& [layer, direction] : LayerDirections) { // std::cout << "Layer: " << layer << ", Direction: " << (direction == LayerDirection::Horizontal ? "Horizontal" : "Vertical") // << std::endl; // } std::vector target_layers; - std::string dir_path = rt_dir_path + "/initial_router/"; + std::string dir_path = rt_dir_path + "/early_router/"; std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); std::filesystem::path out_file_path = parent_path / output_filename; if (egr_type == "horizontal" || egr_type == "vertical") { LayerDirection target_direction = (egr_type == "horizontal") ? LayerDirection::Horizontal : LayerDirection::Vertical; - for (const auto& [layer, direction] : layer_directions) { if (direction == target_direction) { target_layers.push_back(layer); } } - - std::vector> sum_matrix; - bool is_first_file = true; - - for (const auto& entry : std::filesystem::directory_iterator(dir_path)) { - std::string filename = entry.path().filename().string(); - if (filename.find("overflow_map_") != std::string::npos) { - for (const auto& layer : target_layers) { - if (filename.find(layer) != std::string::npos) { - std::ifstream file(entry.path()); - std::string line; - size_t row = 0; - while (std::getline(file, line)) { - std::istringstream iss(line); - std::string value; - int col = 0; - while (std::getline(iss, value, ',')) { - double num_value = std::stod(value); - if (is_first_file) { - if (row >= sum_matrix.size()) { - sum_matrix.push_back(std::vector()); - } - sum_matrix[row].push_back(num_value); - } else { - sum_matrix[row][col] += num_value; - } - col++; - } - row++; - } - is_first_file = false; - break; - } - } - } - } - - std::ofstream out_file(out_file_path); - for (const auto& row : sum_matrix) { - for (size_t i = 0; i < row.size(); ++i) { - out_file << row[i]; - if (i < row.size() - 1) { - out_file << ","; - } - } - out_file << "\n"; - } - out_file.close(); } else if (egr_type == "union") { - dir_path = rt_dir_path + "/topology_generator/"; - std::string source_file = dir_path + "overflow_map_planar.csv"; - std::filesystem::copy_file(source_file, out_file_path, std::filesystem::copy_options::overwrite_existing); + for (const auto& [layer, direction] : layer_directions) { + target_layers.push_back(layer); + } } + + std::vector> sum_matrix; + bool is_first_file = true; + + for (const auto& entry : std::filesystem::directory_iterator(dir_path)) { + std::string filename = entry.path().filename().string(); + if (filename.find("overflow_map_") != std::string::npos) { + for (const auto& layer : target_layers) { + if (filename.find(layer) != std::string::npos) { + std::ifstream file(entry.path()); + std::string line; + size_t row = 0; + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string value; + int col = 0; + while (std::getline(iss, value, ',')) { + double num_value = std::stod(value); + if (is_first_file) { + if (row >= sum_matrix.size()) { + sum_matrix.push_back(std::vector()); + } + sum_matrix[row].push_back(num_value); + } else { + sum_matrix[row][col] += num_value; + } + col++; + } + row++; + } + is_first_file = false; + break; + } + } + } + } + + std::ofstream out_file(out_file_path); + for (const auto& row : sum_matrix) { + for (size_t i = 0; i < row.size(); ++i) { + out_file << row[i]; + if (i < row.size() - 1) { + out_file << ","; + } + } + out_file << "\n"; + } + out_file.close(); + return out_file_path.string(); } @@ -371,13 +371,13 @@ string CongestionEval::evalLUTRUDY(CongestionNets nets, CongestionRegion region, int pin_num = net.pins.size(); int aspect_ratio = 1; if (net_ux - net_lx >= net_uy - net_ly && net_uy - net_ly != 0) { - aspect_ratio = std::round((net_ux - net_lx) / (net_uy - net_ly)); + aspect_ratio = std::round((net_ux - net_lx) / static_cast(net_uy - net_ly)); } else if (net_ux - net_lx < net_uy - net_ly && net_ux - net_lx != 0) { - aspect_ratio = std::round((net_uy - net_ly) / (net_ux - net_lx)); + aspect_ratio = std::round((net_uy - net_ly) / static_cast(net_ux - net_lx)); } - float l_ness = 0.f; + double l_ness = 0.0; if (pin_num < 3) { - l_ness = 1.f; + l_ness = 1.0; } else if (pin_num <= 15) { std::vector> point_set; for (const auto& pin : net.pins) { @@ -385,7 +385,7 @@ string CongestionEval::evalLUTRUDY(CongestionNets nets, CongestionRegion region, } l_ness = calculateLness(point_set, net_lx, net_ux, net_ly, net_uy); } else { - l_ness = 0.5f; + l_ness = 0.5; } double hor_lutrudy = 0.0; @@ -452,18 +452,18 @@ string CongestionEval::evalLUTRUDY(CongestionNets nets, CongestionRegion region, return getAbsoluteFilePath(output_path); } -float CongestionEval::calculateLness(std::vector> point_set, int32_t net_lx, int32_t net_ux, int32_t net_ly, - int32_t net_uy) +double CongestionEval::calculateLness(std::vector> point_set, int32_t net_lx, int32_t net_ux, int32_t net_ly, + int32_t net_uy) { - int32_t bbox = (net_ux - net_lx) * (net_uy - net_ly); + int64_t bbox = static_cast(net_ux - net_lx) * static_cast(net_uy - net_ly); int32_t r1 = calcLowerLeftRP(point_set, net_lx, net_ly); int32_t r2 = calcLowerRightRP(point_set, net_ux, net_ly); int32_t r3 = calcUpperLeftRP(point_set, net_lx, net_uy); int32_t r4 = calcUpperRightRP(point_set, net_ux, net_uy); int32_t r = std::max({r1, r2, r3, r4}); - float l_ness; + double l_ness; if (bbox != 0) { - l_ness = r / bbox; + l_ness = static_cast(r) / static_cast(bbox); } else { l_ness = 1.0; } @@ -530,7 +530,7 @@ int32_t CongestionEval::calcUpperRightRP(std::vector return r; } -double CongestionEval::getLUT(int32_t pin_num, int32_t aspect_ratio, float l_ness) +double CongestionEval::getLUT(int32_t pin_num, int32_t aspect_ratio, double l_ness) { int ar_index; if (aspect_ratio == 1) { @@ -558,21 +558,21 @@ double CongestionEval::getLUT(int32_t pin_num, int32_t aspect_ratio, float l_nes return WIRELENGTH_LUT[ar_index][pin_index][l_index]; } -int32_t CongestionEval::evalTotalOverflow(string rt_dir_path, string overflow_type) +int32_t CongestionEval::evalTotalOverflow(string stage, string rt_dir_path, string overflow_type) { int32_t total_overflow = 0; std::string file_name; if (overflow_type == "horizontal") { - file_name = "egr_horizontal_overflow.csv"; + file_name = stage + "_egr_horizontal_overflow.csv"; } else if (overflow_type == "vertical") { - file_name = "egr_vertical_overflow.csv"; + file_name = stage + "_egr_vertical_overflow.csv"; } else if (overflow_type == "union") { - file_name = "egr_union_overflow.csv"; + file_name = stage + "_egr_union_overflow.csv"; } else { return -1; } - std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); + std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); std::filesystem::path file_path = parent_path / file_name; std::string file_path_str = file_path.string(); @@ -594,21 +594,21 @@ int32_t CongestionEval::evalTotalOverflow(string rt_dir_path, string overflow_ty return total_overflow; } -int32_t CongestionEval::evalMaxOverflow(string rt_dir_path, string overflow_type) +int32_t CongestionEval::evalMaxOverflow(string stage, string rt_dir_path, string overflow_type) { int32_t max_overflow = -1; std::string file_name; if (overflow_type == "horizontal") { - file_name = "egr_horizontal_overflow.csv"; + file_name = stage + "_egr_horizontal_overflow.csv"; } else if (overflow_type == "vertical") { - file_name = "egr_vertical_overflow.csv"; + file_name = stage + "_egr_vertical_overflow.csv"; } else if (overflow_type == "union") { - file_name = "egr_union_overflow.csv"; + file_name = stage + "_egr_union_overflow.csv"; } else { return -1; } - std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); + std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); std::filesystem::path file_path = parent_path / file_name; std::string file_path_str = file_path.string(); @@ -631,21 +631,21 @@ int32_t CongestionEval::evalMaxOverflow(string rt_dir_path, string overflow_type return max_overflow; } -float CongestionEval::evalAvgOverflow(string rt_dir_path, string overflow_type) +float CongestionEval::evalAvgOverflow(string stage, string rt_dir_path, string overflow_type) { float avg_overflow = 0.0f; std::string file_name; if (overflow_type == "horizontal") { - file_name = "egr_horizontal_overflow.csv"; + file_name = stage + "_egr_horizontal_overflow.csv"; } else if (overflow_type == "vertical") { - file_name = "egr_vertical_overflow.csv"; + file_name = stage + "_egr_vertical_overflow.csv"; } else if (overflow_type == "union") { - file_name = "egr_union_overflow.csv"; + file_name = stage + "_egr_union_overflow.csv"; } else { return -1; } - std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); + std::filesystem::path parent_path = std::filesystem::path(rt_dir_path).parent_path(); std::filesystem::path file_path = parent_path / file_name; std::string file_path_str = file_path.string(); @@ -714,16 +714,16 @@ float CongestionEval::evalAvgOverflow(string rt_dir_path, string overflow_type) return avg_overflow; } -float CongestionEval::evalMaxUtilization(string map_path, string utilization_type, bool use_lut) +float CongestionEval::evalMaxUtilization(string stage, string map_path, string utilization_type, bool use_lut) { float max_util = -1.0; std::string file_path; std::string file_name; if (use_lut == true) { - file_name = "/lut_rudy_"; + file_name = "/" + stage + "_lut_rudy_"; } else { - file_name = "/rudy_"; + file_name = "/" + stage + "_rudy_"; } if (utilization_type == "horizontal") { @@ -755,16 +755,16 @@ float CongestionEval::evalMaxUtilization(string map_path, string utilization_typ return max_util; } -float CongestionEval::evalAvgUtilization(string rudy_dir_path, string utilization_type, bool use_lut) +float CongestionEval::evalAvgUtilization(string stage, string rudy_dir_path, string utilization_type, bool use_lut) { float avg_util = 0.0f; std::string file_path; std::string file_name; if (use_lut == true) { - file_name = "/lut_rudy_"; + file_name = "/" + stage + "_lut_rudy_"; } else { - file_name = "/rudy_"; + file_name = "/" + stage + "_rudy_"; } if (utilization_type == "horizontal") { @@ -900,14 +900,14 @@ void CongestionEval::evalNetInfo() int aspect_ratio = 1; if (net_ux - net_lx >= net_uy - net_ly && net_uy - net_ly != 0) { - aspect_ratio = std::round((net_ux - net_lx) / (net_uy - net_ly)); + aspect_ratio = std::round((net_ux - net_lx) / static_cast(net_uy - net_ly)); } else if (net_ux - net_lx < net_uy - net_ly && net_ux - net_lx != 0) { - aspect_ratio = std::round((net_uy - net_ly) / (net_ux - net_lx)); + aspect_ratio = std::round((net_uy - net_ly) / static_cast(net_ux - net_lx)); } - float l_ness = 0.f; + double l_ness = 0.0; if (pin_num < 3) { - l_ness = 1.f; + l_ness = 1.0; } else if (pin_num <= 15) { std::vector> point_set; for (const auto& pin : net.pins) { @@ -915,12 +915,27 @@ void CongestionEval::evalNetInfo() } l_ness = calculateLness(point_set, net_lx, net_ux, net_ly, net_uy); } else { - l_ness = 0.5f; + l_ness = 0.5; } + int32_t bbox_width = net_ux - net_lx; + int32_t bbox_height = net_uy - net_ly; + int64_t bbox_area = static_cast(bbox_width) * static_cast(bbox_height); + int32_t bbox_lx = net_lx; + int32_t bbox_ly = net_ly; + int32_t bbox_ux = net_ux; + int32_t bbox_uy = net_uy; + _name_pin_numer.emplace(net.name, pin_num); _name_aspect_ratio.emplace(net.name, aspect_ratio); _name_lness.emplace(net.name, l_ness); + _name_bbox_width.emplace(net.name, bbox_width); + _name_bbox_height.emplace(net.name, bbox_height); + _name_bbox_area.emplace(net.name, bbox_area); + _name_bbox_lx.emplace(net.name, bbox_lx); + _name_bbox_ly.emplace(net.name, bbox_ly); + _name_bbox_ux.emplace(net.name, bbox_ux); + _name_bbox_uy.emplace(net.name, bbox_uy); } } @@ -942,7 +957,7 @@ int CongestionEval::findAspectRatio(std::string net_name) throw std::runtime_error("Aspect ratio not found for net: " + net_name); } -float CongestionEval::findLness(std::string net_name) +double CongestionEval::findLness(std::string net_name) { auto it = _name_lness.find(net_name); if (it != _name_lness.end()) { @@ -951,6 +966,69 @@ float CongestionEval::findLness(std::string net_name) throw std::runtime_error("Lness not found for net: " + net_name); } +int32_t CongestionEval::findBBoxWidth(std::string net_name) +{ + auto it = _name_bbox_width.find(net_name); + if (it != _name_bbox_width.end()) { + return it->second; + } + throw std::runtime_error("BBox width not found for net: " + net_name); +} + +int32_t CongestionEval::findBBoxHeight(std::string net_name) +{ + auto it = _name_bbox_height.find(net_name); + if (it != _name_bbox_height.end()) { + return it->second; + } + throw std::runtime_error("BBox height not found for net: " + net_name); +} + +int64_t CongestionEval::findBBoxArea(std::string net_name) +{ + auto it = _name_bbox_area.find(net_name); + if (it != _name_bbox_area.end()) { + return it->second; + } + throw std::runtime_error("BBox area not found for net: " + net_name); +} + +int32_t CongestionEval::findBBoxLx(std::string net_name) +{ + auto it = _name_bbox_lx.find(net_name); + if (it != _name_bbox_lx.end()) { + return it->second; + } + throw std::runtime_error("BBox lx not found for net: " + net_name); +} + +int32_t CongestionEval::findBBoxLy(std::string net_name) +{ + auto it = _name_bbox_ly.find(net_name); + if (it != _name_bbox_ly.end()) { + return it->second; + } + throw std::runtime_error("BBox ly not found for net: " + net_name); +} + +int32_t CongestionEval::findBBoxUx(std::string net_name) +{ + auto it = _name_bbox_ux.find(net_name); + if (it != _name_bbox_ux.end()) { + return it->second; + } + throw std::runtime_error("BBox ux not found for net: " + net_name); +} + +int32_t CongestionEval::findBBoxUy(std::string net_name) +{ + auto it = _name_bbox_uy.find(net_name); + if (it != _name_bbox_uy.end()) { + return it->second; + } + throw std::runtime_error("BBox uy not found for net: " + net_name); +} + std::string CongestionEval::getEGRDirPath() { return EVAL_INIT_EGR_INST->getEGRDirPath(); @@ -961,4 +1039,9 @@ std::string CongestionEval::getDefaultOutputDir() return getDefaultOutputPath(); } +void CongestionEval::setEGRDirPath(std::string egr_dir_path) +{ + EVAL_INIT_EGR_INST->setEGRDirPath(egr_dir_path); +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/module/congestion/congestion_eval.h b/src/evaluation/src/module/congestion/congestion_eval.h index f54303078..eb871cb97 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.h +++ b/src/evaluation/src/module/congestion/congestion_eval.h @@ -22,37 +22,37 @@ class CongestionEval static CongestionEval* getInst(); static void destroyInst(); - string evalHoriEGR(string rt_dir_path); - string evalVertiEGR(string rt_dir_path); - string evalUnionEGR(string rt_dir_path); + string evalHoriEGR(string stage, string rt_dir_path); + string evalVertiEGR(string stage, string rt_dir_path); + string evalUnionEGR(string stage, string rt_dir_path); - string evalHoriRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); - string evalVertiRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); - string evalUnionRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalHoriRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalVertiRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalUnionRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); - string evalHoriLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); - string evalVertiLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); - string evalUnionLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalHoriLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalVertiLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); + string evalUnionLUTRUDY(string stage, CongestionNets nets, CongestionRegion region, int32_t grid_size); - int32_t evalHoriTotalOverflow(string rt_dir_path); - int32_t evalVertiTotalOverflow(string rt_dir_path); - int32_t evalUnionTotalOverflow(string rt_dir_path); + int32_t evalHoriTotalOverflow(string stage, string rt_dir_path); + int32_t evalVertiTotalOverflow(string stage, string rt_dir_path); + int32_t evalUnionTotalOverflow(string stage, string rt_dir_path); - int32_t evalHoriMaxOverflow(string rt_dir_path); - int32_t evalVertiMaxOverflow(string rt_dir_path); - int32_t evalUnionMaxOverflow(string rt_dir_path); + int32_t evalHoriMaxOverflow(string stage, string rt_dir_path); + int32_t evalVertiMaxOverflow(string stage, string rt_dir_path); + int32_t evalUnionMaxOverflow(string stage, string rt_dir_path); - float evalHoriAvgOverflow(string rt_dir_path); - float evalVertiAvgOverflow(string rt_dir_path); - float evalUnionAvgOverflow(string rt_dir_path); + float evalHoriAvgOverflow(string stage, string rt_dir_path); + float evalVertiAvgOverflow(string stage, string rt_dir_path); + float evalUnionAvgOverflow(string stage, string rt_dir_path); - float evalHoriMaxUtilization(string rudy_dir_path, bool use_lut = false); - float evalVertiMaxUtilization(string rudy_dir_path, bool use_lut = false); - float evalUnionMaxUtilization(string rudy_dir_path, bool use_lut = false); + float evalHoriMaxUtilization(string stage, string rudy_dir_path, bool use_lut = false); + float evalVertiMaxUtilization(string stage, string rudy_dir_path, bool use_lut = false); + float evalUnionMaxUtilization(string stage, string rudy_dir_path, bool use_lut = false); - float evalHoriAvgUtilization(string rudy_dir_path, bool use_lut = false); - float evalVertiAvgUtilization(string rudy_dir_path, bool use_lut = false); - float evalUnionAvgUtilization(string rudy_dir_path, bool use_lut = false); + float evalHoriAvgUtilization(string stage, string rudy_dir_path, bool use_lut = false); + float evalVertiAvgUtilization(string stage, string rudy_dir_path, bool use_lut = false); + float evalUnionAvgUtilization(string stage, string rudy_dir_path, bool use_lut = false); void initEGR(); void destroyEGR(); @@ -65,32 +65,47 @@ class CongestionEval void evalNetInfo(); int findPinNumber(std::string net_name); int findAspectRatio(std::string net_name); - float findLness(std::string net_name); + double findLness(std::string net_name); + int32_t findBBoxWidth(std::string net_name); + int32_t findBBoxHeight(std::string net_name); + int64_t findBBoxArea(std::string net_name); + int32_t findBBoxLx(std::string net_name); + int32_t findBBoxLy(std::string net_name); + int32_t findBBoxUx(std::string net_name); + int32_t findBBoxUy(std::string net_name); int32_t getRowHeight(); std::string getEGRDirPath(); std::string getDefaultOutputDir(); + void setEGRDirPath(std::string egr_dir_path); private: static CongestionEval* _congestion_eval; std::map _name_pin_numer; std::map _name_aspect_ratio; - std::map _name_lness; + std::map _name_lness; + std::map _name_bbox_width; + std::map _name_bbox_height; + std::map _name_bbox_area; + std::map _name_bbox_lx; + std::map _name_bbox_ly; + std::map _name_bbox_ux; + std::map _name_bbox_uy; string evalEGR(string rt_dir_path, string egr_type, string output_filename); string evalRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size, string rudy_type, string output_filename); string evalLUTRUDY(CongestionNets nets, CongestionRegion region, int32_t grid_size, string lutrudy_type, string output_filename); - float calculateLness(std::vector> point_set, int32_t net_lx, int32_t net_ux, int32_t net_ly, int32_t net_uy); + double calculateLness(std::vector> point_set, int32_t net_lx, int32_t net_ux, int32_t net_ly, int32_t net_uy); int32_t calcLowerLeftRP(std::vector> point_set, int32_t x_min, int32_t y_min); int32_t calcLowerRightRP(std::vector> point_set, int32_t x_max, int32_t y_min); int32_t calcUpperLeftRP(std::vector> point_set, int32_t x_min, int32_t y_max); int32_t calcUpperRightRP(std::vector> point_set, int32_t x_max, int32_t y_max); - double getLUT(int32_t pin_num, int32_t aspect_ratio, float l_ness); - int32_t evalTotalOverflow(string rt_dir_path, string overflow_type); - int32_t evalMaxOverflow(string rt_dir_path, string overflow_type); - float evalAvgOverflow(string rt_dir_path, string overflow_type); - float evalMaxUtilization(string rudy_dir_path, string utilization_type, bool use_lut = false); - float evalAvgUtilization(string rudy_dir_path, string utilization_type, bool use_lut = false); + double getLUT(int32_t pin_num, int32_t aspect_ratio, double l_ness); + int32_t evalTotalOverflow(string stage, string rt_dir_path, string overflow_type); + int32_t evalMaxOverflow(string stage, string rt_dir_path, string overflow_type); + float evalAvgOverflow(string stage, string rt_dir_path, string overflow_type); + float evalMaxUtilization(string stage, string rudy_dir_path, string utilization_type, bool use_lut = false); + float evalAvgUtilization(string stage, string rudy_dir_path, string utilization_type, bool use_lut = false); }; } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/module/density/density_eval.cpp b/src/evaluation/src/module/density/density_eval.cpp index 3799d0387..0d9807a6c 100644 --- a/src/evaluation/src/module/density/density_eval.cpp +++ b/src/evaluation/src/module/density/density_eval.cpp @@ -49,49 +49,49 @@ void DensityEval::destroyInst() } } -std::string DensityEval::evalMacroDensity(DensityCells cells, DensityRegion region, int32_t grid_size) +std::string DensityEval::evalMacroDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage) { - return evalDensity(cells, region, grid_size, "macro", "macro_density.csv"); + return evalDensity(cells, region, grid_size, "macro", stage + "_macro_density.csv"); } -std::string DensityEval::evalStdCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size) +std::string DensityEval::evalStdCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage) { - return evalDensity(cells, region, grid_size, "stdcell", "stdcell_density.csv"); + return evalDensity(cells, region, grid_size, "stdcell", stage + "_stdcell_density.csv"); } -std::string DensityEval::evalAllCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size) +std::string DensityEval::evalAllCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage) { - return evalDensity(cells, region, grid_size, "all", "allcell_density.csv"); + return evalDensity(cells, region, grid_size, "all", stage + "_allcell_density.csv"); } -std::string DensityEval::evalMacroPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalMacroPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalPinDensity(pins, region, grid_size, neighbor, "macro", "macro_pin_density.csv"); + return evalPinDensity(pins, region, grid_size, neighbor, "macro", stage + "_macro_pin_density.csv"); } -std::string DensityEval::evalStdCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalStdCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalPinDensity(pins, region, grid_size, neighbor, "stdcell", "stdcell_pin_density.csv"); + return evalPinDensity(pins, region, grid_size, neighbor, "stdcell", stage + "_stdcell_pin_density.csv"); } -std::string DensityEval::evalAllCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalAllCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalPinDensity(pins, region, grid_size, neighbor, "all", "allcell_pin_density.csv"); + return evalPinDensity(pins, region, grid_size, neighbor, "all", stage + "_allcell_pin_density.csv"); } -std::string DensityEval::evalLocalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalLocalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalNetDensity(nets, region, grid_size, neighbor, "local", "local_net_density.csv"); + return evalNetDensity(nets, region, grid_size, neighbor, "local", stage + "_local_net_density.csv"); } -std::string DensityEval::evalGlobalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalGlobalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalNetDensity(nets, region, grid_size, neighbor, "global", "global_net_density.csv"); + return evalNetDensity(nets, region, grid_size, neighbor, "global", stage + "_global_net_density.csv"); } -std::string DensityEval::evalAllNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor) +std::string DensityEval::evalAllNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor) { - return evalNetDensity(nets, region, grid_size, neighbor, "all", "allnet_density.csv"); + return evalNetDensity(nets, region, grid_size, neighbor, "all", stage + "_allnet_density.csv"); } std::string DensityEval::evalHorizonMargin(DensityCells cells, DensityRegion die, DensityRegion core, int32_t grid_size) diff --git a/src/evaluation/src/module/density/density_eval.h b/src/evaluation/src/module/density/density_eval.h index 4ca3dab3a..3a5267a03 100644 --- a/src/evaluation/src/module/density/density_eval.h +++ b/src/evaluation/src/module/density/density_eval.h @@ -27,17 +27,17 @@ class DensityEval static DensityEval* getInst(); static void destroyInst(); - std::string evalMacroDensity(DensityCells cells, DensityRegion region, int32_t grid_size); - std::string evalStdCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size); - std::string evalAllCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size); + std::string evalMacroDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage); + std::string evalStdCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage); + std::string evalAllCellDensity(DensityCells cells, DensityRegion region, int32_t grid_size, std::string stage); - std::string evalMacroPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor); - std::string evalStdCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor); - std::string evalAllCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, bool neighbor); + std::string evalMacroPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); + std::string evalStdCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); + std::string evalAllCellPinDensity(DensityPins pins, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); - std::string evalLocalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor); - std::string evalGlobalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor); - std::string evalAllNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, bool neighbor); + std::string evalLocalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); + std::string evalGlobalNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); + std::string evalAllNetDensity(DensityNets nets, DensityRegion region, int32_t grid_size, std::string stage, bool neighbor); std::string evalHorizonMargin(DensityCells cells, DensityRegion die, DensityRegion core, int32_t grid_size); std::string evalVerticalMargin(DensityCells cells, DensityRegion die, DensityRegion core, int32_t grid_size); diff --git a/src/evaluation/src/module/timing/timing_eval.cc b/src/evaluation/src/module/timing/timing_eval.cc index d20bcf0d3..01111e723 100644 --- a/src/evaluation/src/module/timing/timing_eval.cc +++ b/src/evaluation/src/module/timing/timing_eval.cc @@ -26,6 +26,11 @@ void TimingEval::runSTA() EVAL_INIT_STA_INST->runSTA(); } +void TimingEval::evalTiming(const std::string& routing_type, const bool& rt_done) +{ + EVAL_INIT_STA_INST->evalTiming(routing_type, rt_done); +} + void TimingEval::destroyInst() { delete _timing_eval; @@ -111,4 +116,9 @@ void TimingEval::updateTiming(const std::vector& timing_net_list, co EVAL_INIT_STA_INST->updateTiming(timing_net_list, name_list, propagation_level, dbu_unit); } +bool TimingEval::isClockNet(const std::string& net_name) const +{ + return EVAL_INIT_STA_INST->isClockNet(net_name); +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/module/timing/timing_eval.hh b/src/evaluation/src/module/timing/timing_eval.hh index 22377157e..7847afccb 100644 --- a/src/evaluation/src/module/timing/timing_eval.hh +++ b/src/evaluation/src/module/timing/timing_eval.hh @@ -5,6 +5,9 @@ * @date 2024-08-28 * @brief evaluation with timing & power */ + +#pragma once + #include #include #include @@ -23,7 +26,8 @@ class TimingEval ~TimingEval() = default; static TimingEval* getInst(); - static void runSTA(); + void runSTA(); + void evalTiming(const std::string& routing_type, const bool& rt_done = false); static void destroyInst(); @@ -44,6 +48,8 @@ class TimingEval void updateTiming(const std::vector& timing_net_list, const std::vector& name_list, const int& propagation_level, int32_t dbu_unit); + bool isClockNet(const std::string& net_name) const; + private: static TimingEval* _timing_eval; }; diff --git a/src/evaluation/src/module/wirelength/wirelength_eval.cpp b/src/evaluation/src/module/wirelength/wirelength_eval.cpp index d159242e8..8c0a994d6 100644 --- a/src/evaluation/src/module/wirelength/wirelength_eval.cpp +++ b/src/evaluation/src/module/wirelength/wirelength_eval.cpp @@ -115,7 +115,7 @@ int32_t WirelengthEval::evalTotalVTree() int32_t WirelengthEval::evalTotalEGRWL() { - return evalTotalEGRWL(EVAL_INIT_EGR_INST->getEGRDirPath() + "/initial_router/route.guide"); + return evalTotalEGRWL(EVAL_INIT_EGR_INST->getEGRDirPath() + "/early_router/route.guide"); } int32_t WirelengthEval::evalNetHPWL(PointSet point_set) @@ -429,10 +429,11 @@ void WirelengthEval::destroyFlute() void WirelengthEval::evalNetInfo() { auto name_pointset = getNamePointSet(); + EVAL_INIT_EGR_INST->parseGuideFile(EVAL_INIT_EGR_INST->getEGRDirPath() + "/early_router/route.guide"); for (const auto& [net_name, point_set] : name_pointset) { _name_hpwl[net_name] = evalNetHPWL(point_set); _name_flute[net_name] = evalNetFLUTE(point_set); - _name_grwl[net_name] = evalNetEGRWL(EVAL_INIT_EGR_INST->getEGRDirPath() + "/initial_router/route.guide", net_name) * getDesignUnit(); + _name_grwl[net_name] = EVAL_INIT_EGR_INST->getNetEGRWL(net_name) * getDesignUnit(); } } diff --git a/src/evaluation/src/util/init_egr.cpp b/src/evaluation/src/util/init_egr.cpp index 9f70a6e5f..b8b9ef781 100644 --- a/src/evaluation/src/util/init_egr.cpp +++ b/src/evaluation/src/util/init_egr.cpp @@ -48,12 +48,21 @@ void InitEGR::destroyInst() } } -void InitEGR::runEGR() +void InitEGR::runEGR(bool enable_timing) { irt::RTInterface& rt_interface = irt::RTInterface::getInst(); + auto* idb_layout = dmInst->get_idb_lef_service()->get_layout(); + auto routing_layers = idb_layout->get_layers()->get_routing_layers(); + auto logic_layer_name = routing_layers.size() >= 2 ? routing_layers[1]->get_name() : routing_layers[0]->get_name(); + auto clock_layer_name = routing_layers.size() >= 4 ? routing_layers[routing_layers.size() - 4]->get_name() : logic_layer_name; std::map config_map; config_map.insert({"-temp_directory_path", _egr_dir_path}); config_map.insert({"-output_inter_result", 1}); + config_map.insert({"-bottom_routing_layer", logic_layer_name}); // only for 28nm + config_map.insert({"-top_routing_layer", clock_layer_name}); // only for 28nm + if (enable_timing == true) { + config_map.insert({"-enable_timing", 1}); + } rt_interface.initRT(config_map); rt_interface.runEGR(); rt_interface.destroyRT(); @@ -61,18 +70,25 @@ void InitEGR::runEGR() float InitEGR::parseEGRWL(std::string guide_path) { - float egr_wl = 0; + parseGuideFile(guide_path); + float total_egr_wl = 0.0; + for (const auto& net : _net_lengths) { + total_egr_wl += net.second; + } + return total_egr_wl; +} + +void InitEGR::parseGuideFile(const std::string& guide_path) +{ + _net_lengths.clear(); std::ifstream file(guide_path); std::string line; - std::map net_lengths; std::string current_net; struct Wire { - int gx1, gy1, gx2, gy2; float rx1, ry1, rx2, ry2; - std::string layer; }; for (int i = 0; i < 4; ++i) { @@ -86,24 +102,18 @@ float InitEGR::parseEGRWL(std::string guide_path) if (type == "guide") { iss >> current_net; - if (net_lengths.find(current_net) == net_lengths.end()) { - net_lengths[current_net] = 0.0; + if (_net_lengths.find(current_net) == _net_lengths.end()) { + _net_lengths[current_net] = 0.0; } } else if (type == "wire") { Wire wire; - iss >> wire.gx1 >> wire.gy1 >> wire.gx2 >> wire.gy2 >> wire.rx1 >> wire.ry1 >> wire.rx2 >> wire.ry2 >> wire.layer; - float wire_length = fabs(wire.rx1 - wire.rx2) + fabs(wire.ry1 - wire.ry2); - net_lengths[current_net] += wire_length; + int gx1, gy1, gx2, gy2; + std::string layer; + iss >> gx1 >> gy1 >> gx2 >> gy2 >> wire.rx1 >> wire.ry1 >> wire.rx2 >> wire.ry2 >> layer; + float wire_length = std::abs(wire.rx1 - wire.rx2) + std::abs(wire.ry1 - wire.ry2); + _net_lengths[current_net] += wire_length; } } - - for (const auto& net : net_lengths) { - // std::cout << "Net " << net.first << " wire length: " << net.second << std::endl; - egr_wl += net.second; - } - - // std::cout << "Total wire length for all nets: " << egr_wl << std::endl; - return egr_wl; } float InitEGR::parseNetEGRWL(std::string guide_path, std::string net_name) @@ -274,4 +284,13 @@ std::unordered_map InitEGR::parseLayerDirection(std return layer_directions; } +float InitEGR::getNetEGRWL(std::string net_name) +{ + auto it = _net_lengths.find(net_name); + if (it != _net_lengths.end()) { + return it->second; + } + return 0.0; +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/util/init_egr.h b/src/evaluation/src/util/init_egr.h index 33ac5af95..cf91c09c9 100644 --- a/src/evaluation/src/util/init_egr.h +++ b/src/evaluation/src/util/init_egr.h @@ -26,9 +26,12 @@ class InitEGR static InitEGR* getInst(); static void destroyInst(); - void runEGR(); + void runEGR(bool enable_timing = false); std::string getEGRDirPath() { return _egr_dir_path; } + void setEGRDirPath(std::string egr_dir_path) { _egr_dir_path = egr_dir_path; } + float getNetEGRWL(std::string net_name); + void parseGuideFile(const std::string& guide_path); float parseEGRWL(std::string guide_path); float parseNetEGRWL(std::string guide_path, std::string net_name); float parsePathEGRWL(std::string guide_path, std::string net_name, std::string load_name); @@ -37,8 +40,8 @@ class InitEGR private: static InitEGR* _init_egr; - std::string _egr_dir_path; + std::unordered_map _net_lengths; }; } // namespace ieval diff --git a/src/evaluation/src/util/init_sta.cc b/src/evaluation/src/util/init_sta.cc index 6b0891af7..d2f8488ee 100644 --- a/src/evaluation/src/util/init_sta.cc +++ b/src/evaluation/src/util/init_sta.cc @@ -27,7 +27,6 @@ #include "api/PowerEngine.hh" #include "api/TimingEngine.hh" #include "api/TimingIDBAdapter.hh" -#include "feature_irt.h" #include "idm.h" #include "salt/base/flute.h" #include "salt/salt.h" @@ -62,10 +61,6 @@ void InitSTA::destroyInst() void InitSTA::runSTA() { - if (_sta_init) { - return; - } - _sta_init = true; // auto routing_type_list = {"WLM", "HPWL", "FLUTE", "SALT", "EGR", "DR"} initStaEngine(); auto routing_type_list = {"HPWL", "FLUTE", "SALT", "EGR", "DR"}; @@ -79,6 +74,136 @@ void InitSTA::runSTA() }); } +void InitSTA::evalTiming(const std::string& routing_type, const bool& rt_done) +{ + initStaEngine(); + if (routing_type == "EGR" || routing_type == "DR") { + if (!rt_done) { + callRT(routing_type); + } + } else { + buildRCTree(routing_type); + } + + updateResult(routing_type); +} + +void InitSTA::leaglization(const std::vector>& pins) +{ + if (pins.empty()) { + return; + } + + std::set> loc_set; + bool is_legal = true; + for (size_t i = 0; i < pins.size(); ++i) { + if (loc_set.contains(std::make_pair(pins[i]->loc.x, pins[i]->loc.y))) { + is_legal = false; + break; + } + loc_set.insert(std::make_pair(pins[i]->loc.x, pins[i]->loc.y)); + } + if (is_legal) { + return; + } + + // find all duplicated locations, and move them to a new location, objective: no duplicated locations and minimum total movement + // x: pin->loc.x + // y: pin->loc.y + // Step 1: Group pins by their (x, y) locations + std::map, std::vector>> loc_map; + for (const auto& pin : pins) { + std::pair coord = {pin->loc.x, pin->loc.y}; + loc_map[coord].push_back(pin); + } + + // Step 2: Initialize a set to keep track of occupied locations + std::unordered_set occupied; + // Helper lambda to encode (x, y) into a unique key + auto encode = [](int x, int y) -> long long { + // Assuming x and y are within reasonable bounds to prevent overflow + return static_cast(x) * 100000000 + y; + }; + + // Populate the occupied set with initial locations + for (const auto& [coord, pin_list] : loc_map) { + occupied.insert(encode(coord.first, coord.second)); + } + + // Step 3: Collect all pins that need to be moved + std::vector> pins_to_move; + for (const auto& [coord, pin_list] : loc_map) { + if (pin_list.size() > 1) { + // Keep the first pin, move the rest + for (size_t i = 1; i < pin_list.size(); ++i) { + pins_to_move.push_back(pin_list[i]); + } + } + } + + // Step 4: Define directions for BFS (8-connected grid) + const std::vector> directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; + + // Step 5: For each pin to move, find the nearest available location + for (const auto& pin : pins_to_move) { + int start_x = pin->loc.x; + int start_y = pin->loc.y; + + // BFS initialization + std::queue> q; + std::unordered_set visited; + q.push({start_x, start_y}); + visited.insert(encode(start_x, start_y)); + + bool found = false; + int new_x = start_x; + int new_y = start_y; + + while (!q.empty() && !found) { + int current_level_size = q.size(); + for (int i = 0; i < current_level_size; ++i) { + auto [x, y] = q.front(); + q.pop(); + + // Explore all directions + for (const auto& [dx, dy] : directions) { + int nx = x + dx; + int ny = y + dy; + long long key = encode(nx, ny); + + if (visited.find(key) == visited.end()) { + // Check if the location is free + if (occupied.find(key) == occupied.end()) { + // Found a free location + new_x = nx; + new_y = ny; + occupied.insert(key); + found = true; + break; + } + // Mark as visited and add to queue for further exploration + visited.insert(key); + q.push({nx, ny}); + } + } + if (found) + break; + } + } + + if (!found) { + // If no free location found in the immediate vicinity, expand the search + // This can be optimized or have a maximum search radius + // For simplicity, we'll assign a far away location + LOG_FATAL << "No free location found for pin x=" << start_x << ", y=" << start_y; + } + + // Update the pin's location + pin->loc.x = new_x; + pin->loc.y = new_y; + } +} + void InitSTA::initStaEngine() { if (STA_INST->isBuildGraph()) { @@ -100,8 +225,8 @@ void InitSTA::callRT(const std::string& routing_type) auto* idb_layout = dmInst->get_idb_lef_service()->get_layout(); auto routing_layers = idb_layout->get_layers()->get_routing_layers(); auto logic_layer_name = routing_layers.size() >= 2 ? routing_layers[1]->get_name() : routing_layers[0]->get_name(); - auto clock_layer_name = routing_layers.size() >= 3 ? routing_layers[routing_layers.size() - 3]->get_name() : logic_layer_name; - // Hard Code, consider the clock layer is the last 3rd layer + auto clock_layer_name = routing_layers.size() >= 4 ? routing_layers[routing_layers.size() - 4]->get_name() : logic_layer_name; + // Hard Code, consider the clock layer is the last 4rd layer const std::string temp_path = dmInst->get_config().get_output_path() + "/rt/rt_temp_directory"; config_map.insert({"-temp_directory_path", temp_path}); config_map.insert({"-bottom_routing_layer", logic_layer_name}); @@ -143,7 +268,7 @@ void InitSTA::buildRCTree(const std::string& routing_type) auto routing_layers = idb_layout->get_layers()->get_routing_layers(); auto logic_layer = routing_layers.size() >= 2 ? 2 : 1; auto clock_layer - = routing_layers.size() >= 3 ? routing_layers.size() - 3 : logic_layer; // Hard Code, consider the clock layer is the last 3rd layer + = routing_layers.size() >= 4 ? routing_layers.size() - 4 : logic_layer; // Hard Code, consider the clock layer is the last 3rd layer auto calc_res = [&](const bool& is_clock, const double& wirelength) { if (!is_clock) { return idb_adapter->getResistance(logic_layer, wirelength, width); @@ -166,13 +291,17 @@ void InitSTA::buildRCTree(const std::string& routing_type) // WLM if (routing_type == "WLM") { LOG_ERROR << "STA does not support WLM, TBD..."; + auto loads = sta_net->getLoads(); + + if (loads.empty()) { + continue; + } auto* driver = sta_net->getDriver(); auto front_node = STA_INST->makeOrFindRCTreeNode(driver); double res = 0; // rc TBD double cap = 0; // rc TBD - auto loads = sta_net->getLoads(); for (auto load : loads) { auto back_node = STA_INST->makeOrFindRCTreeNode(load); STA_INST->makeResistor(sta_net, front_node, back_node, res); @@ -182,11 +311,16 @@ void InitSTA::buildRCTree(const std::string& routing_type) } if (routing_type == "HPWL") { + auto loads = sta_net->getLoads(); + + if (loads.empty()) { + continue; + } + auto* driver = sta_net->getDriver(); auto driver_loc = idb_adapter->idbLocation(driver); auto front_node = STA_INST->makeOrFindRCTreeNode(driver); - auto loads = sta_net->getLoads(); for (auto load : loads) { auto load_loc = idb_adapter->idbLocation(load); auto wirelength = calc_length(driver_loc->get_x(), driver_loc->get_y(), load_loc->get_x(), load_loc->get_y()); @@ -202,7 +336,9 @@ void InitSTA::buildRCTree(const std::string& routing_type) if (routing_type == "FLUTE" || routing_type == "SALT") { std::vector pin_ports = {sta_net->getDriver()}; std::ranges::copy(sta_net->getLoads(), std::back_inserter(pin_ports)); - + if (pin_ports.size() < 2) { + continue; + } // makr rc node auto make_rc_node = [&](const std::shared_ptr& salt_node) { if (salt_node->pin) { @@ -222,6 +358,7 @@ void InitSTA::buildRCTree(const std::string& routing_type) auto pin = std::make_shared(idb_loc->get_x(), idb_loc->get_y(), i); salt_pins.push_back(pin); } + leaglization(salt_pins); salt::Net salt_net; salt_net.init(0, sta_net->get_name(), salt_pins); @@ -562,4 +699,9 @@ void InitSTA::updateTiming(const std::vector& timing_net_list, const STA_INST->updateTiming(); } +bool InitSTA::isClockNet(const std::string& net_name) const +{ + return STA_INST->isClockNet(net_name.c_str()); +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/util/init_sta.hh b/src/evaluation/src/util/init_sta.hh index 150328d13..30740d2fa 100644 --- a/src/evaluation/src/util/init_sta.hh +++ b/src/evaluation/src/util/init_sta.hh @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include #include @@ -31,6 +32,9 @@ namespace ista { enum class AnalysisMode; } +namespace salt { +class Pin; +} namespace ieval { struct TimingNet; @@ -43,6 +47,7 @@ class InitSTA static InitSTA* getInst(); static void destroyInst(); void runSTA(); + void evalTiming(const std::string& routing_type, const bool& rt_done = false); std::map>> getTiming() const { return _timing; } std::map> getPower() const { return _power; } @@ -62,7 +67,10 @@ class InitSTA void updateTiming(const std::vector& timing_net_list, const std::vector& name_list, const int& propagation_level, int32_t dbu_unit); + bool isClockNet(const std::string& net_name) const; + private: + void leaglization(const std::vector>& pins); void initStaEngine(); void callRT(const std::string& routing_type); void buildRCTree(const std::string& routing_type); @@ -72,7 +80,6 @@ class InitSTA static InitSTA* _init_sta; - bool _sta_init = false; std::map>> _timing; std::map> _power; std::map> _net_power; diff --git a/src/feature/builder/CMakeLists.txt b/src/feature/builder/CMakeLists.txt index ad790ed79..3e90c7284 100644 --- a/src/feature/builder/CMakeLists.txt +++ b/src/feature/builder/CMakeLists.txt @@ -7,6 +7,8 @@ add_library(feature_builder feature_eval_congestion.cpp feature_eval_density.cpp feature_eval_timing.cc + + feature_eval_union.cpp ) target_include_directories(feature_builder @@ -30,4 +32,5 @@ target_link_libraries(feature_builder eval_density_api eval_wirelength_api eval_timing_api + eval_union_api ) \ No newline at end of file diff --git a/src/feature/builder/feature_builder.h b/src/feature/builder/feature_builder.h index 7861d368c..ed5e12e49 100644 --- a/src/feature/builder/feature_builder.h +++ b/src/feature/builder/feature_builder.h @@ -63,6 +63,13 @@ class FeatureBuilder DensityMapSummary buildDensityEvalSummary(int32_t grid_size); CongestionSummary buildCongestionEvalSummary(int32_t grid_size); TimingEvalSummary buildTimingEvalSummary(); + TimingEvalSummary buildTimingUnionEvalSummary(); + void evalTiming(const std::string& routing_type, const bool& rt_done = false); + + bool initEvalTool(); + UnionEvalSummary buildUnionEvalSummary(int32_t grid_size, std::string stage); + bool buildNetEval(std::string csv_path); + bool destroyEvalTool(); bool buildRouteData(RouteAnalyseData* data); diff --git a/src/feature/builder/feature_builder_tool.cpp b/src/feature/builder/feature_builder_tool.cpp index 242a3754d..2c36135d9 100644 --- a/src/feature/builder/feature_builder_tool.cpp +++ b/src/feature/builder/feature_builder_tool.cpp @@ -49,9 +49,9 @@ PlaceSummary FeatureBuilder::buildPLSummary(std::string step) RTSummary FeatureBuilder::buildRTSummary() { - RTSummary summary = RTI.outputSummary(); + // RTSummary summary = RTI.getSummary(); - return summary; + // return summary; } CTSSummary FeatureBuilder::buildCTSSummary() @@ -71,7 +71,7 @@ NetOptSummary FeatureBuilder::buildNetOptSummary() TimingOptSummary FeatureBuilder::buildTimingOptSummary() { TimingOptSummary summary = ToApiInst.outputSummary(); - + return summary; } diff --git a/src/feature/builder/feature_eval_congestion.cpp b/src/feature/builder/feature_eval_congestion.cpp index 5e6fea233..1b381b0ae 100644 --- a/src/feature/builder/feature_eval_congestion.cpp +++ b/src/feature/builder/feature_eval_congestion.cpp @@ -14,51 +14,52 @@ CongestionSummary FeatureBuilder::buildCongestionEvalSummary(int32_t grid_size) { CongestionSummary congestion_summary; - ieval::EGRMapSummary eval_egr_map_summary = CONGESTION_API_INST->egrMap(); - congestion_summary.egr_map_summary.horizontal_sum = eval_egr_map_summary.horizontal_sum; - congestion_summary.egr_map_summary.vertical_sum = eval_egr_map_summary.vertical_sum; - congestion_summary.egr_map_summary.union_sum = eval_egr_map_summary.union_sum; + // ieval::EGRMapSummary eval_egr_map_summary = CONGESTION_API_INST->egrMap(); + // congestion_summary.egr_map_summary.horizontal_sum = eval_egr_map_summary.horizontal_sum; + // congestion_summary.egr_map_summary.vertical_sum = eval_egr_map_summary.vertical_sum; + // congestion_summary.egr_map_summary.union_sum = eval_egr_map_summary.union_sum; - ieval::RUDYMapSummary eval_rudy_map_summary = CONGESTION_API_INST->rudyMap(grid_size); - congestion_summary.rudy_map_summary.rudy_horizontal = eval_rudy_map_summary.rudy_horizontal; - congestion_summary.rudy_map_summary.rudy_vertical = eval_rudy_map_summary.rudy_vertical; - congestion_summary.rudy_map_summary.rudy_union = eval_rudy_map_summary.rudy_union; - congestion_summary.rudy_map_summary.lutrudy_horizontal = eval_rudy_map_summary.lutrudy_horizontal; - congestion_summary.rudy_map_summary.lutrudy_vertical = eval_rudy_map_summary.lutrudy_vertical; - congestion_summary.rudy_map_summary.lutrudy_union = eval_rudy_map_summary.lutrudy_union; + // ieval::RUDYMapSummary eval_rudy_map_summary = CONGESTION_API_INST->rudyMap(grid_size); + // congestion_summary.rudy_map_summary.rudy_horizontal = eval_rudy_map_summary.rudy_horizontal; + // congestion_summary.rudy_map_summary.rudy_vertical = eval_rudy_map_summary.rudy_vertical; + // congestion_summary.rudy_map_summary.rudy_union = eval_rudy_map_summary.rudy_union; + // congestion_summary.rudy_map_summary.lutrudy_horizontal = eval_rudy_map_summary.lutrudy_horizontal; + // congestion_summary.rudy_map_summary.lutrudy_vertical = eval_rudy_map_summary.lutrudy_vertical; + // congestion_summary.rudy_map_summary.lutrudy_union = eval_rudy_map_summary.lutrudy_union; - ieval::OverflowSummary eval_overflow_summary = CONGESTION_API_INST->egrOverflow(); - congestion_summary.overflow_summary.total_overflow_horizontal = eval_overflow_summary.total_overflow_horizontal; - congestion_summary.overflow_summary.total_overflow_vertical = eval_overflow_summary.total_overflow_vertical; - congestion_summary.overflow_summary.total_overflow_union = eval_overflow_summary.total_overflow_union; - congestion_summary.overflow_summary.max_overflow_horizontal = eval_overflow_summary.max_overflow_horizontal; - congestion_summary.overflow_summary.max_overflow_vertical = eval_overflow_summary.max_overflow_vertical; - congestion_summary.overflow_summary.max_overflow_union = eval_overflow_summary.max_overflow_union; - congestion_summary.overflow_summary.weighted_average_overflow_horizontal = eval_overflow_summary.weighted_average_overflow_horizontal; - congestion_summary.overflow_summary.weighted_average_overflow_vertical = eval_overflow_summary.weighted_average_overflow_vertical; - congestion_summary.overflow_summary.weighted_average_overflow_union = eval_overflow_summary.weighted_average_overflow_union; + // ieval::OverflowSummary eval_overflow_summary = CONGESTION_API_INST->egrOverflow(); + // congestion_summary.overflow_summary.total_overflow_horizontal = eval_overflow_summary.total_overflow_horizontal; + // congestion_summary.overflow_summary.total_overflow_vertical = eval_overflow_summary.total_overflow_vertical; + // congestion_summary.overflow_summary.total_overflow_union = eval_overflow_summary.total_overflow_union; + // congestion_summary.overflow_summary.max_overflow_horizontal = eval_overflow_summary.max_overflow_horizontal; + // congestion_summary.overflow_summary.max_overflow_vertical = eval_overflow_summary.max_overflow_vertical; + // congestion_summary.overflow_summary.max_overflow_union = eval_overflow_summary.max_overflow_union; + // congestion_summary.overflow_summary.weighted_average_overflow_horizontal = + // eval_overflow_summary.weighted_average_overflow_horizontal; congestion_summary.overflow_summary.weighted_average_overflow_vertical = + // eval_overflow_summary.weighted_average_overflow_vertical; congestion_summary.overflow_summary.weighted_average_overflow_union = + // eval_overflow_summary.weighted_average_overflow_union; - ieval::UtilizationSummary eval_utilization_summary = CONGESTION_API_INST->rudyUtilization(false); - congestion_summary.rudy_utilization_summary.max_utilization_horizontal = eval_utilization_summary.max_utilization_horizontal; - congestion_summary.rudy_utilization_summary.max_utilization_vertical = eval_utilization_summary.max_utilization_vertical; - congestion_summary.rudy_utilization_summary.max_utilization_union = eval_utilization_summary.max_utilization_union; - congestion_summary.rudy_utilization_summary.weighted_average_utilization_horizontal - = eval_utilization_summary.weighted_average_utilization_horizontal; - congestion_summary.rudy_utilization_summary.weighted_average_utilization_vertical - = eval_utilization_summary.weighted_average_utilization_vertical; - congestion_summary.rudy_utilization_summary.weighted_average_utilization_union - = eval_utilization_summary.weighted_average_utilization_union; + // ieval::UtilizationSummary eval_utilization_summary = CONGESTION_API_INST->rudyUtilization(false); + // congestion_summary.rudy_utilization_summary.max_utilization_horizontal = eval_utilization_summary.max_utilization_horizontal; + // congestion_summary.rudy_utilization_summary.max_utilization_vertical = eval_utilization_summary.max_utilization_vertical; + // congestion_summary.rudy_utilization_summary.max_utilization_union = eval_utilization_summary.max_utilization_union; + // congestion_summary.rudy_utilization_summary.weighted_average_utilization_horizontal + // = eval_utilization_summary.weighted_average_utilization_horizontal; + // congestion_summary.rudy_utilization_summary.weighted_average_utilization_vertical + // = eval_utilization_summary.weighted_average_utilization_vertical; + // congestion_summary.rudy_utilization_summary.weighted_average_utilization_union + // = eval_utilization_summary.weighted_average_utilization_union; - ieval::UtilizationSummary eval_lut_utilization_summary = CONGESTION_API_INST->rudyUtilization(true); - congestion_summary.lutrudy_utilization_summary.max_utilization_horizontal = eval_lut_utilization_summary.max_utilization_horizontal; - congestion_summary.lutrudy_utilization_summary.max_utilization_vertical = eval_lut_utilization_summary.max_utilization_vertical; - congestion_summary.lutrudy_utilization_summary.max_utilization_union = eval_lut_utilization_summary.max_utilization_union; - congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_horizontal - = eval_lut_utilization_summary.weighted_average_utilization_horizontal; - congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_vertical - = eval_lut_utilization_summary.weighted_average_utilization_vertical; - congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_union - = eval_lut_utilization_summary.weighted_average_utilization_union; + // ieval::UtilizationSummary eval_lut_utilization_summary = CONGESTION_API_INST->rudyUtilization(true); + // congestion_summary.lutrudy_utilization_summary.max_utilization_horizontal = eval_lut_utilization_summary.max_utilization_horizontal; + // congestion_summary.lutrudy_utilization_summary.max_utilization_vertical = eval_lut_utilization_summary.max_utilization_vertical; + // congestion_summary.lutrudy_utilization_summary.max_utilization_union = eval_lut_utilization_summary.max_utilization_union; + // congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_horizontal + // = eval_lut_utilization_summary.weighted_average_utilization_horizontal; + // congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_vertical + // = eval_lut_utilization_summary.weighted_average_utilization_vertical; + // congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_union + // = eval_lut_utilization_summary.weighted_average_utilization_union; return congestion_summary; } diff --git a/src/feature/builder/feature_eval_density.cpp b/src/feature/builder/feature_eval_density.cpp index 93ce46ba6..2f0ef4b24 100644 --- a/src/feature/builder/feature_eval_density.cpp +++ b/src/feature/builder/feature_eval_density.cpp @@ -14,21 +14,21 @@ DensityMapSummary FeatureBuilder::buildDensityEvalSummary(int32_t grid_size) { DensityMapSummary density_map_summary; - ieval::DensityMapSummary eval_density_map_summary = DENSITY_API_INST->densityMap(grid_size); - density_map_summary.cell_map_summary.macro_density = eval_density_map_summary.cell_map_summary.macro_density; - density_map_summary.cell_map_summary.stdcell_density = eval_density_map_summary.cell_map_summary.stdcell_density; - density_map_summary.cell_map_summary.allcell_density = eval_density_map_summary.cell_map_summary.allcell_density; - density_map_summary.pin_map_summary.macro_pin_density = eval_density_map_summary.pin_map_summary.macro_pin_density; - density_map_summary.pin_map_summary.stdcell_pin_density = eval_density_map_summary.pin_map_summary.stdcell_pin_density; - density_map_summary.pin_map_summary.allcell_pin_density = eval_density_map_summary.pin_map_summary.allcell_pin_density; - density_map_summary.net_map_summary.local_net_density = eval_density_map_summary.net_map_summary.local_net_density; - density_map_summary.net_map_summary.global_net_density = eval_density_map_summary.net_map_summary.global_net_density; - density_map_summary.net_map_summary.allnet_density = eval_density_map_summary.net_map_summary.allnet_density; - - ieval::MacroMarginSummary eval_macro_margin_summary = DENSITY_API_INST->macroMarginMap(grid_size); - density_map_summary.macro_margin_summary.horizontal_margin = eval_macro_margin_summary.horizontal_margin; - density_map_summary.macro_margin_summary.vertical_margin = eval_macro_margin_summary.vertical_margin; - density_map_summary.macro_margin_summary.union_margin = eval_macro_margin_summary.union_margin; + // ieval::DensityMapSummary eval_density_map_summary = DENSITY_API_INST->densityMap(grid_size); + // density_map_summary.cell_map_summary.macro_density = eval_density_map_summary.cell_map_summary.macro_density; + // density_map_summary.cell_map_summary.stdcell_density = eval_density_map_summary.cell_map_summary.stdcell_density; + // density_map_summary.cell_map_summary.allcell_density = eval_density_map_summary.cell_map_summary.allcell_density; + // density_map_summary.pin_map_summary.macro_pin_density = eval_density_map_summary.pin_map_summary.macro_pin_density; + // density_map_summary.pin_map_summary.stdcell_pin_density = eval_density_map_summary.pin_map_summary.stdcell_pin_density; + // density_map_summary.pin_map_summary.allcell_pin_density = eval_density_map_summary.pin_map_summary.allcell_pin_density; + // density_map_summary.net_map_summary.local_net_density = eval_density_map_summary.net_map_summary.local_net_density; + // density_map_summary.net_map_summary.global_net_density = eval_density_map_summary.net_map_summary.global_net_density; + // density_map_summary.net_map_summary.allnet_density = eval_density_map_summary.net_map_summary.allnet_density; + + // ieval::MacroMarginSummary eval_macro_margin_summary = DENSITY_API_INST->macroMarginMap(grid_size); + // density_map_summary.macro_margin_summary.horizontal_margin = eval_macro_margin_summary.horizontal_margin; + // density_map_summary.macro_margin_summary.vertical_margin = eval_macro_margin_summary.vertical_margin; + // density_map_summary.macro_margin_summary.union_margin = eval_macro_margin_summary.union_margin; return density_map_summary; } diff --git a/src/feature/builder/feature_eval_timing.cc b/src/feature/builder/feature_eval_timing.cc index 68ff97414..3d1c1f227 100644 --- a/src/feature/builder/feature_eval_timing.cc +++ b/src/feature/builder/feature_eval_timing.cc @@ -77,4 +77,74 @@ TimingEvalSummary FeatureBuilder::buildTimingEvalSummary() return timing_eval_summary; } +TimingEvalSummary FeatureBuilder::buildTimingUnionEvalSummary() +{ + TimingEvalSummary timing_eval_summary; + auto timing_summary = EVAL_STA_API_INST->evalDesign(); + if (timing_summary.contains("WLM")) { + WlmTimingEvalSummary wlm_timing_eval_summary; + auto wlm_timing_summary = timing_summary.at("WLM"); + std::ranges::for_each(wlm_timing_summary.clock_timings, [&wlm_timing_eval_summary](const auto& clock_timing) { + wlm_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + wlm_timing_eval_summary.power_info = {wlm_timing_summary.static_power, wlm_timing_summary.dynamic_power}; + timing_eval_summary.wlm_timing_eval_summary = wlm_timing_eval_summary; + } + if (timing_summary.contains("HPWL")) { + HpwlTimingEvalSummary hpwl_timing_eval_summary; + auto hpwl_timing_summary = timing_summary.at("HPWL"); + std::ranges::for_each(hpwl_timing_summary.clock_timings, [&hpwl_timing_eval_summary](const auto& clock_timing) { + hpwl_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + hpwl_timing_eval_summary.power_info = {hpwl_timing_summary.static_power, hpwl_timing_summary.dynamic_power}; + timing_eval_summary.hpwl_timing_eval_summary = hpwl_timing_eval_summary; + } + if (timing_summary.contains("FLUTE")) { + FluteTimingEvalSummary flute_timing_eval_summary; + auto flute_timing_summary = timing_summary.at("FLUTE"); + std::ranges::for_each(flute_timing_summary.clock_timings, [&flute_timing_eval_summary](const auto& clock_timing) { + flute_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + flute_timing_eval_summary.power_info = {flute_timing_summary.static_power, flute_timing_summary.dynamic_power}; + timing_eval_summary.flute_timing_eval_summary = flute_timing_eval_summary; + } + if (timing_summary.contains("SALT")) { + SaltTimingEvalSummary salt_timing_eval_summary; + auto salt_timing_summary = timing_summary.at("SALT"); + std::ranges::for_each(salt_timing_summary.clock_timings, [&salt_timing_eval_summary](const auto& clock_timing) { + salt_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + salt_timing_eval_summary.power_info = {salt_timing_summary.static_power, salt_timing_summary.dynamic_power}; + timing_eval_summary.salt_timing_eval_summary = salt_timing_eval_summary; + } + if (timing_summary.contains("EGR")) { + EgrTimingEvalSummary egr_timing_eval_summary; + auto egr_timing_summary = timing_summary.at("EGR"); + std::ranges::for_each(egr_timing_summary.clock_timings, [&egr_timing_eval_summary](const auto& clock_timing) { + egr_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + egr_timing_eval_summary.power_info = {egr_timing_summary.static_power, egr_timing_summary.dynamic_power}; + timing_eval_summary.egr_timing_eval_summary = egr_timing_eval_summary; + } + if (timing_summary.contains("DR")) { + DrTimingEvalSummary dr_timing_eval_summary; + auto dr_timing_summary = timing_summary.at("DR"); + std::ranges::for_each(dr_timing_summary.clock_timings, [&dr_timing_eval_summary](const auto& clock_timing) { + dr_timing_eval_summary.clock_timings.push_back({clock_timing.clock_name, clock_timing.setup_tns, clock_timing.setup_wns, + clock_timing.hold_tns, clock_timing.hold_wns, clock_timing.suggest_freq}); + }); + dr_timing_eval_summary.power_info = {dr_timing_summary.static_power, dr_timing_summary.dynamic_power}; + timing_eval_summary.dr_timing_eval_summary = dr_timing_eval_summary; + } + return timing_eval_summary; +} +void FeatureBuilder::evalTiming(const std::string& routing_type, const bool& rt_done) +{ + EVAL_STA_API_INST->evalTiming(routing_type, rt_done); +} } // namespace ieda_feature \ No newline at end of file diff --git a/src/feature/builder/feature_eval_union.cpp b/src/feature/builder/feature_eval_union.cpp new file mode 100644 index 000000000..5faa7f38a --- /dev/null +++ b/src/feature/builder/feature_eval_union.cpp @@ -0,0 +1,207 @@ +/* + * @FilePath: feature_eval_union.cpp + * @Author: Yihang Qiu (qiuyihang23@mails.ucas.ac.cn) + * @Date: 2024-10-11 11:00:07 + * @Description: + */ + +#include +#include +#include + +#include "congestion_api.h" +#include "density_api.h" +#include "feature_builder.h" +#include "idm.h" +#include "timing_api.hh" +#include "union_api.h" +#include "wirelength_api.h" + +namespace ieda_feature { + +UnionEvalSummary FeatureBuilder::buildUnionEvalSummary(int32_t grid_size, std::string stage) +{ + UnionEvalSummary union_eval_summary; + + TotalWLSummary total_wl_summary; + ieval::TotalWLSummary eval_total_wl_summary = WIRELENGTH_API_INST->totalWLPure(); + total_wl_summary.HPWL = eval_total_wl_summary.HPWL; + total_wl_summary.FLUTE = eval_total_wl_summary.FLUTE; + total_wl_summary.HTree = eval_total_wl_summary.HTree; + total_wl_summary.VTree = eval_total_wl_summary.VTree; + total_wl_summary.GRWL = eval_total_wl_summary.GRWL; + + DensityMapSummary density_map_summary; + ieval::DensityMapSummary eval_density_map_summary = DENSITY_API_INST->densityMapPure(stage, grid_size); + density_map_summary.cell_map_summary.macro_density = eval_density_map_summary.cell_map_summary.macro_density; + density_map_summary.cell_map_summary.stdcell_density = eval_density_map_summary.cell_map_summary.stdcell_density; + density_map_summary.cell_map_summary.allcell_density = eval_density_map_summary.cell_map_summary.allcell_density; + density_map_summary.pin_map_summary.macro_pin_density = eval_density_map_summary.pin_map_summary.macro_pin_density; + density_map_summary.pin_map_summary.stdcell_pin_density = eval_density_map_summary.pin_map_summary.stdcell_pin_density; + density_map_summary.pin_map_summary.allcell_pin_density = eval_density_map_summary.pin_map_summary.allcell_pin_density; + density_map_summary.net_map_summary.local_net_density = eval_density_map_summary.net_map_summary.local_net_density; + density_map_summary.net_map_summary.global_net_density = eval_density_map_summary.net_map_summary.global_net_density; + density_map_summary.net_map_summary.allnet_density = eval_density_map_summary.net_map_summary.allnet_density; + if (stage == "place") { + ieval::MacroMarginSummary eval_macro_margin_summary = DENSITY_API_INST->macroMarginMap(grid_size); + density_map_summary.macro_margin_summary.horizontal_margin = eval_macro_margin_summary.horizontal_margin; + density_map_summary.macro_margin_summary.vertical_margin = eval_macro_margin_summary.vertical_margin; + density_map_summary.macro_margin_summary.union_margin = eval_macro_margin_summary.union_margin; + } + + CongestionSummary congestion_summary; + ieval::EGRMapSummary eval_egr_map_summary = CONGESTION_API_INST->egrMapPure(stage); + congestion_summary.egr_map_summary.horizontal_sum = eval_egr_map_summary.horizontal_sum; + congestion_summary.egr_map_summary.vertical_sum = eval_egr_map_summary.vertical_sum; + congestion_summary.egr_map_summary.union_sum = eval_egr_map_summary.union_sum; + ieval::RUDYMapSummary eval_rudy_map_summary = CONGESTION_API_INST->rudyMapPure(stage, grid_size); + congestion_summary.rudy_map_summary.rudy_horizontal = eval_rudy_map_summary.rudy_horizontal; + congestion_summary.rudy_map_summary.rudy_vertical = eval_rudy_map_summary.rudy_vertical; + congestion_summary.rudy_map_summary.rudy_union = eval_rudy_map_summary.rudy_union; + congestion_summary.rudy_map_summary.lutrudy_horizontal = eval_rudy_map_summary.lutrudy_horizontal; + congestion_summary.rudy_map_summary.lutrudy_vertical = eval_rudy_map_summary.lutrudy_vertical; + congestion_summary.rudy_map_summary.lutrudy_union = eval_rudy_map_summary.lutrudy_union; + ieval::OverflowSummary eval_overflow_summary = CONGESTION_API_INST->egrOverflow(stage); + congestion_summary.overflow_summary.total_overflow_horizontal = eval_overflow_summary.total_overflow_horizontal; + congestion_summary.overflow_summary.total_overflow_vertical = eval_overflow_summary.total_overflow_vertical; + congestion_summary.overflow_summary.total_overflow_union = eval_overflow_summary.total_overflow_union; + congestion_summary.overflow_summary.max_overflow_horizontal = eval_overflow_summary.max_overflow_horizontal; + congestion_summary.overflow_summary.max_overflow_vertical = eval_overflow_summary.max_overflow_vertical; + congestion_summary.overflow_summary.max_overflow_union = eval_overflow_summary.max_overflow_union; + congestion_summary.overflow_summary.weighted_average_overflow_horizontal = eval_overflow_summary.weighted_average_overflow_horizontal; + congestion_summary.overflow_summary.weighted_average_overflow_vertical = eval_overflow_summary.weighted_average_overflow_vertical; + congestion_summary.overflow_summary.weighted_average_overflow_union = eval_overflow_summary.weighted_average_overflow_union; + ieval::UtilizationSummary eval_utilization_summary = CONGESTION_API_INST->rudyUtilization(stage, false); + congestion_summary.rudy_utilization_summary.max_utilization_horizontal = eval_utilization_summary.max_utilization_horizontal; + congestion_summary.rudy_utilization_summary.max_utilization_vertical = eval_utilization_summary.max_utilization_vertical; + congestion_summary.rudy_utilization_summary.max_utilization_union = eval_utilization_summary.max_utilization_union; + congestion_summary.rudy_utilization_summary.weighted_average_utilization_horizontal + = eval_utilization_summary.weighted_average_utilization_horizontal; + congestion_summary.rudy_utilization_summary.weighted_average_utilization_vertical + = eval_utilization_summary.weighted_average_utilization_vertical; + congestion_summary.rudy_utilization_summary.weighted_average_utilization_union + = eval_utilization_summary.weighted_average_utilization_union; + ieval::UtilizationSummary eval_lut_utilization_summary = CONGESTION_API_INST->rudyUtilization(stage, true); + congestion_summary.lutrudy_utilization_summary.max_utilization_horizontal = eval_lut_utilization_summary.max_utilization_horizontal; + congestion_summary.lutrudy_utilization_summary.max_utilization_vertical = eval_lut_utilization_summary.max_utilization_vertical; + congestion_summary.lutrudy_utilization_summary.max_utilization_union = eval_lut_utilization_summary.max_utilization_union; + congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_horizontal + = eval_lut_utilization_summary.weighted_average_utilization_horizontal; + congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_vertical + = eval_lut_utilization_summary.weighted_average_utilization_vertical; + congestion_summary.lutrudy_utilization_summary.weighted_average_utilization_union + = eval_lut_utilization_summary.weighted_average_utilization_union; + + union_eval_summary.total_wl_summary = total_wl_summary; + union_eval_summary.density_map_summary = density_map_summary; + union_eval_summary.congestion_summary = congestion_summary; + + return union_eval_summary; +} + +bool FeatureBuilder::initEvalTool() +{ + UNION_API_INST->initIDB(); + UNION_API_INST->initEGR(true); + UNION_API_INST->initFlute(); + + return true; +} + +bool FeatureBuilder::destroyEvalTool() +{ + UNION_API_INST->destroyIDB(); + UNION_API_INST->destroyEGR(); + UNION_API_INST->destroyFlute(); + UNION_API_INST->destroyInst(); + + return true; +} + +bool FeatureBuilder::buildNetEval(std::string csv_path) +{ + std::cout << "Building net evaluation data...\n"; + + auto* idb_builder = dmInst->get_idb_builder(); + idb::IdbDesign* idb_design = idb_builder->get_def_service()->get_design(); + + CONGESTION_API_INST->evalNetInfoPure(); + WIRELENGTH_API_INST->evalNetInfoPure(); + auto net_power_data = ieval::TimingAPI::getInst()->evalNetPower(); + + std::ofstream csv_file(csv_path, std::ios::out | std::ios::binary); + if (!csv_file) { + return false; + } + + csv_file << "net_name,net_type,pin_num,aspect_ratio,bbox_width,bbox_height,bbox_area,lx,ly,ux,uy,lness,hpwl,rsmt,grwl,hpwl_power,flute_" + "power,egr_power\n"; + + const size_t buffer_size = 1024 * 1024; // 1MB buffer + std::vector buffer(buffer_size); + csv_file.rdbuf()->pubsetbuf(buffer.data(), buffer_size); + + std::ostringstream oss; + oss.str().reserve(buffer_size); // Pre-allocate memory + + for (size_t i = 0; i < idb_design->get_net_list()->get_net_list().size(); i++) { + auto* idb_net = idb_design->get_net_list()->get_net_list()[i]; + std::string net_name = idb_net->get_net_name(); + std::string net_type; + + int pin_num = CONGESTION_API_INST->findPinNumber(net_name); + if (pin_num < 4) { + continue; + } + int aspect_ratio = CONGESTION_API_INST->findAspectRatio(net_name); + float l_ness = CONGESTION_API_INST->findLness(net_name); + int32_t bbox_width = CONGESTION_API_INST->findBBoxWidth(net_name); + int32_t bbox_height = CONGESTION_API_INST->findBBoxHeight(net_name); + int64_t bbox_area = CONGESTION_API_INST->findBBoxArea(net_name); + int32_t bbox_lx = CONGESTION_API_INST->findBBoxLx(net_name); + int32_t bbox_ly = CONGESTION_API_INST->findBBoxLy(net_name); + int32_t bbox_ux = CONGESTION_API_INST->findBBoxUx(net_name); + int32_t bbox_uy = CONGESTION_API_INST->findBBoxUy(net_name); + + int32_t hpwl = WIRELENGTH_API_INST->findNetHPWL(net_name); + int32_t flute = WIRELENGTH_API_INST->findNetFLUTE(net_name); + int32_t grwl = WIRELENGTH_API_INST->findNetGRWL(net_name); + + // Remove backslashes in net_name to match timing && power evaluation data + net_name.erase(std::remove(net_name.begin(), net_name.end(), '\\'), net_name.end()); + + if (ieval::TimingAPI::getInst()->isClockNet(net_name)) { + net_type = "clock"; + } else { + net_type = "signal"; + } + + if (net_power_data["HPWL"].find(net_name) == net_power_data["HPWL"].end() + || net_power_data["FLUTE"].find(net_name) == net_power_data["FLUTE"].end() + || net_power_data["EGR"].find(net_name) == net_power_data["EGR"].end()) { + std::cerr << "Error: net_name '" << net_name << "' not found in net_power_data.\n"; + std::exit(EXIT_FAILURE); + } + + double hpwl_power = net_power_data["HPWL"][net_name]; + double flute_power = net_power_data["FLUTE"][net_name]; + double egr_power = net_power_data["EGR"][net_name]; + + csv_file << net_name << ',' << net_type << "," << pin_num << ',' << aspect_ratio << ',' << bbox_width << "," << bbox_height << "," + << bbox_area << "," << bbox_lx << "," << bbox_ly << "," << bbox_ux << "," << bbox_uy << "," << l_ness << ',' << hpwl << ',' + << flute << ',' << grwl << ',' << hpwl_power << ',' << flute_power << "," << egr_power << '\n'; + + if (oss.tellp() >= buffer_size / 2) { + csv_file << oss.str(); + oss.str(""); + oss.clear(); + } + } + if (oss.tellp() > 0) { + csv_file << oss.str(); + } + csv_file.close(); + return true; +} + +} // namespace ieda_feature \ No newline at end of file diff --git a/src/feature/database/feature_ieval.h b/src/feature/database/feature_ieval.h index 54271933d..68b92c316 100644 --- a/src/feature/database/feature_ieval.h +++ b/src/feature/database/feature_ieval.h @@ -114,35 +114,28 @@ struct CongestionSummary UtilizationSummary rudy_utilization_summary; UtilizationSummary lutrudy_utilization_summary; }; -struct WlmTimingEvalSummary +struct TimingEvalSummaryBase { std::vector clock_timings; PowerInfo power_info; }; -struct HpwlTimingEvalSummary +struct WlmTimingEvalSummary : TimingEvalSummaryBase { - std::vector clock_timings; - PowerInfo power_info; }; -struct FluteTimingEvalSummary +struct HpwlTimingEvalSummary : TimingEvalSummaryBase { - std::vector clock_timings; - PowerInfo power_info; }; -struct SaltTimingEvalSummary +struct FluteTimingEvalSummary : TimingEvalSummaryBase { - std::vector clock_timings; - PowerInfo power_info; }; -struct EgrTimingEvalSummary +struct SaltTimingEvalSummary : TimingEvalSummaryBase { - std::vector clock_timings; - PowerInfo power_info; }; -struct DrTimingEvalSummary +struct EgrTimingEvalSummary : TimingEvalSummaryBase +{ +}; +struct DrTimingEvalSummary : TimingEvalSummaryBase { - std::vector clock_timings; - PowerInfo power_info; }; struct TimingEvalSummary { @@ -154,4 +147,12 @@ struct TimingEvalSummary DrTimingEvalSummary dr_timing_eval_summary; }; +struct UnionEvalSummary +{ + TotalWLSummary total_wl_summary; + DensityMapSummary density_map_summary; + CongestionSummary congestion_summary; + TimingEvalSummary timing_eval_summary; +}; + } // namespace ieda_feature diff --git a/src/feature/database/feature_ipl.h b/src/feature/database/feature_ipl.h index 0bc938e3f..64ca8f001 100644 --- a/src/feature/database/feature_ipl.h +++ b/src/feature/database/feature_ipl.h @@ -23,18 +23,18 @@ namespace ieda_feature { struct PLCommonSummary { float place_density; - float pin_density; - int64_t HPWL; - int64_t STWL; - int64_t GRWL; + // float pin_density; + // int64_t HPWL; + // int64_t STWL; + // int64_t GRWL; - int32_t egr_tof; - int32_t egr_mof; - float egr_ace; + // int32_t egr_tof; + // int32_t egr_mof; + // float egr_ace; - float tns; - float wns; - float suggest_freq; + // float tns; + // float wns; + // float suggest_freq; }; struct LGSummary diff --git a/src/feature/database/feature_irt.h b/src/feature/database/feature_irt.h index 770d10c86..f5b0fe9ca 100644 --- a/src/feature/database/feature_irt.h +++ b/src/feature/database/feature_irt.h @@ -39,7 +39,30 @@ struct SASummary int32_t total_supply = 0; }; -struct IRSummary +struct TGSummary +{ + int32_t total_demand = 0; + int32_t total_overflow = 0; + double total_wire_length = 0; + std::vector clocks_timing; + PowerInfo power_info; +}; + +struct LASummary +{ + std::map routing_demand_map; + int32_t total_demand = 0; + std::map routing_overflow_map; + int32_t total_overflow = 0; + std::map routing_wire_length_map; + double total_wire_length = 0; + std::map cut_via_num_map; + int32_t total_via_num = 0; + std::vector clocks_timing; + PowerInfo power_info; +}; + +struct ERSummary { std::map routing_demand_map; int32_t total_demand = 0; @@ -93,7 +116,9 @@ struct RTSummary { PASummary pa_summary; SASummary sa_summary; - IRSummary ir_summary; + TGSummary tg_summary; + LASummary la_summary; + ERSummary er_summary; std::map iter_gr_summary_map; TASummary ta_summary; std::map iter_dr_summary_map; diff --git a/src/feature/feature_manager.cpp b/src/feature/feature_manager.cpp index 589a354fa..9e9f3ba8e 100644 --- a/src/feature/feature_manager.cpp +++ b/src/feature/feature_manager.cpp @@ -63,6 +63,103 @@ bool FeatureManager::save_eval_summary(std::string path, int32_t grid_size) return feature_parser.buildSummaryEvalJsonl(path); } +bool FeatureManager::save_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size) +{ + FeatureBuilder builder; + + bool is_init_eval_tool = builder.initEvalTool(); + if (!is_init_eval_tool) { + return false; + } + + // auto union_db = builder.buildUnionEvalSummary(grid_size); + // _summary->set_wirelength_eval(union_db.total_wl_summary); + // _summary->set_density_eval(union_db.density_map_summary); + // _summary->set_congestion_eval(union_db.congestion_summary); + + bool csv_success = builder.buildNetEval(csv_path); + // bool csv_success = true; + + // FeatureParser feature_parser(_summary); + // bool jsonl_success = feature_parser.buildSummaryEvalJsonl(jsonl_path); + bool jsonl_success = true; + + builder.destroyEvalTool(); + + return jsonl_success && csv_success; +} + +bool FeatureManager::save_pl_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size) +{ + // EGR + FeatureBuilder builder; + + bool is_init_eval_tool = builder.initEvalTool(); + if (!is_init_eval_tool) { + return false; + } + + std::string stage = "place"; + + auto union_db = builder.buildUnionEvalSummary(grid_size, stage); + _summary->set_wirelength_eval(union_db.total_wl_summary); + _summary->set_density_eval(union_db.density_map_summary); + _summary->set_congestion_eval(union_db.congestion_summary); + + builder.evalTiming("EGR", true); + + builder.evalTiming("HPWL"); + builder.evalTiming("FLUTE"); + builder.evalTiming("SALT"); + + auto union_timing_db = builder.buildTimingUnionEvalSummary(); + _summary->set_timing_eval(union_timing_db); + + FeatureParser feature_parser(_summary); + bool jsonl_success = feature_parser.buildSummaryEvalJsonl(jsonl_path); + bool csv_success = builder.buildNetEval(csv_path); + + builder.destroyEvalTool(); + + return jsonl_success && csv_success; +} + +bool FeatureManager::save_cts_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size) +{ + // EGR + FeatureBuilder builder; + + bool is_init_eval_tool = builder.initEvalTool(); + if (!is_init_eval_tool) { + return false; + } + + std::string stage = "cts"; + + auto union_db = builder.buildUnionEvalSummary(grid_size, stage); + _summary->set_wirelength_eval(union_db.total_wl_summary); + _summary->set_density_eval(union_db.density_map_summary); + _summary->set_congestion_eval(union_db.congestion_summary); + + builder.evalTiming("EGR", true); + + builder.evalTiming("HPWL"); + builder.evalTiming("FLUTE"); + builder.evalTiming("SALT"); + + auto union_timing_db = builder.buildTimingUnionEvalSummary(); + _summary->set_timing_eval(union_timing_db); + + FeatureParser feature_parser(_summary); + bool jsonl_success = feature_parser.buildSummaryEvalJsonl(jsonl_path); + + bool csv_success = builder.buildNetEval(csv_path); + + builder.destroyEvalTool(); + + return jsonl_success && csv_success; +} + bool FeatureManager::save_timing_eval_summary(std::string path) { FeatureBuilder builder; @@ -102,9 +199,7 @@ bool FeatureManager::save_tools(std::string path, std::string step) _summary->set_ito_optsetup(db); } else if (step == "route") { - auto db = builder.buildRTSummary(); - - _summary->set_irt(db); + // skip } else { } @@ -139,4 +234,9 @@ bool FeatureManager::read_route_data(std::string path) return feature_parser.readRouteData(path, &_route_data); } +bool FeatureManager::save_cong_map(std::string stage, std::string csv_dir) +{ + FeatureParser feature_parser; + return feature_parser.buildCongMap(stage, csv_dir); +} } // namespace ieda_feature diff --git a/src/feature/feature_manager.h b/src/feature/feature_manager.h index 43d3f76c3..ef5fa34c5 100644 --- a/src/feature/feature_manager.h +++ b/src/feature/feature_manager.h @@ -56,6 +56,7 @@ class FeatureManager bool save_summary(std::string path); bool save_tools(std::string path, std::string step); bool save_eval_map(std::string path, int bin_cnt_x, int bin_cnt_y); + bool save_cong_map(std::string stage, std::string csv_dir); bool save_net_eval(std::string path); // route data bool save_route_data(std::string path); @@ -63,6 +64,9 @@ class FeatureManager // evaluation bool save_eval_summary(std::string path, int32_t grid_size); bool save_timing_eval_summary(std::string path); + bool save_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size); + bool save_pl_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size); + bool save_cts_eval_union(std::string jsonl_path, std::string csv_path, int32_t grid_size); private: static FeatureManager* _instance; diff --git a/src/feature/parser/feature_parser.cpp b/src/feature/parser/feature_parser.cpp index 350be1fcc..b73aa8069 100644 --- a/src/feature/parser/feature_parser.cpp +++ b/src/feature/parser/feature_parser.cpp @@ -228,7 +228,6 @@ bool FeatureParser::buildSummaryEval(std::string json_path) return true; } - bool FeatureParser::buildSummaryEvalJsonl(std::string jsonl_path) { std::ofstream& file_stream = ieda::getOutputFileStream(jsonl_path); diff --git a/src/feature/parser/feature_parser.h b/src/feature/parser/feature_parser.h index 77d19f93d..0c3745430 100644 --- a/src/feature/parser/feature_parser.h +++ b/src/feature/parser/feature_parser.h @@ -72,6 +72,7 @@ class FeatureParser bool buildSummaryEvalJsonl(std::string jsonl_path); bool buildSummaryTimingEval(std::string json_path); bool buildNetEval(std::string csv_path); + bool buildCongMap(std::string stage, std::string csv_dir); private: IdbLayout* _layout = nullptr; diff --git a/src/feature/parser/feature_parser_eval.cpp b/src/feature/parser/feature_parser_eval.cpp index 7620bf3b4..7135dc0a1 100644 --- a/src/feature/parser/feature_parser_eval.cpp +++ b/src/feature/parser/feature_parser_eval.cpp @@ -73,6 +73,15 @@ bool FeatureParser::buildSummaryMap(std::string csv_path, int bin_cnt_x, int bin return true; } +bool FeatureParser::buildCongMap(std::string stage, std::string csv_dir) +{ + if (CONGESTION_API_INST->egrUnionMap(stage, csv_dir) != "") { + return true; + } + + return false; +} + bool FeatureParser::buildNetEval(std::string csv_path) { auto* idb_builder = dmInst->get_idb_builder(); @@ -227,13 +236,26 @@ json FeatureParser::buildSummaryTiming() }; auto routing_timing_summary = _summary->get_summary_timing_eval(); - // TBD - // add_routing_timing("WLM", routing_timing_summary.wlm_timing_eval_summary.clock_timings); - add_routing_timing("HPWL", routing_timing_summary.hpwl_timing_eval_summary.clock_timings); - add_routing_timing("FLUTE", routing_timing_summary.flute_timing_eval_summary.clock_timings); - add_routing_timing("SALT", routing_timing_summary.salt_timing_eval_summary.clock_timings); - add_routing_timing("EGR", routing_timing_summary.egr_timing_eval_summary.clock_timings); - add_routing_timing("DR", routing_timing_summary.dr_timing_eval_summary.clock_timings); + + if (routing_timing_summary.wlm_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("WLM", routing_timing_summary.wlm_timing_eval_summary.clock_timings); + } + if (routing_timing_summary.hpwl_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("HPWL", routing_timing_summary.hpwl_timing_eval_summary.clock_timings); + } + if (routing_timing_summary.flute_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("FLUTE", routing_timing_summary.flute_timing_eval_summary.clock_timings); + } + if (routing_timing_summary.salt_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("SALT", routing_timing_summary.salt_timing_eval_summary.clock_timings); + } + if (routing_timing_summary.egr_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("EGR", routing_timing_summary.egr_timing_eval_summary.clock_timings); + } + if (routing_timing_summary.dr_timing_eval_summary.clock_timings.size() > 0) { + add_routing_timing("DR", routing_timing_summary.dr_timing_eval_summary.clock_timings); + } + return timing; } @@ -247,13 +269,24 @@ json FeatureParser::buildSummaryPower() auto timing_summary = _summary->get_summary_timing_eval(); - // TBD - // add_routing_power("WLM", timing_summary.wlm_timing_eval_summary.power_info); - add_routing_power("HPWL", timing_summary.hpwl_timing_eval_summary.power_info); - add_routing_power("FLUTE", timing_summary.flute_timing_eval_summary.power_info); - add_routing_power("SALT", timing_summary.salt_timing_eval_summary.power_info); - add_routing_power("EGR", timing_summary.egr_timing_eval_summary.power_info); - add_routing_power("DR", timing_summary.dr_timing_eval_summary.power_info); + if (timing_summary.wlm_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("WLM", timing_summary.wlm_timing_eval_summary.power_info); + } + if (timing_summary.hpwl_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("HPWL", timing_summary.hpwl_timing_eval_summary.power_info); + } + if (timing_summary.flute_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("FLUTE", timing_summary.flute_timing_eval_summary.power_info); + } + if (timing_summary.salt_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("SALT", timing_summary.salt_timing_eval_summary.power_info); + } + if (timing_summary.egr_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("EGR", timing_summary.egr_timing_eval_summary.power_info); + } + if (timing_summary.dr_timing_eval_summary.power_info.static_power > 0) { + add_routing_power("DR", timing_summary.dr_timing_eval_summary.power_info); + } return power; } diff --git a/src/feature/parser/feature_parser_tools.cpp b/src/feature/parser/feature_parser_tools.cpp index ba5d284fd..166dfeea9 100644 --- a/src/feature/parser/feature_parser_tools.cpp +++ b/src/feature/parser/feature_parser_tools.cpp @@ -62,41 +62,92 @@ json FeatureParser::buildSummaryRT() } json_rt["SA"] = json_sa; - /// IR - json json_ir; - json_ir["total_demand"] = rt_sum.ir_summary.total_demand; - for (auto demand : rt_sum.ir_summary.routing_demand_map) { - json_ir["routing_demand_map"][std::to_string(demand.first)] = demand.second; + // TG + json json_tg; + json_tg["total_demand"] = rt_sum.tg_summary.total_demand; + json_tg["total_overflow"] = rt_sum.tg_summary.total_overflow; + json_tg["total_wire_length"] = rt_sum.tg_summary.total_wire_length; + + for (int i = 0; i < (int) rt_sum.tg_summary.clocks_timing.size(); i++) { + auto clock_timing = rt_sum.tg_summary.clocks_timing[i]; + json_tg["clocks_timing"][i]["clock_name"] = clock_timing.clock_name; + json_tg["clocks_timing"][i]["setup_tns"] = clock_timing.setup_tns; + json_tg["clocks_timing"][i]["setup_wns"] = clock_timing.setup_wns; + json_tg["clocks_timing"][i]["suggest_freq"] = clock_timing.suggest_freq; + } + json_tg["static_power"] = rt_sum.tg_summary.power_info.static_power; + json_tg["dynamic_power"] = rt_sum.tg_summary.power_info.dynamic_power; + json_rt["TG"] = json_tg; + + /// LA + json json_la; + json_la["total_demand"] = rt_sum.la_summary.total_demand; + for (auto demand : rt_sum.la_summary.routing_demand_map) { + json_la["routing_demand_map"][std::to_string(demand.first)] = demand.second; } - json_ir["total_overflow"] = rt_sum.ir_summary.total_overflow; - for (auto routing_overflow : rt_sum.ir_summary.routing_overflow_map) { - json_ir["routing_overflow_map"][std::to_string(routing_overflow.first)] = routing_overflow.second; + json_la["total_overflow"] = rt_sum.la_summary.total_overflow; + for (auto routing_overflow : rt_sum.la_summary.routing_overflow_map) { + json_la["routing_overflow_map"][std::to_string(routing_overflow.first)] = routing_overflow.second; } - json_ir["total_wire_length"] = rt_sum.ir_summary.total_wire_length; - for (auto routing_wire_length : rt_sum.ir_summary.routing_wire_length_map) { - json_ir["routing_wire_length_map"][std::to_string(routing_wire_length.first)] = routing_wire_length.second; + json_la["total_wire_length"] = rt_sum.la_summary.total_wire_length; + for (auto routing_wire_length : rt_sum.la_summary.routing_wire_length_map) { + json_la["routing_wire_length_map"][std::to_string(routing_wire_length.first)] = routing_wire_length.second; } - json_ir["total_via_num"] = rt_sum.ir_summary.total_via_num; - for (auto cut_via_num : rt_sum.ir_summary.cut_via_num_map) { - json_ir["cut_via_num_map"][std::to_string(cut_via_num.first)] = cut_via_num.second; + json_la["total_via_num"] = rt_sum.la_summary.total_via_num; + for (auto cut_via_num : rt_sum.la_summary.cut_via_num_map) { + json_la["cut_via_num_map"][std::to_string(cut_via_num.first)] = cut_via_num.second; } - for (int i = 0; i < (int) rt_sum.ir_summary.clocks_timing.size(); i++) { - auto clock_timing = rt_sum.ir_summary.clocks_timing[i]; - json_ir["clocks_timing"][i]["clock_name"] = clock_timing.clock_name; - json_ir["clocks_timing"][i]["setup_tns"] = clock_timing.setup_tns; - json_ir["clocks_timing"][i]["setup_wns"] = clock_timing.setup_wns; - json_ir["clocks_timing"][i]["suggest_freq"] = clock_timing.suggest_freq; + for (int i = 0; i < (int) rt_sum.la_summary.clocks_timing.size(); i++) { + auto clock_timing = rt_sum.la_summary.clocks_timing[i]; + json_la["clocks_timing"][i]["clock_name"] = clock_timing.clock_name; + json_la["clocks_timing"][i]["setup_tns"] = clock_timing.setup_tns; + json_la["clocks_timing"][i]["setup_wns"] = clock_timing.setup_wns; + json_la["clocks_timing"][i]["suggest_freq"] = clock_timing.suggest_freq; } - json_ir["static_power"] = rt_sum.ir_summary.power_info.static_power; - json_ir["dynamic_power"] = rt_sum.ir_summary.power_info.dynamic_power; + json_la["static_power"] = rt_sum.la_summary.power_info.static_power; + json_la["dynamic_power"] = rt_sum.la_summary.power_info.dynamic_power; - json_rt["IR"] = json_ir; + json_rt["LA"] = json_la; - // // GR + // ER + json json_er; + json_er["total_demand"] = rt_sum.la_summary.total_demand; + for (auto demand : rt_sum.la_summary.routing_demand_map) { + json_er["routing_demand_map"][std::to_string(demand.first)] = demand.second; + } + + json_er["total_overflow"] = rt_sum.la_summary.total_overflow; + for (auto routing_overflow : rt_sum.la_summary.routing_overflow_map) { + json_er["routing_overflow_map"][std::to_string(routing_overflow.first)] = routing_overflow.second; + } + + json_er["total_wire_length"] = rt_sum.la_summary.total_wire_length; + for (auto routing_wire_length : rt_sum.la_summary.routing_wire_length_map) { + json_er["routing_wire_length_map"][std::to_string(routing_wire_length.first)] = routing_wire_length.second; + } + + json_er["total_via_num"] = rt_sum.la_summary.total_via_num; + for (auto cut_via_num : rt_sum.la_summary.cut_via_num_map) { + json_er["cut_via_num_map"][std::to_string(cut_via_num.first)] = cut_via_num.second; + } + + for (int i = 0; i < (int) rt_sum.la_summary.clocks_timing.size(); i++) { + auto clock_timing = rt_sum.la_summary.clocks_timing[i]; + json_er["clocks_timing"][i]["clock_name"] = clock_timing.clock_name; + json_er["clocks_timing"][i]["setup_tns"] = clock_timing.setup_tns; + json_er["clocks_timing"][i]["setup_wns"] = clock_timing.setup_wns; + json_er["clocks_timing"][i]["suggest_freq"] = clock_timing.suggest_freq; + } + json_er["static_power"] = rt_sum.la_summary.power_info.static_power; + json_er["dynamic_power"] = rt_sum.la_summary.power_info.dynamic_power; + + json_rt["ER"] = json_er; + + // GR json json_gr_list; for (auto [id, gr_sum] : rt_sum.iter_gr_summary_map) { json json_gr; @@ -197,32 +248,32 @@ json FeatureParser::buildSummaryPL(std::string step) if (step == "place") { summary_pl["gplace"]["place_density"] = pl_summary.gplace.place_density; - summary_pl["gplace"]["pin_density"] = pl_summary.gplace.pin_density; - summary_pl["gplace"]["HPWL"] = pl_summary.gplace.HPWL; - summary_pl["gplace"]["STWL"] = pl_summary.gplace.STWL; - summary_pl["gplace"]["GRWL"] = pl_summary.gplace.GRWL; + // summary_pl["gplace"]["pin_density"] = pl_summary.gplace.pin_density; + // summary_pl["gplace"]["HPWL"] = pl_summary.gplace.HPWL; + // summary_pl["gplace"]["STWL"] = pl_summary.gplace.STWL; + // summary_pl["gplace"]["GRWL"] = pl_summary.gplace.GRWL; - summary_pl["gplace"]["egr_tof"] = pl_summary.gplace.egr_tof; - summary_pl["gplace"]["egr_mof"] = pl_summary.gplace.egr_mof; - summary_pl["gplace"]["egr_ace"] = pl_summary.gplace.egr_ace; + // summary_pl["gplace"]["egr_tof"] = pl_summary.gplace.egr_tof; + // summary_pl["gplace"]["egr_mof"] = pl_summary.gplace.egr_mof; + // summary_pl["gplace"]["egr_ace"] = pl_summary.gplace.egr_ace; - summary_pl["gplace"]["tns"] = pl_summary.gplace.tns; - summary_pl["gplace"]["wns"] = pl_summary.gplace.wns; - summary_pl["gplace"]["suggest_freq"] = pl_summary.gplace.suggest_freq; + // summary_pl["gplace"]["tns"] = pl_summary.gplace.tns; + // summary_pl["gplace"]["wns"] = pl_summary.gplace.wns; + // summary_pl["gplace"]["suggest_freq"] = pl_summary.gplace.suggest_freq; summary_pl["dplace"]["place_density"] = pl_summary.dplace.place_density; - summary_pl["dplace"]["pin_density"] = pl_summary.dplace.pin_density; - summary_pl["dplace"]["HPWL"] = pl_summary.dplace.HPWL; - summary_pl["dplace"]["STWL"] = pl_summary.dplace.STWL; - summary_pl["dplace"]["GRWL"] = pl_summary.dplace.GRWL; + // summary_pl["dplace"]["pin_density"] = pl_summary.dplace.pin_density; + // summary_pl["dplace"]["HPWL"] = pl_summary.dplace.HPWL; + // summary_pl["dplace"]["STWL"] = pl_summary.dplace.STWL; + // summary_pl["dplace"]["GRWL"] = pl_summary.dplace.GRWL; - summary_pl["dplace"]["egr_tof"] = pl_summary.dplace.egr_tof; - summary_pl["dplace"]["egr_mof"] = pl_summary.dplace.egr_mof; - summary_pl["dplace"]["egr_ace"] = pl_summary.dplace.egr_ace; + // summary_pl["dplace"]["egr_tof"] = pl_summary.dplace.egr_tof; + // summary_pl["dplace"]["egr_mof"] = pl_summary.dplace.egr_mof; + // summary_pl["dplace"]["egr_ace"] = pl_summary.dplace.egr_ace; - summary_pl["dplace"]["tns"] = pl_summary.dplace.tns; - summary_pl["dplace"]["wns"] = pl_summary.dplace.wns; - summary_pl["dplace"]["suggest_freq"] = pl_summary.dplace.suggest_freq; + // summary_pl["dplace"]["tns"] = pl_summary.dplace.tns; + // summary_pl["dplace"]["wns"] = pl_summary.dplace.wns; + // summary_pl["dplace"]["suggest_freq"] = pl_summary.dplace.suggest_freq; summary_pl["instance_cnt"] = pl_summary.instance_cnt; summary_pl["fix_inst_cnt"] = pl_summary.fix_inst_cnt; @@ -237,18 +288,18 @@ json FeatureParser::buildSummaryPL(std::string step) // 3: Data parameters required for legalization. else if (step == "legalization") { summary_pl["legalization"]["place_density"] = pl_summary.lg_summary.pl_common_summary.place_density; - summary_pl["legalization"]["pin_density"] = pl_summary.lg_summary.pl_common_summary.pin_density; - summary_pl["legalization"]["HPWL"] = pl_summary.lg_summary.pl_common_summary.HPWL; - summary_pl["legalization"]["STWL"] = pl_summary.lg_summary.pl_common_summary.STWL; - summary_pl["legalization"]["GRWL"] = pl_summary.lg_summary.pl_common_summary.GRWL; + // summary_pl["legalization"]["pin_density"] = pl_summary.lg_summary.pl_common_summary.pin_density; + // summary_pl["legalization"]["HPWL"] = pl_summary.lg_summary.pl_common_summary.HPWL; + // summary_pl["legalization"]["STWL"] = pl_summary.lg_summary.pl_common_summary.STWL; + // summary_pl["legalization"]["GRWL"] = pl_summary.lg_summary.pl_common_summary.GRWL; - summary_pl["legalization"]["egr_tof"] = pl_summary.lg_summary.pl_common_summary.egr_tof; - summary_pl["legalization"]["egr_mof"] = pl_summary.lg_summary.pl_common_summary.egr_mof; - summary_pl["legalization"]["egr_ace"] = pl_summary.lg_summary.pl_common_summary.egr_ace; + // summary_pl["legalization"]["egr_tof"] = pl_summary.lg_summary.pl_common_summary.egr_tof; + // summary_pl["legalization"]["egr_mof"] = pl_summary.lg_summary.pl_common_summary.egr_mof; + // summary_pl["legalization"]["egr_ace"] = pl_summary.lg_summary.pl_common_summary.egr_ace; - summary_pl["legalization"]["tns"] = pl_summary.lg_summary.pl_common_summary.tns; - summary_pl["legalization"]["wns"] = pl_summary.lg_summary.pl_common_summary.wns; - summary_pl["legalization"]["suggest_freq"] = pl_summary.lg_summary.pl_common_summary.suggest_freq; + // summary_pl["legalization"]["tns"] = pl_summary.lg_summary.pl_common_summary.tns; + // summary_pl["legalization"]["wns"] = pl_summary.lg_summary.pl_common_summary.wns; + // summary_pl["legalization"]["suggest_freq"] = pl_summary.lg_summary.pl_common_summary.suggest_freq; summary_pl["legalization"]["total_movement"] = pl_summary.lg_summary.lg_total_movement; summary_pl["legalization"]["max_movement"] = pl_summary.lg_summary.lg_max_movement; diff --git a/src/interface/gui/CMakeLists.txt b/src/interface/gui/CMakeLists.txt index 5c773d4e4..42e8766b2 100644 --- a/src/interface/gui/CMakeLists.txt +++ b/src/interface/gui/CMakeLists.txt @@ -5,12 +5,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations ") -if(BUILD_PR_FLOW) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) - if(NOT DEFINED CMD_BUILD) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) - endif() +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) +if(NOT DEFINED CMD_BUILD) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${HOME_BUILD}/lib/iGUI) endif() @@ -181,82 +179,41 @@ set(headers include(${HOME_CMAKE}/operation/idb.cmake) -if(BUILD_PR_FLOW) - message("Build iGUI lib") - - add_library(iGUI - ${headers} - ${sources} - ) - - target_link_libraries(iGUI Qt5${QT_VERSION_MAJOR}::Widgets Qt5${QT_VERSION_MAJOR}::Xml Qt5${QT_VERSION_MAJOR}::Core) - # 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_placement - tool_api_ipl - idrc_pro_violation - ieda_feature - ) - - if(OpenMP_CXX_FOUND) - target_link_libraries(iGUI - OpenMP::OpenMP_CXX - ) - - endif() - - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/graphicsitem) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiaction) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guicontroltree) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiDB) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiparser) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/designitem) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/utilityitem) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/utility) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guispeedupitems) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interface) - target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/config) - - - target_include_directories(iGUI - PUBLIC - # ${HOME_PLATFORM}/ - # ${HOME_PLATFORM}//tool_api - # ${HOME_PLATFORM}//tool_api/irt_io - ) - -else() - message("Build iGUI exe") - - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/graphicsitem) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/guiaction) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/guicontroltree) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/guiDB) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/guiparser) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/designitem) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/utilityitem) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/utility) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/guispeedupitems) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interface) - - set(exe_sources - src/main.cpp - ${sources} - ) - add_executable(iGUI - ${headers} - ${exe_sources} - ${samples} - ) - - target_link_libraries(iGUI Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml Qt${QT_VERSION_MAJOR}::Core) - target_link_libraries(iGUI idb IdbBuilder def_service lef_service ) +add_library(iGUI + ${headers} + ${sources} +) +target_link_libraries(iGUI Qt5${QT_VERSION_MAJOR}::Widgets Qt5${QT_VERSION_MAJOR}::Xml Qt5${QT_VERSION_MAJOR}::Core) +# 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_placement + tool_api_ipl + idrc_pro_violation + ieda_feature +) +if(OpenMP_CXX_FOUND) +target_link_libraries(iGUI + OpenMP::OpenMP_CXX +) endif() - -# add_subdirectory(${IDB_HOME} idb.out) -SET(CMAKE_BUILD_TYPE "debug") +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/graphicsitem) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiaction) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guicontroltree) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiDB) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guiparser) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/designitem) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/utilityitem) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/utility) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/guispeedupitems) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interface) +target_include_directories(iGUI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/config) +target_include_directories(iGUI + PUBLIC + # ${HOME_PLATFORM}/ + # ${HOME_PLATFORM}//tool_api + # ${HOME_PLATFORM}//tool_api/irt_io +) diff --git a/src/interface/python/py_feature/py_feature.cpp b/src/interface/python/py_feature/py_feature.cpp index dedf3ef81..6e9d348cc 100644 --- a/src/interface/python/py_feature/py_feature.cpp +++ b/src/interface/python/py_feature/py_feature.cpp @@ -55,6 +55,21 @@ bool feature_eval_summary(const std::string& path, int32_t grid_size) return featureInst->save_eval_summary(path, grid_size); } +bool feature_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size) +{ + return featureInst->save_eval_union(jsonl_path, csv_path, grid_size); +} + +bool feature_pl_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size) +{ + return featureInst->save_pl_eval_union(jsonl_path, csv_path, grid_size); +} + +bool feature_cts_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size) +{ + return featureInst->save_cts_eval_union(jsonl_path, csv_path, grid_size); +} + bool feature_timing_eval_summary(const std::string& path) { return featureInst->save_timing_eval_summary(path); diff --git a/src/interface/python/py_feature/py_feature.h b/src/interface/python/py_feature/py_feature.h index f96cea23f..22753cd40 100644 --- a/src/interface/python/py_feature/py_feature.h +++ b/src/interface/python/py_feature/py_feature.h @@ -28,5 +28,8 @@ bool feature_route_read(const std::string& path); bool feature_eval_summary(const std::string& path, int32_t grid_size); bool feature_timing_eval_summary(const std::string& path); bool feature_net_eval(const std::string& path); +bool feature_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size); +bool feature_pl_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size); +bool feature_cts_eval_union(const std::string& jsonl_path, const std::string& csv_path, int32_t grid_size); } // namespace python_interface \ No newline at end of file diff --git a/src/interface/python/py_feature/py_register_feature.h b/src/interface/python/py_feature/py_register_feature.h index 499d7cf3e..7d5471bb7 100644 --- a/src/interface/python/py_feature/py_register_feature.h +++ b/src/interface/python/py_feature/py_register_feature.h @@ -32,6 +32,9 @@ void register_feature(py::module& m) m.def("feature_eval_summary", feature_eval_summary, py::arg("path"), py::arg("grid_size")); m.def("feature_timing_eval_summary", feature_timing_eval_summary, py::arg("path")); m.def("feature_net_eval", feature_net_eval, py::arg("path")); + m.def("feature_eval_union", feature_eval_union, py::arg("jsonl_path"), py::arg("csv_path"), py::arg("grid_size")); + m.def("feature_pl_eval_union", feature_pl_eval_union, py::arg("jsonl_path"), py::arg("csv_path"), py::arg("grid_size")); + m.def("feature_cts_eval_union", feature_cts_eval_union, py::arg("jsonl_path"), py::arg("csv_path"), py::arg("grid_size")); } } // namespace python_interface \ No newline at end of file diff --git a/src/interface/python/py_idb/py_register_idb.cpp b/src/interface/python/py_idb/py_register_idb.cpp index c3e7b1298..3df958112 100644 --- a/src/interface/python/py_idb/py_register_idb.cpp +++ b/src/interface/python/py_idb/py_register_idb.cpp @@ -32,7 +32,8 @@ void register_idb(py::module& m) m.def("def_init", initDef, py::arg("def_path")); m.def("verilog_init", initVerilog, py::arg("verilog_path"), py::arg("top_module")); m.def("def_save", saveDef, py::arg("def_name")); - m.def("netlist_save", saveNetList, py::arg("netlist_path"), py::arg("exclude_cell_names") = std::set{}); + m.def("netlist_save", saveNetList, py::arg("netlist_path"), py::arg("exclude_cell_names") = std::set{}, + py::arg("is_add_space_for_escape_name") = false); m.def("gds_save", saveGDSII, py::arg("gds_name")); } diff --git a/src/interface/python/py_ipw/py_ipw.cpp b/src/interface/python/py_ipw/py_ipw.cpp index 8262b3958..b38609eba 100644 --- a/src/interface/python/py_ipw/py_ipw.cpp +++ b/src/interface/python/py_ipw/py_ipw.cpp @@ -52,7 +52,11 @@ build_connection_map(std::vector> clusters, std::set build_macro_connection_map(unsigned max_hop) { auto* power_engine = ipower::PowerEngine::getOrCreatePowerEngine(); +#ifdef USE_GPU + return power_engine->buildMacroConnectionMapWithGPU(max_hop); +#else return power_engine->buildMacroConnectionMap(max_hop); +#endif } } // namespace python_interface \ No newline at end of file diff --git a/src/interface/tcl/tcl_feature/tcl_feature.cpp b/src/interface/tcl/tcl_feature/tcl_feature.cpp index 9479c8532..f6dcf3b23 100644 --- a/src/interface/tcl/tcl_feature/tcl_feature.cpp +++ b/src/interface/tcl/tcl_feature/tcl_feature.cpp @@ -47,7 +47,7 @@ CmdFeatureSummary::CmdFeatureSummary(const char* cmd_name) : TclCmd(cmd_name) unsigned CmdFeatureSummary::check() { TclOption* path_option = getOptionOrArg(TCL_PATH); - //TclOption* step_option = getOptionOrArg(TCL_STEP); + // TclOption* step_option = getOptionOrArg(TCL_STEP); LOG_FATAL_IF(!path_option); // LOG_FATAL_IF(!step_option); return 1; @@ -226,4 +226,50 @@ unsigned CmdFeatureRouteRead::exec() return 1; } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * feature_cong_map -dir "/your/dir/path/" + */ +CmdFeatureCongMap::CmdFeatureCongMap(const char* cmd_name) : TclCmd(cmd_name) +{ + auto* dir_option = new TclStringOption(TCL_DIRECTORY, 1, nullptr); + auto* step_option = new TclStringOption(TCL_STEP, 1, nullptr); + addOption(dir_option); + addOption(step_option); +} + +unsigned CmdFeatureCongMap::check() +{ + TclOption* dir_option = getOptionOrArg(TCL_DIRECTORY); + TclOption* step_option = getOptionOrArg(TCL_STEP); + + LOG_FATAL_IF(!dir_option); + LOG_FATAL_IF(!step_option); + + return 1; +} + +unsigned CmdFeatureCongMap::exec() +{ + if (!check()) { + return 0; + } + + TclOption* option = getOptionOrArg(TCL_DIRECTORY); + auto dir_path = option->getStringVal(); + + std::string stage = ""; + TclOption* step_option = getOptionOrArg(TCL_STEP); + if (step_option->getStringVal() != nullptr) { + stage = step_option->getStringVal(); + } + + featureInst->save_cong_map(stage, dir_path); + + return 1; +} + } // namespace tcl diff --git a/src/interface/tcl/tcl_feature/tcl_feature.h b/src/interface/tcl/tcl_feature/tcl_feature.h index 969f8bde0..e1cd57cc6 100644 --- a/src/interface/tcl/tcl_feature/tcl_feature.h +++ b/src/interface/tcl/tcl_feature/tcl_feature.h @@ -119,4 +119,18 @@ class CmdFeatureEvalSummary : public TclCmd // private data }; +class CmdFeatureCongMap : public TclCmd +{ + public: + explicit CmdFeatureCongMap(const char* cmd_name); + ~CmdFeatureCongMap() override = default; + + unsigned check() override; + unsigned exec() override; + + private: + // private function + // private data +}; + } // namespace tcl \ No newline at end of file diff --git a/src/interface/tcl/tcl_feature/tcl_register_feature.h b/src/interface/tcl/tcl_feature/tcl_register_feature.h index 8d684eae3..c3005bf91 100644 --- a/src/interface/tcl/tcl_feature/tcl_register_feature.h +++ b/src/interface/tcl/tcl_feature/tcl_register_feature.h @@ -38,6 +38,7 @@ int registerCmdFeature() registerTclCmd(CmdFeatureEvalMap, "feature_eval_map"); registerTclCmd(CmdFeatureRoute, "feature_route"); registerTclCmd(CmdFeatureRouteRead, "feature_route_read"); + registerTclCmd(CmdFeatureCongMap, "feature_cong_map"); return EXIT_SUCCESS; } diff --git a/src/interface/tcl/tcl_ito/tcl_toconfig.cpp b/src/interface/tcl/tcl_ito/tcl_toconfig.cpp index 6f38f15f2..8cd32eca8 100644 --- a/src/interface/tcl/tcl_ito/tcl_toconfig.cpp +++ b/src/interface/tcl/tcl_ito/tcl_toconfig.cpp @@ -58,6 +58,8 @@ CmdTOConfig::CmdTOConfig(const char* cmd_name) : TclCmd(cmd_name) _config_list.push_back(std::make_pair("-min_divide_fanoutt", ValueType::kInt)); // optimize_endpoints_percent double _config_list.push_back(std::make_pair("-optimize_endpoints_percent", ValueType::kDouble)); + // drv_optimize_iter_number int + _config_list.push_back(std::make_pair("-drv_optimize_iter_number", ValueType::kInt)); TclUtil::addOption(this, _config_list); } diff --git a/src/operation/iCTS/api/CTSAPI.cc b/src/operation/iCTS/api/CTSAPI.cc index 004e62d37..1ff6550f1 100644 --- a/src/operation/iCTS/api/CTSAPI.cc +++ b/src/operation/iCTS/api/CTSAPI.cc @@ -602,11 +602,17 @@ icts::CtsCellLib* CTSAPI::getCellLib(const std::string& cell_master, const std:: y_slew.emplace_back(slew_mid_value[i * cap_out.size() + j]); } } - LOG_FATAL_IF(x_slew_in.empty() || x_cap_out.empty() || y_delay.empty() || y_slew.empty()) - << "No feasible work value, please check " - "the config parameter: \"max_buf_tran\", \"max_sink_tran\" and " - "\"max_cap\" with the liberty " - << cell_master; + if (x_slew_in.empty() || x_cap_out.empty() || y_delay.empty() || y_slew.empty()) { + LOG_WARNING << "No feasible work value, please check " + "the config parameter: \"max_buf_tran\", \"max_sink_tran\" and " + "\"max_cap\" with the liberty " + << cell_master; + // use all value + x_slew_in = slew_in; + x_cap_out = cap_out; + y_delay = delay_mid_value; + y_slew = slew_mid_value; + } std::vector> x_delay = {x_slew_in, x_cap_out}; lib->set_delay_coef(_model_factory->cppLinearModel(x_delay, y_delay)); diff --git a/src/operation/iCTS/source/data_manager/io/GDSPloter.cc b/src/operation/iCTS/source/data_manager/io/GDSPloter.cc index e981ac3a0..1687c86c8 100644 --- a/src/operation/iCTS/source/data_manager/io/GDSPloter.cc +++ b/src/operation/iCTS/source/data_manager/io/GDSPloter.cc @@ -46,12 +46,14 @@ void GDSPloter::plotDesign(const std::string& path) head(ofs); for (auto& clk_net : clk_nets) { + size_t wire_id = 0; auto net_name = clk_net->get_net_name(); for (const auto& wire : clk_net->get_signal_wires()) { + auto wire_name = "WIRE_" + net_name + "_" + std::to_string(wire_id++); auto first = wire.get_first().point; auto second = wire.get_second().point; - insertWire(ofs, first, second, clk_net->get_driver_inst()->get_level()); + insertWire(ofs, first, second, wire_name, clk_net->get_driver_inst()->get_level()); } } @@ -104,7 +106,14 @@ void GDSPloter::plotDesign(const std::string& path) } } refPolygon(ofs, "core"); - refPolygon(ofs, "WIRE"); + for (auto& clk_net : clk_nets) { + auto net_name = clk_net->get_net_name(); + + for (size_t i = 0; i < clk_net->get_signal_wires().size(); ++i) { + auto wire_name = "WIRE_" + net_name + "_" + std::to_string(i); + refPolygon(ofs, wire_name); + } + } strEnd(ofs); tail(ofs); @@ -129,9 +138,11 @@ void GDSPloter::plotFlyLine(const std::string& path) head(ofs); for (auto& clk_net : clk_nets) { - auto driver = clk_net->get_driver_inst(); - for (auto load : clk_net->get_load_insts()) { - insertWire(ofs, driver->get_location(), load->get_location(), driver->get_level()); + auto* driver = clk_net->get_driver_inst(); + size_t wire_id = 0; + for (auto* load : clk_net->get_load_insts()) { + auto wire_name = "WIRE_" + clk_net->get_net_name() + "_" + std::to_string(wire_id++); + insertWire(ofs, driver->get_location(), load->get_location(), wire_name, driver->get_level()); } } @@ -184,7 +195,13 @@ void GDSPloter::plotFlyLine(const std::string& path) } } refPolygon(ofs, "core"); - refPolygon(ofs, "WIRE"); + + for (auto& clk_net : clk_nets) { + for (size_t i = 0; i < clk_net->get_load_insts().size(); ++i) { + auto wire_name = "WIRE_" + clk_net->get_net_name() + "_" + std::to_string(i); + refPolygon(ofs, wire_name); + } + } strEnd(ofs); tail(ofs); @@ -392,10 +409,11 @@ void GDSPloter::insertInstance(std::fstream& log_ofs, CtsInstance* inst) insertPolygon(log_ofs, rect, name, layer); } -void GDSPloter::insertWire(std::fstream& log_ofs, const Point& begin, const Point& end, const int& layer, const int& width) +void GDSPloter::insertWire(std::fstream& log_ofs, const Point& begin, const Point& end, const string& name, const int& layer, + const int& width) { log_ofs << "BGNSTR" << std::endl; - log_ofs << "STRNAME WIRE" << std::endl; + log_ofs << "STRNAME " << name << std::endl; log_ofs << "PATH" << std::endl; log_ofs << "LAYER " + std::to_string(layer) << std::endl; log_ofs << "DATATYPE 0" << std::endl; diff --git a/src/operation/iCTS/source/data_manager/io/GDSPloter.hh b/src/operation/iCTS/source/data_manager/io/GDSPloter.hh index 2d30b673d..337d772fb 100644 --- a/src/operation/iCTS/source/data_manager/io/GDSPloter.hh +++ b/src/operation/iCTS/source/data_manager/io/GDSPloter.hh @@ -55,7 +55,8 @@ class GDSPloter static void insertPolygon(std::fstream& log_ofs, IdbRect& poly, const string& name = "polygon", int layer = 0, const int& type = 1); - static void insertWire(std::fstream& log_ofs, const Point& begin, const Point& end, const int& layer = 0, const int& width = 80); + static void insertWire(std::fstream& log_ofs, const Point& begin, const Point& end, const string& name = "WIRE", const int& layer = 0, + const int& width = 80); static void head(std::fstream& log_ofs); static void tail(std::fstream& log_ofs); diff --git a/src/operation/iDRC/CMakeLists.txt b/src/operation/iDRC/CMakeLists.txt index 6f9f6c7f9..4d59c4d17 100644 --- a/src/operation/iDRC/CMakeLists.txt +++ b/src/operation/iDRC/CMakeLists.txt @@ -8,16 +8,12 @@ add_subdirectory(api) add_subdirectory(source) # add_subdirectory(test) -if(BUILD_PR_FLOW) - # ADD_EXECUTABLE(run_drc ${IDRC_TESTS}/run_drc.cpp) - # TARGET_LINK_LIBRARIES(run_drc DRC) -else(BUILD_PR_FLOW) - ADD_EXECUTABLE(run_drc ${IDRC_TESTS}/run_drc.cpp) - TARGET_LINK_LIBRARIES(run_drc DRC) - - ADD_EXECUTABLE(conflict_graph ${IDRC_TESTS}/conflict_graph.cpp) - TARGET_LINK_LIBRARIES(conflict_graph DRC) - - add_executable(test_boost ${IDRC_TESTS}/test_boost.cpp) - target_link_libraries(test_boost DRC) -endif(BUILD_PR_FLOW) \ No newline at end of file + +# ADD_EXECUTABLE(run_drc ${IDRC_TESTS}/run_drc.cpp) +# TARGET_LINK_LIBRARIES(run_drc DRC) + +# ADD_EXECUTABLE(conflict_graph ${IDRC_TESTS}/conflict_graph.cpp) +# TARGET_LINK_LIBRARIES(conflict_graph DRC) + +# add_executable(test_boost ${IDRC_TESTS}/test_boost.cpp) +# target_link_libraries(test_boost DRC) \ No newline at end of file diff --git a/src/operation/iPL/api/PLAPI.cc b/src/operation/iPL/api/PLAPI.cc index 71645549a..1479ba8e0 100644 --- a/src/operation/iPL/api/PLAPI.cc +++ b/src/operation/iPL/api/PLAPI.cc @@ -377,13 +377,13 @@ void PLAPI::runFlow() { // runMP(); runGP(); - printHPWLInfo(); - printTimingInfo(); - notifyPLWLInfo(0); - if (isSTAStarted()) { - notifyPLCongestionInfo(0); - notifyPLTimingInfo(0); - } + // printHPWLInfo(); + // printTimingInfo(); + // notifyPLWLInfo(0); + // if (isSTAStarted()) { + // notifyPLCongestionInfo(0); + // notifyPLTimingInfo(0); + // } if (PlacerDBInst.get_placer_config()->get_buffer_config().isMaxLengthOpt()) { std::cout << std::endl; @@ -398,13 +398,13 @@ void PLAPI::runFlow() std::cout << std::endl; runLG(); - printHPWLInfo(); - printTimingInfo(); - notifyPLWLInfo(1); - if (isSTAStarted()) { - notifyPLCongestionInfo(1); - notifyPLTimingInfo(1); - } + // printHPWLInfo(); + // printTimingInfo(); + // notifyPLWLInfo(1); + // if (isSTAStarted()) { + // notifyPLCongestionInfo(1); + // notifyPLTimingInfo(1); + // } std::cout << std::endl; if (isSTAStarted()) { @@ -412,14 +412,14 @@ void PLAPI::runFlow() } else { runDP(); } - printHPWLInfo(); - printTimingInfo(); + // printHPWLInfo(); + // printTimingInfo(); - notifyPLWLInfo(2); - if (isSTAStarted()) { - notifyPLCongestionInfo(2); - notifyPLTimingInfo(2); - } + // notifyPLWLInfo(2); + // if (isSTAStarted()) { + // notifyPLCongestionInfo(2); + // notifyPLTimingInfo(2); + // } std::cout << std::endl; @@ -950,46 +950,46 @@ ieda_feature::PlaceSummary PLAPI::outputSummary(std::string step) // 1:全局布局、详细布局、合法化都需要存储的数据参数,需要根据step存储不同的值 auto place_density = PlacerDBInst.place_density; - auto pin_density = PlacerDBInst.pin_density; - auto HPWL = PlacerDBInst.PL_HPWL; - auto STWL = PlacerDBInst.PL_STWL; - auto GRWL = PlacerDBInst.PL_GRWL; + // auto pin_density = PlacerDBInst.pin_density; + // auto HPWL = PlacerDBInst.PL_HPWL; + // auto STWL = PlacerDBInst.PL_STWL; + // auto GRWL = PlacerDBInst.PL_GRWL; - auto egr_tof = PlacerDBInst.egr_tof; - auto egr_mof = PlacerDBInst.egr_mof; - auto egr_ace = PlacerDBInst.egr_ace; + // auto egr_tof = PlacerDBInst.egr_tof; + // auto egr_mof = PlacerDBInst.egr_mof; + // auto egr_ace = PlacerDBInst.egr_ace; - auto tns = PlacerDBInst.tns; - auto wns = PlacerDBInst.wns; - auto suggest_freq = PlacerDBInst.suggest_freq; + // auto tns = PlacerDBInst.tns; + // auto wns = PlacerDBInst.wns; + // auto suggest_freq = PlacerDBInst.suggest_freq; // 2:全局布局、详细布局需要存储的数据参数 if (step == "place") { summary.gplace.place_density = place_density[0]; - summary.gplace.pin_density = pin_density[0]; - summary.gplace.HPWL = HPWL[0]; - summary.gplace.STWL = STWL[0]; - summary.gplace.GRWL = GRWL[0]; + // summary.gplace.pin_density = pin_density[0]; + // summary.gplace.HPWL = HPWL[0]; + // summary.gplace.STWL = STWL[0]; + // summary.gplace.GRWL = GRWL[0]; - summary.gplace.egr_tof = egr_tof[0]; - summary.gplace.egr_mof = egr_mof[0]; - summary.gplace.egr_ace = egr_ace[0]; - summary.gplace.tns = tns[0]; - summary.gplace.wns = wns[0]; - summary.gplace.suggest_freq = suggest_freq[0]; + // summary.gplace.egr_tof = egr_tof[0]; + // summary.gplace.egr_mof = egr_mof[0]; + // summary.gplace.egr_ace = egr_ace[0]; + // summary.gplace.tns = tns[0]; + // summary.gplace.wns = wns[0]; + // summary.gplace.suggest_freq = suggest_freq[0]; summary.dplace.place_density = place_density[1]; - summary.dplace.pin_density = pin_density[1]; - summary.dplace.HPWL = HPWL[1]; - summary.dplace.STWL = STWL[1]; - summary.dplace.GRWL = GRWL[1]; + // summary.dplace.pin_density = pin_density[1]; + // summary.dplace.HPWL = HPWL[1]; + // summary.dplace.STWL = STWL[1]; + // summary.dplace.GRWL = GRWL[1]; - summary.dplace.egr_tof = egr_tof[1]; - summary.dplace.egr_mof = egr_mof[1]; - summary.dplace.egr_ace = egr_ace[1]; - summary.dplace.tns = tns[1]; - summary.dplace.wns = wns[1]; - summary.dplace.suggest_freq = suggest_freq[1]; + // summary.dplace.egr_tof = egr_tof[1]; + // summary.dplace.egr_mof = egr_mof[1]; + // summary.dplace.egr_ace = egr_ace[1]; + // summary.dplace.tns = tns[1]; + // summary.dplace.wns = wns[1]; + // summary.dplace.suggest_freq = suggest_freq[1]; auto* pl_design = PlacerDBInst.get_design(); summary.instance_cnt = pl_design->get_instances_range(); @@ -1014,17 +1014,17 @@ ieda_feature::PlaceSummary PLAPI::outputSummary(std::string step) // 3:合法化需要存储的数据参数 else if (step == "legalization") { summary.lg_summary.pl_common_summary.place_density = place_density[2]; - summary.lg_summary.pl_common_summary.pin_density = pin_density[2]; - summary.lg_summary.pl_common_summary.HPWL = HPWL[2]; - summary.lg_summary.pl_common_summary.STWL = STWL[2]; - summary.lg_summary.pl_common_summary.GRWL = GRWL[2]; + // summary.lg_summary.pl_common_summary.pin_density = pin_density[2]; + // summary.lg_summary.pl_common_summary.HPWL = HPWL[2]; + // summary.lg_summary.pl_common_summary.STWL = STWL[2]; + // summary.lg_summary.pl_common_summary.GRWL = GRWL[2]; - summary.lg_summary.pl_common_summary.egr_tof = egr_tof[2]; - summary.lg_summary.pl_common_summary.egr_mof = egr_mof[2]; - summary.lg_summary.pl_common_summary.egr_ace = egr_ace[2]; - summary.lg_summary.pl_common_summary.tns = tns[2]; - summary.lg_summary.pl_common_summary.wns = wns[2]; - summary.lg_summary.pl_common_summary.suggest_freq = suggest_freq[2]; + // summary.lg_summary.pl_common_summary.egr_tof = egr_tof[2]; + // summary.lg_summary.pl_common_summary.egr_mof = egr_mof[2]; + // summary.lg_summary.pl_common_summary.egr_ace = egr_ace[2]; + // summary.lg_summary.pl_common_summary.tns = tns[2]; + // summary.lg_summary.pl_common_summary.wns = wns[2]; + // summary.lg_summary.pl_common_summary.suggest_freq = suggest_freq[2]; summary.lg_summary.lg_total_movement = PlacerDBInst.lg_total_movement; summary.lg_summary.lg_max_movement = PlacerDBInst.lg_max_movement; diff --git a/src/operation/iPL/api/external_api/ExternalAPI.cc b/src/operation/iPL/api/external_api/ExternalAPI.cc index 2e50fc932..d1bf4eec4 100644 --- a/src/operation/iPL/api/external_api/ExternalAPI.cc +++ b/src/operation/iPL/api/external_api/ExternalAPI.cc @@ -175,14 +175,14 @@ ieval::TotalWLSummary ExternalAPI::evalproIDBWL() ieval::OverflowSummary ExternalAPI::evalproCongestion() { - CONGESTION_API_INST->egrMap(); + CONGESTION_API_INST->egrMap("place"); - return CONGESTION_API_INST->egrOverflow(); + return CONGESTION_API_INST->egrOverflow("place"); } float ExternalAPI::obtainPeakAvgPinDens() { - ieval::PinMapSummary pin_map_summary = DENSITY_API_INST->pinDensityMap(); + ieval::PinMapSummary pin_map_summary = DENSITY_API_INST->pinDensityMap("place"); std::string file_path = pin_map_summary.allcell_pin_density; std::ifstream file(file_path); diff --git a/src/operation/iPL/source/module/global_placer/electrostatic_placer/database/BinGrid.hh b/src/operation/iPL/source/module/global_placer/electrostatic_placer/database/BinGrid.hh index 1fd5174cb..cdbfc5e5f 100644 --- a/src/operation/iPL/source/module/global_placer/electrostatic_placer/database/BinGrid.hh +++ b/src/operation/iPL/source/module/global_placer/electrostatic_placer/database/BinGrid.hh @@ -33,9 +33,9 @@ #include #include "GridManager.hh" -#include "TopologyManager.hh" -#include "Parameter.hh" #include "NesInstance.hh" +#include "Parameter.hh" +#include "TopologyManager.hh" namespace ipl { @@ -72,17 +72,17 @@ class BinGrid int64_t get_overflow_area_without_filler() const { return _overflow_area_wofiller; } void set_thread_nums(int32_t thread_nums) { _thread_nums = thread_nums; } - void set_route_cap_h(int num) {_route_cap_h = num;} - void set_route_cap_v(int num) {_route_cap_v = num;} - void set_partial_route_cap_h(int num) {_partial_route_cap_h = num;} - void set_partial_route_cap_v(int num) {_partial_route_cap_v = num;} + void set_route_cap_h(int num) { _route_cap_h = num; } + void set_route_cap_v(int num) { _route_cap_v = num; } + void set_partial_route_cap_h(int num) { _partial_route_cap_h = num; } + void set_partial_route_cap_v(int num) { _partial_route_cap_v = num; } void initNesInstanceTypeList(std::vector& nInst_list); void updateBinGrid(std::vector& nInst_list, int32_t thread_num); void updataOverflowArea(std::vector& nInst_list, int32_t thread_num); - void evalRouteDem(const std::vector& network_list,int32_t thread_num); + void evalRouteDem(const std::vector& network_list, int32_t thread_num); void evalRouteCap(int32_t thread_num); void evalRouteUtil(); void plotRouteCap(); @@ -96,7 +96,7 @@ class BinGrid std::vector obtainOccupiedBinList(NesInstance* nInst); // TODO. std::vector obtainOccupiednInstList(Grid* bin); // TODO. - GridManager* get_grid_manager() const {return _grid_manager;} + GridManager* get_grid_manager() const { return _grid_manager; } private: GridManager* _grid_manager; @@ -114,7 +114,7 @@ class BinGrid int32_t _bin_cnt_y; int32_t _bin_size_x; int32_t _bin_size_y; - + int _route_cap_h; int _route_cap_v; int _partial_route_cap_h; @@ -125,7 +125,7 @@ class BinGrid void resetBinToArea(); - float calcLness(std::vector>& point_set, int32_t xmin, int32_t xmax, int32_t ymin, int32_t ymax); + double calcLness(std::vector>& point_set, int32_t xmin, int32_t xmax, int32_t ymin, int32_t ymax); int64_t calcLowerLeftRP(std::vector>& point_set, int32_t xmin, int32_t ymin); int64_t calcLowerRightRP(std::vector>& point_set, int32_t xmax, int32_t ymin); int64_t calcUpperLeftRP(std::vector>& point_set, int32_t xmin, int32_t ymax); @@ -164,7 +164,7 @@ inline void BinGrid::initNesInstanceTypeList(std::vector& nInst_li { for (auto* nInst : nInst_list) { if (nInst->isFixed()) { - if (nInst->isMacro()){ + if (nInst->isMacro()) { _route_macro_inst_list.push_back(nInst); } continue; @@ -258,34 +258,34 @@ inline void BinGrid::updataOverflowArea(std::vector& nInst_list, i _overflow_area_wofiller = overflow_area_wofiller; } -inline void BinGrid::evalRouteDem(const std::vector& network_list,int32_t thread_num) +inline void BinGrid::evalRouteDem(const std::vector& network_list, int32_t thread_num) { _grid_manager->clearRUDY(); - int wire_space_h = _bin_size_y / (_route_cap_h / _bin_cnt_y); + int wire_space_h = _bin_size_y / (_route_cap_h / _bin_cnt_y); int wire_space_v = _bin_size_x / (_route_cap_v / _bin_cnt_x); float dm_h = 4; float dm_v = 4; #pragma omp parallel for num_threads(thread_num) for (auto* network : network_list) { - if (network->isIgnoreNetwork()){ + if (network->isIgnoreNetwork()) { continue; } - + auto net_shape = std::move(network->obtainNetWorkShape()); - if (net_shape.get_ll_x() > net_shape.get_ur_x()){ + if (net_shape.get_ll_x() > net_shape.get_ur_x()) { continue; } - if (net_shape.get_ur_x() > _grid_manager->get_shape().get_ur_x()){ + if (net_shape.get_ur_x() > _grid_manager->get_shape().get_ur_x()) { net_shape.set_upper_right(_grid_manager->get_shape().get_ur_x(), net_shape.get_ur_y()); } - if (net_shape.get_ur_y() > _grid_manager->get_shape().get_ur_y()){ + if (net_shape.get_ur_y() > _grid_manager->get_shape().get_ur_y()) { net_shape.set_upper_right(net_shape.get_ur_x(), _grid_manager->get_shape().get_ur_y()); } - if (net_shape.get_ll_x() < _grid_manager->get_shape().get_ll_x()){ - net_shape.set_lower_left(_grid_manager->get_shape().get_ll_x(),net_shape.get_ll_y()); + if (net_shape.get_ll_x() < _grid_manager->get_shape().get_ll_x()) { + net_shape.set_lower_left(_grid_manager->get_shape().get_ll_x(), net_shape.get_ll_y()); } - if (net_shape.get_ll_y() < _grid_manager->get_shape().get_ll_y()){ + if (net_shape.get_ll_y() < _grid_manager->get_shape().get_ll_y()) { net_shape.set_lower_left(net_shape.get_ll_x(), _grid_manager->get_shape().get_ll_y()); } @@ -295,31 +295,31 @@ inline void BinGrid::evalRouteDem(const std::vector& network_list,int3 int32_t aspect_ratio = 1; if (net_width >= net_height && net_height != 0) { - aspect_ratio = std::round(net_width / net_height); + aspect_ratio = std::round(net_width / static_cast(net_height)); } else if (net_width < net_height && net_width != 0) { - aspect_ratio = std::round(net_height / net_width); + aspect_ratio = std::round(net_height / static_cast(net_width)); } - float l_ness = 0.0; - if (pin_num <= 3){ + double l_ness = 0.0; + if (pin_num <= 3) { l_ness = 1.0; - }else if (pin_num <= 15){ + } else if (pin_num <= 15) { std::vector> point_set; point_set.reserve(pin_num); - for (int i = 0; i < pin_num; ++i){ + for (int i = 0; i < pin_num; ++i) { const int32_t pin_x = network->get_node_list()[i]->get_location().get_x(); const int32_t pin_y = network->get_node_list()[i]->get_location().get_y(); - point_set.emplace_back(std::make_pair(pin_x,pin_y)); + point_set.emplace_back(std::make_pair(pin_x, pin_y)); } l_ness = calcLness(point_set, net_shape.get_ll_x(), net_shape.get_ur_x(), net_shape.get_ll_y(), net_shape.get_ur_y()); - }else{ + } else { l_ness = 0.5; } l_ness = netWiringDistributionMapWeight(pin_num, aspect_ratio, l_ness); - + std::vector overlap_grid_list; _grid_manager->obtainOverlapGridList(overlap_grid_list, net_shape); - for (auto* grid : overlap_grid_list){ + for (auto* grid : overlap_grid_list) { auto& grid_h_cong = grid->h_cong; auto& grid_v_cong = grid->v_cong; @@ -336,10 +336,10 @@ inline void BinGrid::evalRouteDem(const std::vector& network_list,int3 float tmp_h_cong = 0.0; float tmp_v_cong = 0.0; - if (net_shape.get_height()!= 0){ + if (net_shape.get_height() != 0) { tmp_h_cong = l_ness * overlap_area * wire_space_h * dm_h / static_cast(net_shape.get_height()); } - if (net_shape.get_width() != 0){ + if (net_shape.get_width() != 0) { tmp_v_cong = l_ness * overlap_area * wire_space_v * dm_v / static_cast(net_shape.get_width()); } @@ -356,26 +356,24 @@ inline void BinGrid::fastGaussianBlur() _grid_manager->blurRouteDemand(); } - - -inline float BinGrid::calcLness(std::vector>& point_set, int32_t xmin, int32_t xmax, int32_t ymin, int32_t ymax) +inline double BinGrid::calcLness(std::vector>& point_set, int32_t xmin, int32_t xmax, int32_t ymin, + int32_t ymax) { - int64_t bbox = (xmax - xmin) * (ymax - ymin); - int64_t R1 = calcLowerLeftRP(point_set, xmin, ymin); - int64_t R2 = calcLowerRightRP(point_set, xmax, ymin); - int64_t R3 = calcUpperLeftRP(point_set, xmin, ymax); - int64_t R4 = calcUpperRightRP(point_set, xmax, ymax); - int64_t R = std::max({R1, R2, R3, R4}); - float l_ness; + int64_t bbox = static_cast(xmax - xmin) * static_cast(ymax - ymin); + int64_t r1 = calcLowerLeftRP(point_set, xmin, ymin); + int64_t r2 = calcLowerRightRP(point_set, xmax, ymin); + int64_t r3 = calcUpperLeftRP(point_set, xmin, ymax); + int64_t r4 = calcUpperRightRP(point_set, xmax, ymax); + int64_t r = std::max({r1, r2, r3, r4}); + double l_ness; if (bbox != 0) { - l_ness = R / bbox; + l_ness = static_cast(r) / static_cast(bbox); } else { l_ness = 1.0; } return l_ness; } - inline int64_t BinGrid::calcLowerLeftRP(std::vector>& point_set, int32_t xmin, int32_t ymin) { std::sort(point_set.begin(), point_set.end()); // Sort point_set with x-coordinates in ascending order @@ -436,25 +434,22 @@ inline int64_t BinGrid::calcUpperRightRP(std::vector return R; } - inline void BinGrid::evalRouteCap(int32_t thread_num) { int32_t bin_capa_h = _bin_size_x * _bin_size_y; int32_t bin_capa_v = bin_capa_h; _grid_manager->initRouteCap(bin_capa_h, bin_capa_v); - float util_h = _partial_route_cap_h / (float)_route_cap_h ; - float util_v = _partial_route_cap_v / (float)_route_cap_v ; - + float util_h = _partial_route_cap_h / (float) _route_cap_h; + float util_v = _partial_route_cap_v / (float) _route_cap_v; + #pragma omp parallel for num_threads(thread_num) - for(size_t i = 0; i < _route_macro_inst_list.size(); ++i) - { + for (size_t i = 0; i < _route_macro_inst_list.size(); ++i) { auto macro_shape = _route_macro_inst_list[i]->get_origin_shape(); std::vector overlap_grid_list; _grid_manager->obtainOverlapGridList(overlap_grid_list, macro_shape); - for (auto* grid : overlap_grid_list) - { + for (auto* grid : overlap_grid_list) { auto& grid_h_cap = grid->h_cap; auto& grid_v_cap = grid->v_cap; @@ -476,7 +471,6 @@ inline void BinGrid::evalRouteCap(int32_t thread_num) } } - inline void BinGrid::evalRouteUtil() { _grid_manager->evalRouteUtil(); @@ -495,22 +489,21 @@ inline void BinGrid::plotOverflowUtil(float sum_overflow, int32_t iter_num) // plot_h << feed_h.str() << std::endl; } - inline void BinGrid::plotRouteCap() { _grid_manager->plotRouteCap(); } -inline void BinGrid::plotRouteDem(){ +inline void BinGrid::plotRouteDem() +{ _grid_manager->plotRouteDem(); } -inline void BinGrid::plotRouteUtil(int32_t iter_num){ +inline void BinGrid::plotRouteUtil(int32_t iter_num) +{ _grid_manager->plotRouteUtil(iter_num); } - - inline int64_t BinGrid::obtainOverflowAreaWithoutFiller() { int64_t overflow_area = 0; diff --git a/src/operation/iPW/CMakeLists.txt b/src/operation/iPW/CMakeLists.txt index bb11dedcf..01bdb180e 100644 --- a/src/operation/iPW/CMakeLists.txt +++ b/src/operation/iPW/CMakeLists.txt @@ -5,7 +5,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) set(CMAKE_CXX_STANDARD 20) set(SANITIZER OFF) - if(SANITIZER) add_compile_options("-fsanitize=thread") link_libraries("-fsanitize=thread") @@ -32,6 +31,12 @@ include_directories(${PROJECT_SOURCE_DIR}/src/operation/iPW/source/module) include_directories(${HOME_THIRDPARTY}/pybind11) + +if (USE_GPU) +message("power use gpu mode.") +add_subdirectory(source/gpu-kernel) +endif() + add_subdirectory(api) add_subdirectory(source/module/core) add_subdirectory(source/module/ops/annotate_toggle_sp) @@ -45,6 +50,7 @@ add_subdirectory(source/module/ops/read_vcd) add_subdirectory(source/module/ops/plot_power) add_subdirectory(source/shell-cmd) add_subdirectory(source/python-api) + add_subdirectory(test) add_executable(iPower main.cc) diff --git a/src/operation/iPW/api/CMakeLists.txt b/src/operation/iPW/api/CMakeLists.txt index bda7f3f8d..225dc3e22 100644 --- a/src/operation/iPW/api/CMakeLists.txt +++ b/src/operation/iPW/api/CMakeLists.txt @@ -9,7 +9,12 @@ aux_source_directory(./ SRC) add_library(power ${SRC}) +if (USE_GPU) +target_link_libraries(power power-gpu core vcd_wrapper build_graph propagate_toggle_sp levelize dump calc_power plot_power) +else () target_link_libraries(power core vcd_wrapper build_graph propagate_toggle_sp levelize dump calc_power plot_power) +endif() + target_include_directories(power PUBLIC ${PROJECT_SOURCE_DIR}/src/operation/iPW/source/module diff --git a/src/operation/iPW/api/PowerEngine.cc b/src/operation/iPW/api/PowerEngine.cc index c229e54e7..2a1919d2e 100644 --- a/src/operation/iPW/api/PowerEngine.cc +++ b/src/operation/iPW/api/PowerEngine.cc @@ -27,6 +27,10 @@ #include "PowerEngine.hh" #include "ThreadPool/ThreadPool.h" +#include "gpu-kernel/kernel_common.h" +#ifdef USE_GPU +#include "gpu-kernel/power_kernel.cuh" +#endif #include "usage/usage.hh" namespace ipower { @@ -235,49 +239,57 @@ std::vector PowerEngine::buildMacroConnectionMap( // dfs macro connecton from one seq vertex. std::function&, unsigned)> - dfs_from_src_seq_vertex = - [¯o_connections, &connection_mutex, &max_hop, - &dfs_from_src_seq_vertex](PwrSeqVertex* src_marco_vertex, - PwrSeqVertex* current_macro_vertex, - std::vector stages_each_hop, - unsigned hop) { - if (hop == 0) { - return; - } + dfs_from_src_seq_vertex = [¯o_connections, &connection_mutex, + &max_hop, &dfs_from_src_seq_vertex]( + PwrSeqVertex* src_seq_vertex, + PwrSeqVertex* current_macro_vertex, + std::vector stages_each_hop, + unsigned hop) { + if (hop == 0) { + return; + } - std::tuple one_connection; - auto& src_arcs = current_macro_vertex->get_src_arcs(); - for (auto* src_arc : src_arcs) { - auto* snk_seq_vertex = src_arc->get_snk(); - stages_each_hop[max_hop - hop] = src_arc->get_combine_depth(); - if (snk_seq_vertex->isMacro()) { - std::string snk_obj_name(snk_seq_vertex->get_obj_name()); - MacroConnection one_connection( - src_marco_vertex->get_own_seq_inst()->get_name(), - snk_seq_vertex->get_own_seq_inst()->get_name(), - stages_each_hop, max_hop - hop + 1); - { - // add connection. - std::lock_guard lk(connection_mutex); - macro_connections.emplace_back(std::move(one_connection)); - } - } - - dfs_from_src_seq_vertex(src_marco_vertex, snk_seq_vertex, - stages_each_hop, hop - 1); + std::tuple one_connection; + auto& src_arcs = current_macro_vertex->get_src_arcs(); + for (auto* src_arc : src_arcs) { + auto* snk_seq_vertex = src_arc->get_snk(); + stages_each_hop[max_hop - hop] = src_arc->get_combine_depth(); + if (snk_seq_vertex->isMacro() || snk_seq_vertex->isOutputPort()) { + const char* src_vertex_name = src_seq_vertex->get_obj_name().data(); + const char* snk_vertex_name = snk_seq_vertex->get_obj_name().data(); + if (src_seq_vertex->isInputPort() || + snk_seq_vertex->isOutputPort()) { + LOG_INFO_FIRST_N(100) << "port connection: " << src_vertex_name + << " -> " << snk_vertex_name; } - }; + MacroConnection one_connection(src_vertex_name, snk_vertex_name, + stages_each_hop, max_hop - hop + 1); + { + // add connection. + std::lock_guard lk(connection_mutex); + macro_connections.emplace_back(std::move(one_connection)); + + LOG_INFO_EVERY_N(2000000) + << "build macro connection num: " << macro_connections.size(); + } + } + + dfs_from_src_seq_vertex(src_seq_vertex, snk_seq_vertex, + stages_each_hop, hop - 1); + } + }; { ThreadPool thread_pool(48); PwrSeqVertex* seq_vertex; FOREACH_SEQ_VERTEX(&seq_graph, seq_vertex) { - if (seq_vertex->isMacro()) { + if (seq_vertex->isMacro() || seq_vertex->isInputPort()) { + // dfs from src seq vertex. thread_pool.enqueue( - [max_hop, &dfs_from_src_seq_vertex](auto* src_marco_vertex, + [max_hop, &dfs_from_src_seq_vertex](auto* src_seq_vertex, auto* current_macro_vertex) { std::vector stages_each_hop(max_hop, 0); - dfs_from_src_seq_vertex(src_marco_vertex, current_macro_vertex, + dfs_from_src_seq_vertex(src_seq_vertex, current_macro_vertex, stages_each_hop, max_hop); }, seq_vertex, seq_vertex); @@ -290,6 +302,7 @@ std::vector PowerEngine::buildMacroConnectionMap( } LOG_INFO << "build macro connection map end"; + LOG_INFO << "build macro connection num: " << macro_connections.size(); double memory_delta = stats.memoryDelta(); LOG_INFO << "build macro connection map memory usage " << memory_delta << "MB"; @@ -299,4 +312,161 @@ std::vector PowerEngine::buildMacroConnectionMap( return macro_connections; } +#ifdef USE_GPU +/** + * @brief build macro connection map with gpu kernel. + * + * @param max_hop + * @return std::vector + */ +std::vector PowerEngine::buildMacroConnectionMapWithGPU( + unsigned max_hop) { + ieda::Stats stats; + LOG_INFO << "gpu build macro connection map start"; + auto& seq_graph = _ipower->get_power_seq_graph(); + int num_macro = seq_graph.getMacroSeqVertexNum(); + // The first connection point is the src macro vertex. + std::vector connection_points(num_macro); + + std::map vertex_to_id; + int num_seq_vertexes = seq_graph.get_vertexes().size(); + std::vector is_macros(num_seq_vertexes, 0); + PwrSeqVertex* seq_vertex; + int i = 0; // for seq vertex index. + int j = 0; // for connection point index. + FOREACH_SEQ_VERTEX(&seq_graph, seq_vertex) { + if (seq_vertex->isMacro()) { + connection_points[j]._src_id = i; + connection_points[j++]._snk_id = i; + is_macros[i] = 1; + } + vertex_to_id[seq_vertex] = i; + ++i; + } + + LOG_FATAL_IF(j != num_macro) << "Macro num is " << j; + + // build cpu data for gpu data communcation. + std::vector seq_arcs; // seq arc snk id vector. + std::vector snk_arcs; // snk arc [start, end] pair id vector. + std::vector snk_depths; // snk arc combine cell depth vector. + FOREACH_SEQ_VERTEX(&seq_graph, seq_vertex) { + PwrSeqArc* seq_arc; + std::pair snk_arc_id_pair{-1, -1}; + FOREACH_SRC_SEQ_ARC(seq_vertex, seq_arc) { + auto* snk_seq_vertex = seq_arc->get_snk(); + unsigned snk_seq_vertex_id = vertex_to_id[snk_seq_vertex]; + seq_arcs.push_back(snk_seq_vertex_id); + snk_depths.push_back(seq_arc->get_combine_depth()); + + if (snk_arc_id_pair.first == -1) { + snk_arc_id_pair.first = seq_arcs.size() - 1; + } else { + snk_arc_id_pair.second = seq_arcs.size() - 1; + } + } + + // for only one arc. + snk_arcs.emplace_back(snk_arc_id_pair.first); + if (snk_arc_id_pair.second == -1) { + snk_arc_id_pair.second = snk_arc_id_pair.first; + } + snk_arcs.emplace_back(snk_arc_id_pair.second); + } + + LOG_INFO_IF(seq_arcs.size() != seq_graph.getSeqArcNum()) + << "the seq arc size " << seq_arcs.size() + << " is not equal to seq graph arc num " << seq_graph.getSeqArcNum(); + + std::size_t output_connection_size = seq_arcs.size(); + std::vector out_connection_points(output_connection_size); + int connection_point_num = connection_points.size(); + + auto& seq_vertexes = seq_graph.get_vertexes(); + + // use src arc to calc out connection num. + auto calc_out_connection_num = + [&seq_vertexes](auto& connection_points) -> int { + int out_connection_point_num = 0; + std::set connection_ids; + for (auto& connection_point : connection_points) { + int connection_id = connection_point._snk_id; + if (connection_ids.contains(connection_id)) { + continue; + } + connection_ids.insert(connection_id); + // get src arc num. + auto& seq_vertex = seq_vertexes[connection_id]; + out_connection_point_num += seq_vertex->get_src_arcs().size(); + } + + return out_connection_point_num; + }; + + // the actual number of out connection points. + int out_connection_point_num = calc_out_connection_num(connection_points); + + std::vector macro_connections; + bool is_free_memory = false; + // call gpu function to bfs seq arc. + for (unsigned i = 0; i < max_hop; ++i) { + is_free_memory = (i == max_hop - 1) ? true : false; + build_macro_connection_map(connection_points.data(), is_macros.data(), + seq_arcs.data(), snk_depths.data(), + snk_arcs.data(), connection_point_num, + num_seq_vertexes, output_connection_size, + out_connection_points.data(), is_free_memory); + + // out connection give to connection and build connection map. + connection_points.resize(out_connection_point_num); + int connection_point_index = 0; + for (std::size_t j = 0; j < output_connection_size; ++j) { + int src_id = out_connection_points[j]._src_id; + int snk_id = out_connection_points[j]._snk_id; + // not tranversed, skip. + if (snk_id == -1) { + continue; + } + // set connection point + connection_points[connection_point_index]._src_id = src_id; + connection_points[connection_point_index++]._snk_id = snk_id; + + if (seq_vertexes.at(snk_id)->isMacro()) { + // build macro connection. + MacroConnection macro_connection; + macro_connection._src_macro_name = + seq_vertexes[src_id]->get_own_seq_inst()->get_name(); + macro_connection._dst_macro_name = + seq_vertexes[snk_id]->get_own_seq_inst()->get_name(); + + macro_connections.emplace_back(std::move(macro_connection)); + } + + // reset data. + out_connection_points[j]._src_id = -1; + out_connection_points[j]._snk_id = -1; + } + + LOG_FATAL_IF(connection_point_index != out_connection_point_num) + << "connection_point_index " << connection_point_index + << " is not equal to out_connection_point_num " + << out_connection_point_num; + + // update connection num and out connetion point num. + connection_point_num = out_connection_point_num; + out_connection_point_num = calc_out_connection_num(connection_points); + } + + LOG_INFO << "gpu build macro connection map end"; + double memory_delta = stats.memoryDelta(); + LOG_INFO << "gpu build macro connection map memory usage " << memory_delta + << "MB"; + double time_delta = stats.elapsedRunTime(); + LOG_INFO << "gpu build macro connection map time elapsed " << time_delta + << "s"; + + return macro_connections; +} +#endif + } // namespace ipower \ No newline at end of file diff --git a/src/operation/iPW/api/PowerEngine.hh b/src/operation/iPW/api/PowerEngine.hh index 9f12e6a14..45182a519 100644 --- a/src/operation/iPW/api/PowerEngine.hh +++ b/src/operation/iPW/api/PowerEngine.hh @@ -80,6 +80,10 @@ class PowerEngine { // api for build only macro connection. std::vector buildMacroConnectionMap(unsigned max_hop); +#ifdef USE_GPU + std::vector buildMacroConnectionMapWithGPU(unsigned max_hop); +#endif + private: PowerEngine(); ~PowerEngine(); diff --git a/src/operation/iPW/source/gpu-kernel/CMakeLists.txt b/src/operation/iPW/source/gpu-kernel/CMakeLists.txt new file mode 100644 index 000000000..64e786aff --- /dev/null +++ b/src/operation/iPW/source/gpu-kernel/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.15.0) + +cmake_policy(SET CMP0104 NEW) +set(CMAKE_CUDA_ARCHITECTURES native) + +find_package(CUDAToolkit) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CUDA_STANDARD 17) + +enable_language(CUDA) + +include(CheckLanguage) +check_language(CUDA) + +if(NOT CUDAToolkit_FOUND) + include(FindCUDAToolkit) +endif() + +set(lib_name "power-gpu") + +add_compile_options("-fopenmp") + +set(CMAKE_BUILD_TYPE "Release") + +if(${CMAKE_BUILD_TYPE} STREQUAL "Release") + set(NVCC_FLAGS -O3) + message(STATUS "${lib_name} compile cuda code in release mode") +else() + set(NVCC_FLAGS -G) + message(STATUS "${lib_name} compile cuda code in debug mode") +endif() + +file(GLOB_RECURSE source_file LIST_DIRECTORIES false *.cpp *.c *.cuh *.h *.cu) + +if(BUILD_STATIC_LIB) +add_library(${lib_name} ${source_file}) +else() +add_library(${lib_name} SHARED ${source_file}) +endif() + +target_include_directories(${lib_name} PUBLIC ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + +target_compile_options(${lib_name} PRIVATE $<$:${NVCC_FLAGS}>) + +message(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + +set_property(TARGET ${lib_name} PROPERTY LANGUAGES CXX CUDA) +set_target_properties(${lib_name} + PROPERTIES CUDA_SEPARABLE_COMPILATION ON + CUDA_RESOLVE_DEVICE_SYMBOLS ON) + +target_link_libraries(${lib_name} PRIVATE CUDA::cudart) + + diff --git a/src/operation/iPW/source/gpu-kernel/cuda_common.cuh b/src/operation/iPW/source/gpu-kernel/cuda_common.cuh new file mode 100644 index 000000000..280e520ca --- /dev/null +++ b/src/operation/iPW/source/gpu-kernel/cuda_common.cuh @@ -0,0 +1,22 @@ +/** + * @file kernel_common.h + * @author simin tao (taosm@pcl.ac.cn) + * @brief gpu cuda common functions file. + * @version 0.1 + * @date 2024-10-11 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include +#include "kernel_common.h" + + +inline void cudaCheck(cudaError_t error, const char *file, int line) { + if (error != cudaSuccess) { + printf("CUDA error at file %s:%d:\n%s\n", file, line, cudaGetErrorString(error)); + } +}; +#define cudaWithCheck(err) (cudaCheck(err, __FILE__, __LINE__)) diff --git a/src/operation/iPW/source/gpu-kernel/kernel_common.h b/src/operation/iPW/source/gpu-kernel/kernel_common.h new file mode 100644 index 000000000..0a1ac666b --- /dev/null +++ b/src/operation/iPW/source/gpu-kernel/kernel_common.h @@ -0,0 +1,25 @@ +/** + * @file kernel_common.h + * @author simin tao (taosm@pcl.ac.cn) + * @brief gpu kernel common functions file. + * @version 0.1 + * @date 2024-10-11 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include +#include + +inline void *malloc_check(size_t size, const char *file, int line) { + void *ptr = malloc(size); + if (ptr == NULL) { + printf("error: cpu memory allocation failed at %s:%d\n", file, line); + exit(EXIT_FAILURE); + } + return ptr; +} + +#define mallocWithCheck(size) malloc_check(size, __FILE__, __LINE__) \ No newline at end of file diff --git a/src/operation/iPW/source/gpu-kernel/power_kernel.cu b/src/operation/iPW/source/gpu-kernel/power_kernel.cu new file mode 100644 index 000000000..375770ca4 --- /dev/null +++ b/src/operation/iPW/source/gpu-kernel/power_kernel.cu @@ -0,0 +1,183 @@ +/** + * @file power_kernel.cu + * @author simin tao (taosm@pcl.ac.cn) + * @brief The power gpu kernel for speed up power tool. + * @version 0.1 + * @date 2024-10-09 + * + */ +#include "cuda_common.cuh" +#include "power_kernel.cuh" + +namespace ipower { + +const int THREAD_PER_BLOCK_NUM = 1024; + +/** + * @brief use gpu to do seq graph bfs. + * + * @param connection_points the tranverse from connection point. + * @param is_macros judge whether the seq vertex is a macro, each element is map to a seq vertex. + * @param seq_arcs the snk point each seq vertex src arc reach to. + * @param combine_depths each seq vertex src arc combine logic depth. + * @param snk_arcs each seq vertex snk arc [start, end] pair. + * @param connection_point_num the input connection point number. + * @param num_seq_vertexes the seq graph vertex number. + * @param num_seq_arcs the seq graph arc number. + * @param out_connection_points out connection point number. + * @return __global__ + */ +__global__ void find_next_hop_macro(GPUConnectionPoint* connection_points, + unsigned* is_macros, unsigned* seq_arcs, + unsigned* combine_depths, + unsigned* snk_arcs, + int connection_point_num, + int num_seq_vertexes, int num_seq_arcs, + GPUConnectionPoint* out_connection_points) { + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < connection_point_num) { + GPUConnectionPoint in_connection_point = connection_points[i]; + int seq_vertex_id = in_connection_point._snk_id; + unsigned start = snk_arcs[seq_vertex_id * 2]; + unsigned end = snk_arcs[seq_vertex_id * 2 + 1]; + for (unsigned j = start; j <= end; ++j) { + if (j >= num_seq_arcs) { + printf( + "thread %d seq vertex id %d seq index %d (start %d : end %d) " + "beyond seq arc index.\n", + i, seq_vertex_id, j, start, end); + } + unsigned snk_vertex = seq_arcs[j]; + out_connection_points[j]._src_id = in_connection_point._src_id; + out_connection_points[j]._snk_id = snk_vertex; + // printf( + // "thread %d traverse next hop src id %d -> snk id %d with out " + // "connection %d.\n", + // i, in_connection_point._src_id, snk_vertex, j); + } + + // printf("thread %d traverse the connection point %d next hop.\n", i, + // seq_vertex_id); + } +} + +/** + * @brief build the macro connection map + * + * @param seq_vertexes the seq vertex index. + * @param is_macros whether the seq vertex is macro. + * @param seq_arcs the seq snk arcs for each seq vertex. + * @param snk_arcs the snk arcs [start, end] for each seq vertex. + * @param N the number of the seq vertex. + * @param out_connection_points the output result of the macro connection + * points. + */ +void build_macro_connection_map(GPUConnectionPoint* connection_points, + unsigned* is_macros, unsigned* seq_arcs, + unsigned* snk_depths, unsigned* snk_arcs, + int connection_point_num, int num_seq_vertexes, + int num_seq_arcs, + GPUConnectionPoint* out_connection_points, bool is_free_memory) { + cudaStream_t stream1 = nullptr; + cudaStreamCreate(&stream1); + + // for copy to gpu memrory. + static GPUConnectionPoint* d_connection_points; + static unsigned* d_is_macros; + static unsigned* d_seq_arcs; + static unsigned* d_snk_depths; + static unsigned* d_snk_arcs; + static GPUConnectionPoint* d_out_connection_points; + + static bool is_init = false; + + // init gpu memory. + auto init_memory = [&]() { + + cudaWithCheck(cudaMallocAsync( + (void**)&d_is_macros, num_seq_vertexes * sizeof(unsigned), stream1)); + cudaWithCheck(cudaMallocAsync((void**)&d_seq_arcs, + num_seq_arcs * sizeof(unsigned), stream1)); + cudaWithCheck(cudaMallocAsync((void**)&d_snk_depths, + num_seq_arcs * sizeof(unsigned), stream1)); + // each point has start and end pair snk arc. + cudaWithCheck(cudaMallocAsync( + (void**)&d_snk_arcs, num_seq_vertexes * 2 * sizeof(unsigned), stream1)); + cudaWithCheck(cudaMallocAsync((void**)&d_out_connection_points, + num_seq_arcs * sizeof(GPUConnectionPoint), + stream1)); + + cudaStreamSynchronize(stream1); + + cudaWithCheck(cudaMemcpyAsync(d_is_macros, is_macros, + num_seq_vertexes * sizeof(unsigned), + cudaMemcpyHostToDevice, stream1)); + cudaWithCheck(cudaMemcpyAsync(d_seq_arcs, seq_arcs, + num_seq_arcs * sizeof(unsigned), + cudaMemcpyHostToDevice, stream1)); + cudaWithCheck(cudaMemcpyAsync(d_snk_depths, snk_depths, + num_seq_arcs * sizeof(unsigned), + cudaMemcpyHostToDevice, stream1)); + // each point has start and end pair snk arc. + cudaWithCheck(cudaMemcpyAsync(d_snk_arcs, snk_arcs, + num_seq_vertexes * 2 * sizeof(unsigned), + cudaMemcpyHostToDevice, stream1)); + }; + + if (!is_init) { + init_memory(); + is_init = true; + } + + // need alloc memory every time. + cudaWithCheck(cudaMallocAsync( + (void**)&d_connection_points, + connection_point_num * sizeof(GPUConnectionPoint), stream1)); + + cudaWithCheck( + cudaMemcpyAsync(d_connection_points, connection_points, + connection_point_num * sizeof(GPUConnectionPoint), + cudaMemcpyHostToDevice, stream1)); + + cudaWithCheck(cudaMemcpyAsync(d_out_connection_points, out_connection_points, + num_seq_arcs * sizeof(GPUConnectionPoint), + cudaMemcpyHostToDevice, stream1)); + cudaStreamSynchronize(stream1); + + int num_blocks = + (connection_point_num + THREAD_PER_BLOCK_NUM - 1) / THREAD_PER_BLOCK_NUM; + + printf("use block number %d per block num %d, start run gpu kernel.\n", num_blocks, + THREAD_PER_BLOCK_NUM); + + find_next_hop_macro<<>>( + d_connection_points, d_is_macros, d_seq_arcs, d_snk_depths, d_snk_arcs, + connection_point_num, num_seq_vertexes, num_seq_arcs, + d_out_connection_points); + + // wait to finish. + cudaDeviceSynchronize(); + + printf("run gpu kernel finished.\n"); + + // copy back to host. + cudaWithCheck(cudaMemcpyAsync(out_connection_points, d_out_connection_points, + num_seq_arcs * sizeof(GPUConnectionPoint), + cudaMemcpyDeviceToHost, stream1)); + + cudaDeviceSynchronize(); + + cudaStreamDestroy(stream1); + + // free memory. + cudaWithCheck(cudaFree(d_connection_points)); + if (is_free_memory) { + cudaWithCheck(cudaFree(d_is_macros)); + cudaWithCheck(cudaFree(d_seq_arcs)); + cudaWithCheck(cudaFree(d_snk_depths)); + cudaWithCheck(cudaFree(d_snk_arcs)); + cudaWithCheck(cudaFree(d_out_connection_points)); + } +} + +} // namespace ipower \ No newline at end of file diff --git a/src/operation/iPW/source/gpu-kernel/power_kernel.cuh b/src/operation/iPW/source/gpu-kernel/power_kernel.cuh new file mode 100644 index 000000000..1fd2605e7 --- /dev/null +++ b/src/operation/iPW/source/gpu-kernel/power_kernel.cuh @@ -0,0 +1,63 @@ +// *************************************************************************************** +// 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. +// *************************************************************************************** +/** + * @file power_kernel.cuh + * @author simin tao (taosm@pcl.ac.cn) + * @brief The power gpu kernel for speed up power tool. + * @version 0.1 + * @date 2024-10-09 + * + */ +#pragma once + +#include +#include "kernel_common.h" + +namespace ipower { + +/** + * @brief for gpu kernel function used to store connection point. + * + */ +struct GPUConnectionPoint { + int _src_id = -1; + int _snk_id = -1; + unsigned _last_depth; // The last hop combine depth. +}; + + +/** + * @brief build macro connection map with gpu kernel function. + * + * @param connection_points + * @param is_macros + * @param seq_arcs + * @param snk_depths + * @param snk_arcs + * @param connection_point_num + * @param num_seq_vertexes + * @param num_seq_arcs + * @param out_connection_points + */ +void build_macro_connection_map(GPUConnectionPoint* connection_points, + unsigned* is_macros, unsigned* seq_arcs, + unsigned* snk_depths, unsigned* snk_arcs, + int connection_point_num, int num_seq_vertexes, + int num_seq_arcs, + GPUConnectionPoint* out_connection_points, bool is_free_memory); + +} \ No newline at end of file diff --git a/src/operation/iPW/source/module/core/PwrSeqGraph.cc b/src/operation/iPW/source/module/core/PwrSeqGraph.cc index 531e729a8..111a0344d 100644 --- a/src/operation/iPW/source/module/core/PwrSeqGraph.cc +++ b/src/operation/iPW/source/module/core/PwrSeqGraph.cc @@ -29,6 +29,7 @@ namespace ipower { +// static std::shared_mutex rw_mutex; //! For synchronization read write seq data. /** * @brief add power vertex of the graph. * @@ -48,9 +49,27 @@ void PwrSeqGraph::addPwrSeqVertex(PwrSeqVertex* vertex) { void PwrSeqGraph::addPwrSeqArc(PwrSeqArc* arc) { static std::mutex mt; std::lock_guard lk(mt); + // std::unique_lock lock(rw_mutex); _arcs.emplace_back(arc); } +/** + * @brief find seq arc. + * + * @param src_vertex + * @param snk_vertex + * @return PwrSeqArc* + */ +PwrSeqArc* PwrSeqGraph::findSeqArc(PwrSeqVertex* src_vertex, + PwrSeqVertex* snk_vertex) { + // std::shared_lock lock(rw_mutex); + auto it = std::find_if( + _arcs.begin(), _arcs.end(), [src_vertex, snk_vertex](auto& arc) { + return arc->get_src() == src_vertex && arc->get_snk() == snk_vertex; + }); + return it != _arcs.end() ? it->get() : nullptr; +} + /** * @brief insert seq instance to and seq vertex mapping. * diff --git a/src/operation/iPW/source/module/core/PwrSeqGraph.hh b/src/operation/iPW/source/module/core/PwrSeqGraph.hh index 238e6f5b6..32ee30f0e 100644 --- a/src/operation/iPW/source/module/core/PwrSeqGraph.hh +++ b/src/operation/iPW/source/module/core/PwrSeqGraph.hh @@ -30,6 +30,7 @@ #include #include #include +#include #include "BTreeSet.hh" #include "PwrVertex.hh" @@ -87,7 +88,7 @@ class PwrSeqVertex { using PwrSeqArcSet = std::set; - auto get_obj_name() const { return _obj_name; } + auto& get_obj_name() const { return _obj_name; } [[nodiscard]] unsigned isInputPort() const { return _is_input_port; } void set_is_input_port() { _is_input_port = 1; } @@ -254,6 +255,8 @@ class PwrSeqGraph { void addPwrSeqArc(PwrSeqArc* arc); auto& get_arcs() { return _arcs; } + PwrSeqArc* findSeqArc(PwrSeqVertex* src_vertex, PwrSeqVertex* snk_vertex); + void addInputPortVerex(PwrSeqVertex* vertex) { _input_port_vertexes.emplace_back(vertex); } @@ -326,6 +329,7 @@ class PwrSeqGraph { _obj_to_vertex; //!< The seq belong inst to graph vertex. std::map _port_to_vertex; //!< The seq belong power port to graph vertex. + }; /** @@ -354,7 +358,7 @@ class PwrSeqGraph { * */ #define FOREACH_SEQ_ARC(graph, arc) \ - if (auto& arcs = graph->get_arcs(); !arcs.empty()) \ + if (auto& arcs = (graph)->get_arcs(); !arcs.empty()) \ for (auto p = arcs.begin(); \ p != arcs.end() ? arc = p->get(), true : false; ++p) } // namespace ipower diff --git a/src/operation/iPW/source/module/core/PwrVertex.cc b/src/operation/iPW/source/module/core/PwrVertex.cc index 37cbf5323..6bb111665 100644 --- a/src/operation/iPW/source/module/core/PwrVertex.cc +++ b/src/operation/iPW/source/module/core/PwrVertex.cc @@ -55,8 +55,17 @@ std::optional PwrVertex::getDriveVoltage() { // for port. auto* the_net = design_obj->get_net(); auto the_loads = the_net->getLoads(); - auto* one_load = the_loads.front(); - design_obj = one_load; + for (auto* one_load : the_loads) { + if (one_load->isPin()) { + design_obj = one_load; + break; + } + } + } + + if (design_obj->isPort()) { + // TODO(to taosimin), fix io volatage. + return 0.0; } auto* liberty_port = dynamic_cast(design_obj)->get_cell_port(); diff --git a/src/operation/iPW/source/module/ops/build_graph/PwrBuildGraph.cc b/src/operation/iPW/source/module/ops/build_graph/PwrBuildGraph.cc index 6a0793afc..7dfe14229 100644 --- a/src/operation/iPW/source/module/ops/build_graph/PwrBuildGraph.cc +++ b/src/operation/iPW/source/module/ops/build_graph/PwrBuildGraph.cc @@ -107,6 +107,10 @@ unsigned PwrBuildGraph::operator()(StaGraph* sta_graph) { auto* pwr_src_vertex = _power_graph.staToPwrVertex(sta_src_vertex); auto* pwr_snk_vertex = _power_graph.staToPwrVertex(sta_snk_vertex); + if (sta_arc->is_loop_disable()) { + continue; + } + std::unique_ptr power_arc; // power arc only exist for delay arc. if (sta_arc->isInstArc()) { diff --git a/src/operation/iPW/source/module/ops/calc_power/PwrCalcInternalPower.cc b/src/operation/iPW/source/module/ops/calc_power/PwrCalcInternalPower.cc index 6dce8bff6..661f70e19 100644 --- a/src/operation/iPW/source/module/ops/calc_power/PwrCalcInternalPower.cc +++ b/src/operation/iPW/source/module/ops/calc_power/PwrCalcInternalPower.cc @@ -23,7 +23,6 @@ */ #include "PwrCalcInternalPower.hh" - #include "PwrCalcSPData.hh" namespace ipower { using ieda::Stats; @@ -94,8 +93,12 @@ double PwrCalcInternalPower::calcCombInputPinPower(Instance* inst, // rise power auto rise_slew = (*the_input_sta_vertex) ->getSlewNs(AnalysisMode::kMax, TransType::kRise); - LOG_FATAL_IF(!rise_slew) - << (*the_input_sta_vertex)->getName() << " rise slew is not exist."; + if (!rise_slew) { + LOG_ERROR_IF(!rise_slew) + << (*the_input_sta_vertex)->getName() << " rise slew is not exist."; + continue; + } + double rise_power = internal_power->gatePower(TransType::kRise, *rise_slew, std ::nullopt); double rise_power_mw = lib_cell->convertTablePowerToMw(rise_power); @@ -217,6 +220,11 @@ double PwrCalcInternalPower::calcOutputPinPower(Instance* inst, auto* power_arc_set = dynamic_cast(snk_arc)->get_power_arc_set(); + + if (!power_arc_set) { + continue; + } + LibPowerArc* power_arc; FOREACH_POWER_LIB_ARC(power_arc_set, power_arc) { auto [rise_power_mw, rise_input_slew_ns, rise_output_load] = @@ -376,11 +384,16 @@ double PwrCalcInternalPower::calcSeqInputPinPower(Instance* inst, // rise power auto rise_slew = (*the_input_sta_vertex) ->getSlewNs(AnalysisMode::kMax, TransType::kRise); - LOG_FATAL_IF(!rise_slew) + + double rise_power_mw = 0.0; + LOG_ERROR_IF(!rise_slew) << (*the_input_sta_vertex)->getName() << " rise slew is not exist."; - double rise_power = - internal_power->gatePower(TransType::kRise, *rise_slew, std ::nullopt); - double rise_power_mw = lib_cell->convertTablePowerToMw(rise_power); + if (rise_slew) { + double rise_power = internal_power->gatePower(TransType::kRise, + *rise_slew, std ::nullopt); + rise_power_mw = lib_cell->convertTablePowerToMw(rise_power); + } + // fall power auto fall_slew = (*the_input_sta_vertex) ->getSlewNs(AnalysisMode::kMax, TransType::kFall); @@ -566,8 +579,8 @@ unsigned PwrCalcInternalPower::operator()(PwrGraph* the_graph) { double nom_voltage = inst_cell->get_owner_lib()->get_nom_voltage(); // add power analysis data. - auto internal_data = - std::make_unique(design_inst, MW_TO_W(inst_internal_power)); + auto internal_data = std::make_unique( + design_inst, MW_TO_W(inst_internal_power)); internal_data->set_nom_voltage(nom_voltage); addInternalPower(std::move(internal_data)); diff --git a/src/operation/iPW/source/module/ops/calc_power/PwrCalcSwitchPower.cc b/src/operation/iPW/source/module/ops/calc_power/PwrCalcSwitchPower.cc index 5e4561149..496c683a7 100644 --- a/src/operation/iPW/source/module/ops/calc_power/PwrCalcSwitchPower.cc +++ b/src/operation/iPW/source/module/ops/calc_power/PwrCalcSwitchPower.cc @@ -96,10 +96,17 @@ unsigned PwrCalcSwitchPower::operator()(PwrGraph* the_graph) { /*Calc switch power for power net arc.*/ FOREACH_NET(nl, net) { if (net->getLoads().empty()) { + LOG_INFO << "net " << net->get_name() + << " has no load, skip switch power calculation."; continue; } auto* driver_obj = net->getDriver(); + if (!driver_obj) { + LOG_INFO << "net " << net->get_name() + << " has no driver, skip switch power calculation."; + continue; + } if (driver_obj->isPort() && ((net->getLoads().size() == 1) && net->getLoads().front()->isPort())) { @@ -134,7 +141,8 @@ unsigned PwrCalcSwitchPower::operator()(PwrGraph* the_graph) { // calc swich power of the arc. // swich_power = k*toggle*Cap*(VDD^2) double arc_swich_power = c_switch_power_K * toggle * cap * vdd * vdd; - auto switch_data = std::make_unique(net, MW_TO_W(arc_swich_power)); + auto switch_data = + std::make_unique(net, MW_TO_W(arc_swich_power)); switch_data->set_nom_voltage(vdd); // add power analysis data. addSwitchPower(std::move(switch_data)); diff --git a/src/operation/iPW/source/module/ops/calc_toggle_sp/PwrCalcToggleSP.cc b/src/operation/iPW/source/module/ops/calc_toggle_sp/PwrCalcToggleSP.cc index 0d41402bf..f1f37014c 100644 --- a/src/operation/iPW/source/module/ops/calc_toggle_sp/PwrCalcToggleSP.cc +++ b/src/operation/iPW/source/module/ops/calc_toggle_sp/PwrCalcToggleSP.cc @@ -323,6 +323,12 @@ unsigned PwrCalcToggleSP::calcToggleSP( auto* output_pin = output_vertex->get_sta_vertex()->get_design_obj(); auto* liberty_port = lib_cell->get_cell_port_or_port_bus(output_pin->get_name()); + if (!liberty_port) { + LOG_ERROR << "lib cell " << lib_cell->get_cell_name() + << " has no port " << output_pin->get_name(); + continue; + } + auto* port_func = liberty_port->get_func_expr(); // FiXME, output pad not have function. diff --git a/src/operation/iPW/source/module/ops/levelize_seq_graph/CMakeLists.txt b/src/operation/iPW/source/module/ops/levelize_seq_graph/CMakeLists.txt index 833617e84..edc13df35 100644 --- a/src/operation/iPW/source/module/ops/levelize_seq_graph/CMakeLists.txt +++ b/src/operation/iPW/source/module/ops/levelize_seq_graph/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) set (CMAKE_CXX_STANDARD 20) -set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_BUILD_TYPE "Release") set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") aux_source_directory(./ SRC) diff --git a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.cc b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.cc index cad8e3176..e6c943133 100644 --- a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.cc +++ b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.cc @@ -22,12 +22,11 @@ * @date 2023-03-03 */ -#include "PwrBuildSeqGraph.hh" - #include #include #include +#include "PwrBuildSeqGraph.hh" #include "ThreadPool/ThreadPool.h" #include "ops/dump/PwrDumpSeqGraph.hh" @@ -49,11 +48,35 @@ unsigned PwrBuildSeqGraph::operator()(PwrVertex* the_vertex) { /*Lambda function to create seq graph arc.*/ auto create_seq_arc = [this](auto* seq_vertex, auto* fanout_seq_vertex, auto combine_depth) { + // macro connection need filter repeat arc. + static std::shared_mutex rw_mutex; + if (seq_vertex->isMacro() || fanout_seq_vertex->isMacro()) { + { + std::shared_lock lock(rw_mutex); + if (_macro_arcs.count(std::make_pair(seq_vertex, fanout_seq_vertex))) { + LOG_INFO_FIRST_N(10) + << "Repeat macro arc: " << seq_vertex->get_obj_name() << " -> " + << fanout_seq_vertex->get_obj_name(); + return; + } + } + + { + std::unique_lock lock(rw_mutex); + _macro_arcs.insert(std::make_pair(seq_vertex, fanout_seq_vertex)); + LOG_INFO_EVERY_N(100000) + << "macro seq arc size: " << _macro_arcs.size(); + } + } + PwrSeqArc* seq_arc = new PwrSeqArc(seq_vertex, fanout_seq_vertex); seq_arc->set_combine_depth(combine_depth); seq_vertex->addSrcArc(seq_arc); fanout_seq_vertex->addSnkArc(seq_arc); _seq_graph.addPwrSeqArc(seq_arc); + + LOG_INFO_IF_EVERY_N(_seq_graph.get_arcs().size() > 100000, 10000000) + << "build seq arc size: " << _seq_graph.get_arcs().size(); }; auto* the_sta_vertex = the_vertex->get_sta_vertex(); @@ -78,7 +101,8 @@ unsigned PwrBuildSeqGraph::operator()(PwrVertex* the_vertex) { if (seq_vertex) { the_vertex->addFanoutSeqVertex(seq_vertex, 0); // end vertex is level 0. } else { - LOG_ERROR << seq_instance->get_name() << " is not seq vertex."; + LOG_ERROR << seq_instance->get_name() + << " is not seq vertex, may be no clock."; } the_vertex->set_is_seq_visited(); @@ -189,7 +213,7 @@ unsigned PwrBuildSeqGraph::buildSeqVertexes(PwrGraph* the_graph) { } else { seq_instance = (*data_in_pwr_vertexes.begin())->getOwnInstance(); } - + // New a seq vertex for this instance. PwrSeqVertex* seq_vertex = new PwrSeqVertex( std::move(data_in_pwr_vertexes), std::move(data_out_pwr_vertexes)); diff --git a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.hh b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.hh index 4ad8c50aa..1eb66f5ca 100644 --- a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.hh +++ b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrBuildSeqGraph.hh @@ -1,16 +1,16 @@ // *************************************************************************************** // 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 +// 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: +// 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. +// 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. // *************************************************************************************** @@ -43,9 +43,14 @@ class PwrBuildSeqGraph : public PwrFunc { private: unsigned buildSeqVertexes(PwrGraph* the_graph); unsigned buildPortVertexes(PwrGraph* the_graph); - + unsigned buildSeqArcs(PwrGraph* the_graph); + std::set> + _macro_arcs; // for filter out repeat macro connection, because macro has + // multiple input and output pin, maybe built repeatedly + // macro connection. + PwrSeqGraph _seq_graph; //!< the sequential graph }; } // namespace ipower \ No newline at end of file diff --git a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrLevelizeSeqGraph.cc b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrLevelizeSeqGraph.cc index a53cac6ad..00eea4eba 100644 --- a/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrLevelizeSeqGraph.cc +++ b/src/operation/iPW/source/module/ops/levelize_seq_graph/PwrLevelizeSeqGraph.cc @@ -113,9 +113,9 @@ unsigned PwrLevelizeSeq::operator()(PwrSeqGraph* the_seq_graph) { } double memory_delta = stats.memoryDelta(); - LOG_INFO << "check pipeline loop memory usage " << memory_delta << "MB"; + LOG_INFO << "levelization memory usage " << memory_delta << "MB"; double time_delta = stats.elapsedRunTime(); - LOG_INFO << "check pipeline loop time elapsed " << time_delta << "s"; + LOG_INFO << "levelization time elapsed " << time_delta << "s"; return 1; } diff --git a/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateConst.cc b/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateConst.cc index 3dd7d3eeb..d7522edd7 100644 --- a/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateConst.cc +++ b/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateConst.cc @@ -1,16 +1,16 @@ // *************************************************************************************** // 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 +// 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: +// 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. +// 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. // *************************************************************************************** @@ -85,7 +85,10 @@ void PwrPropagateConst::setTieCellFanout(PwrSeqGraph* the_seq_graph) { pwr_vertex->addFanoutSeqVertex(seq_vertex, 1); FOREACH_SNK_PWR_ARC(pwr_vertex, snk_arc) { auto* the_src_vertex = snk_arc->get_src(); - set_fanout_vertex(seq_vertex, the_src_vertex); + if (!the_src_vertex->get_fanout_seq_vertexes().contains(seq_vertex)) { + set_fanout_vertex(seq_vertex, the_src_vertex); + } + } }; @@ -103,6 +106,8 @@ void PwrPropagateConst::setTieCellFanout(PwrSeqGraph* the_seq_graph) { } /*Find paths that have not been marked with fanout vertex.*/ if (the_src_vertex->get_fanout_seq_vertexes().empty()) { + LOG_INFO << "set tie cell fanout from " << the_src_vertex->getName() + << " data in vertex " << data_in_vertex->getName(); set_fanout_vertex(seq_vertex, the_src_vertex); } } diff --git a/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateToggleSP.cc b/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateToggleSP.cc index b17934d07..53d1c38c9 100644 --- a/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateToggleSP.cc +++ b/src/operation/iPW/source/module/ops/propagate_toggle_sp/PwrPropagateToggleSP.cc @@ -66,7 +66,7 @@ PwrToggleSPData PwrPropagateToggleSP::calcSeqDataOutToggleSP( LOG_INFO_IF(!launch_clock_domain) << "power vertex " << data_in_vertex->getName() << " not found launch clock domain."; - if (data_out_vertex->getName() == "bus/clint/_1098_:QN") { + if (data_out_vertex->getName() == "swerv_exu__30129_:QN") { LOG_INFO << "Debug"; } auto capcure_clock_domain = data_out_vertex->getOwnFastestClockDomain(); @@ -223,9 +223,16 @@ unsigned PwrPropagateToggleSP::operator()(PwrGraph* the_graph) { auto& data_out_vertexes = seq_vertex->get_seq_out_vertexes(); for (auto* data_out_vertex : data_out_vertexes) { auto* seq_data_out_net = data_out_vertex->getDesignObj()->get_net(); + // If the net is not loaded, skip this data out vertex. if (seq_data_out_net && seq_data_out_net->getLoads().empty()) { continue; } + + // If the dataout vertex is not in data path, skip this data out. + auto capcure_clock_domain = data_out_vertex->getOwnFastestClockDomain(); + if (!capcure_clock_domain) { + continue; + } // Get the data in vertex's data. auto seq_toggle_sp_data = getToggleSPData(data_in_vertex); diff --git a/src/operation/iPW/source/module/ops/read_vcd/RustVCDParserWrapper.cc b/src/operation/iPW/source/module/ops/read_vcd/RustVCDParserWrapper.cc index 76152e271..085b4e61a 100644 --- a/src/operation/iPW/source/module/ops/read_vcd/RustVCDParserWrapper.cc +++ b/src/operation/iPW/source/module/ops/read_vcd/RustVCDParserWrapper.cc @@ -46,7 +46,7 @@ unsigned RustVcdParserWrapper::buildAnnotateDB(const char* top_instance_name) { } else { found_scope = traverse_scope(root_scope); } - LOG_FATAL_IF(!found_scope) << "not found the scope" << top_instance_name; + LOG_FATAL_IF(!found_scope) << "not found the scope " << top_instance_name; _top_instance_scope = found_scope; diff --git a/src/operation/iPW/source/python-api/PythonPower.hh b/src/operation/iPW/source/python-api/PythonPower.hh index 55efa9a58..b77e3e8c1 100644 --- a/src/operation/iPW/source/python-api/PythonPower.hh +++ b/src/operation/iPW/source/python-api/PythonPower.hh @@ -92,7 +92,11 @@ build_connection_map(std::vector> clusters, std::vector build_macro_connection_map(unsigned max_hop) { auto* power_engine = ipower::PowerEngine::getOrCreatePowerEngine(); +#ifdef USE_GPU + return power_engine->buildMacroConnectionMapWithGPU(max_hop); +#else return power_engine->buildMacroConnectionMap(max_hop); +#endif } } // namespace ipower \ No newline at end of file diff --git a/src/operation/iPW/source/shell-cmd/CmdReadVcd.cc b/src/operation/iPW/source/shell-cmd/CmdReadVcd.cc index 603c9e80c..67f8acae3 100644 --- a/src/operation/iPW/source/shell-cmd/CmdReadVcd.cc +++ b/src/operation/iPW/source/shell-cmd/CmdReadVcd.cc @@ -42,7 +42,7 @@ CmdReadVcd::CmdReadVcd(const char* cmd_name) : TclCmd(cmd_name) { unsigned CmdReadVcd::check() { TclOption* file_name_option = getOptionOrArg("file_name"); - TclOption* top_instance_name_option = getOptionOrArg("top_instance_name"); + TclOption* top_instance_name_option = getOptionOrArg("-top_name"); LOG_FATAL_IF(!file_name_option); LOG_FATAL_IF(!top_instance_name_option); return 1; @@ -56,7 +56,7 @@ unsigned CmdReadVcd::exec() { TclOption* file_name_option = getOptionOrArg("file_name"); auto vcd_file = file_name_option->getStringVal(); - TclOption* top_instance_name_option = getOptionOrArg("top_instance_name"); + TclOption* top_instance_name_option = getOptionOrArg("-top_name"); auto top_instance_name = top_instance_name_option->getStringVal(); Sta* ista = Sta::getOrCreateSta(); diff --git a/src/operation/iRT/CMakeLists.txt b/src/operation/iRT/CMakeLists.txt index b795d2cde..0446dbeb3 100644 --- a/src/operation/iRT/CMakeLists.txt +++ b/src/operation/iRT/CMakeLists.txt @@ -23,10 +23,11 @@ set(CMAKE_CXX_STANDARD 20) # set(DEBUG_IRT_PIN_ACCESSOR ON) # set(DEBUG_IRT_SUPPLY_ANALYZER ON) # set(DEBUG_IRT_TOPOLOGY_GENERATOR ON) -# set(DEBUG_IRT_INITIAL_ROUTER ON) +# set(DEBUG_IRT_LAYER_ASSIGNER ON) # set(DEBUG_IRT_GLOBAL_ROUTER ON) # set(DEBUG_IRT_TRACK_ASSIGNER ON) # set(DEBUG_IRT_DETAILED_ROUTER ON) +# set(DEBUG_IRT_EARLY_ROUTER ON) ############################ debug source utility ############################ diff --git a/src/operation/iRT/README.md b/src/operation/iRT/README.md index 080f0a3b6..b7493378a 100644 --- a/src/operation/iRT/README.md +++ b/src/operation/iRT/README.md @@ -4,7 +4,7 @@ iPower-structure -布线是继布局和时钟树综合之后的重要物理实施任务,其内容是将分布在芯片核内的模块,标准单元和输入输出接口单元按逻辑关系进行互连,并为满足各种约束条件进行优化。iRT是iEDA课题组针对布线阶段设计的一款布线器,其内部集成了全局布线和详细布线。 +布线是继布局和时钟树综合之后的重要物理实施任务,其内容是将分布在芯片核内的模块,标准单元和输入输出接口单元按逻辑关系进行互连,并为满足各种约束条件进行优化。iRT是iEDA课题组针对布线阶段设计的一款布线器,其内部集成了全局布线和详细布线。 ## 软件结构 @@ -18,13 +18,13 @@ ### module:算法主要模块 -- pin_accessor: 对所有pin分配access点,在port上找到可以接入的点 +- pin_accessor: 对所有pin分配access点,在port上找到可以接入的点 -- global_router: 全局布线器,以GCell为单位,在三维网格上进行全局布线 +- global_router: 全局布线器,以GCell为单位,在三维网格上进行全局布线 -- track_assigner: wire轨道分配,建模为布线问题进行轨道分配 +- track_assigner: wire轨道分配,建模为布线问题进行轨道分配 -- detailed_router: 详细布线器,以DRC驱动的,基于三维track网格的详细布线器 +- detailed_router: 详细布线器,以DRC驱动的,基于三维track网格的详细布线器 ### solver:布线时可以使用的求解器 diff --git a/src/operation/iRT/interface/RTInterface.cpp b/src/operation/iRT/interface/RTInterface.cpp index 7cd774ccd..d3d764273 100644 --- a/src/operation/iRT/interface/RTInterface.cpp +++ b/src/operation/iRT/interface/RTInterface.cpp @@ -18,10 +18,11 @@ #include "DRCEngine.hpp" #include "DetailedRouter.hpp" +#include "EarlyRouter.hpp" #include "GDSPlotter.hpp" #include "GlobalRouter.hpp" -#include "InitialRouter.hpp" #include "LSAssigner4iEDA/ls_assigner/LSAssigner.h" +#include "LayerAssigner.hpp" #include "Monitor.hpp" #include "PinAccessor.hpp" #include "RTInterface.hpp" @@ -32,6 +33,7 @@ #include "api/TimingEngine.hh" #include "api/TimingIDBAdapter.hh" #include "feature_irt.h" +#include "feature_manager.h" #include "flute3/flute.h" #include "idm.h" #include "idrc_api.h" @@ -59,6 +61,8 @@ void RTInterface::destroyInst() #if 1 // 外部调用RT的API +#if 1 // iRT + void RTInterface::initRT(std::map config_map) { Logger::initInst(); @@ -92,25 +96,15 @@ void RTInterface::runEGR() Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); - PinAccessor::initInst(); - RTPA.access(); - PinAccessor::destroyInst(); + RTGP.init(); SupplyAnalyzer::initInst(); RTSA.analyze(); SupplyAnalyzer::destroyInst(); - TopologyGenerator::initInst(); - RTTG.generate(); - TopologyGenerator::destroyInst(); - - InitialRouter::initInst(); - RTIR.route(); - InitialRouter::destroyInst(); - - GlobalRouter::initInst(); - RTGR.route(); - GlobalRouter::destroyInst(); + EarlyRouter::initInst(); + RTER.route(); + EarlyRouter::destroyInst(); RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } @@ -120,6 +114,9 @@ void RTInterface::runRT() Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); + RTDE.init(); + RTGP.init(); + PinAccessor::initInst(); RTPA.access(); PinAccessor::destroyInst(); @@ -132,9 +129,9 @@ void RTInterface::runRT() RTTG.generate(); TopologyGenerator::destroyInst(); - InitialRouter::initInst(); - RTIR.route(); - InitialRouter::destroyInst(); + LayerAssigner::initInst(); + RTLA.route(); + LayerAssigner::destroyInst(); GlobalRouter::initInst(); RTGR.route(); @@ -182,30 +179,48 @@ void RTInterface::clearDef() idb::IdbPins* idb_pin_list = dmInst->get_idb_def_service()->get_design()->get_io_pin_list(); IdbNetList* idb_net_list = dmInst->get_idb_def_service()->get_design()->get_net_list(); + ////////////////////////////////////////// + // 删除net内所有的wire + for (idb::IdbNet* idb_net : idb_net_list->get_net_list()) { + idb_net->clear_wire_list(); + } + // 删除net内所有的wire + ////////////////////////////////////////// + ////////////////////////////////////////// // 删除net内所有的virtual for (idb::IdbNet* idb_net : idb_net_list->get_net_list()) { for (idb::IdbRegularWire* wire : idb_net->get_wire_list()->get_wire_list()) { - std::vector& segment_list = wire->get_segment_list(); - std::sort(segment_list.begin(), segment_list.end(), [](idb::IdbRegularWireSegment* a, idb::IdbRegularWireSegment* b) { - bool a_is_virtual = a->is_virtual(a->get_point_second()); - bool b_is_virtual = b->is_virtual(b->get_point_second()); - if (a_is_virtual == false && b_is_virtual == true) { - return true; + std::vector del_segment_list; + for (idb::IdbRegularWireSegment* segment : wire->get_segment_list()) { + if (segment->is_virtual(segment->get_point_second())) { + del_segment_list.push_back(segment); } - return false; - }); + } + for (idb::IdbRegularWireSegment* segment : del_segment_list) { + wire->delete_seg(segment); + } } } // 删除net内所有的virtual ////////////////////////////////////////// ////////////////////////////////////////// - // 删除net内所有的wire + // 删除net内所有的patch for (idb::IdbNet* idb_net : idb_net_list->get_net_list()) { - idb_net->clear_wire_list(); + for (idb::IdbRegularWire* wire : idb_net->get_wire_list()->get_wire_list()) { + std::vector del_segment_list; + for (idb::IdbRegularWireSegment* segment : wire->get_segment_list()) { + if (segment->is_rect()) { + del_segment_list.push_back(segment); + } + } + for (idb::IdbRegularWireSegment* segment : del_segment_list) { + wire->delete_seg(segment); + } + } } - // 删除net内所有的wire + // 删除net内所有的patch ////////////////////////////////////////// ////////////////////////////////////////// @@ -239,7 +254,7 @@ void RTInterface::clearDef() std::vector remove_pin_list; for (idb::IdbPin* io_pin : idb_pin_list->get_pin_list()) { if (io_pin->get_port_box_list().empty()) { - RTLOG.info(Loc::current(), io_pin->get_pin_name()); + RTLOG.info(Loc::current(), "del io_pin: ", io_pin->get_pin_name()); remove_pin_list.push_back(io_pin); } } @@ -252,9 +267,11 @@ void RTInterface::clearDef() #endif +#endif + #if 1 // RT调用外部的API -#if 1 // iDB +#if 1 // TopData #if 1 // input @@ -343,7 +360,7 @@ void RTInterface::wrapLayerList() routing_layer.set_min_area(idb_routing_layer->get_area()); routing_layer.set_prefer_direction(getRTDirectionByDB(idb_routing_layer->get_direction())); wrapTrackAxis(routing_layer, idb_routing_layer); - wrapRoutingSpacingTable(routing_layer, idb_routing_layer); + wrapRoutingDesignRule(routing_layer, idb_routing_layer); routing_layer_list.push_back(std::move(routing_layer)); } else if (idb_layer->is_cut()) { idb::IdbLayerCut* idb_cut_layer = dynamic_cast(idb_layer); @@ -351,7 +368,7 @@ void RTInterface::wrapLayerList() cut_layer.set_layer_idx(idb_cut_layer->get_id()); cut_layer.set_layer_order(idb_cut_layer->get_order()); cut_layer.set_layer_name(idb_cut_layer->get_name()); - wrapCutSpacingTable(cut_layer, idb_cut_layer); + wrapCutDesignRule(cut_layer, idb_cut_layer); cut_layer_list.push_back(std::move(cut_layer)); } } @@ -377,47 +394,128 @@ void RTInterface::wrapTrackAxis(RoutingLayer& routing_layer, idb::IdbLayerRoutin } } -void RTInterface::wrapRoutingSpacingTable(RoutingLayer& routing_layer, idb::IdbLayerRouting* idb_layer) +void RTInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLayerRouting* idb_layer) { - std::shared_ptr idb_spacing_table; - if (idb_layer->get_spacing_table().get()->get_parallel().get() != nullptr && idb_layer->get_spacing_table().get()->is_parallel()) { - idb_spacing_table = idb_layer->get_spacing_table()->get_parallel(); - } else if (idb_layer->get_spacing_list() != nullptr && !idb_layer->get_spacing_table().get()->is_parallel()) { - idb_spacing_table = idb_layer->get_spacing_table_from_spacing_list()->get_parallel(); - } else { - idb_spacing_table = std::make_shared(1, 1); - idb_spacing_table.get()->set_parallel_length(0, 0); - idb_spacing_table.get()->set_width(0, 0); - idb_spacing_table.get()->set_spacing(0, 0, 0); - RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " spacing table is empty!"); + // prl + { + std::shared_ptr idb_spacing_table; + if (idb_layer->get_spacing_table().get()->get_parallel().get() != nullptr && idb_layer->get_spacing_table().get()->is_parallel()) { + idb_spacing_table = idb_layer->get_spacing_table()->get_parallel(); + } else if (idb_layer->get_spacing_list() != nullptr && !idb_layer->get_spacing_table().get()->is_parallel()) { + idb_spacing_table = idb_layer->get_spacing_table_from_spacing_list()->get_parallel(); + } else { + idb_spacing_table = std::make_shared(1, 1); + idb_spacing_table.get()->set_parallel_length(0, 0); + idb_spacing_table.get()->set_width(0, 0); + idb_spacing_table.get()->set_spacing(0, 0, 0); + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " spacing table is empty!"); + } + + SpacingTable& prl_spacing_table = routing_layer.get_prl_spacing_table(); + std::vector& width_list = prl_spacing_table.get_width_list(); + std::vector& parallel_length_list = prl_spacing_table.get_parallel_length_list(); + GridMap& width_parallel_length_map = prl_spacing_table.get_width_parallel_length_map(); + + width_list = idb_spacing_table->get_width_list(); + parallel_length_list = idb_spacing_table->get_parallel_length_list(); + width_parallel_length_map.init(width_list.size(), parallel_length_list.size()); + for (int32_t x = 0; x < width_parallel_length_map.get_x_size(); x++) { + for (int32_t y = 0; y < width_parallel_length_map.get_y_size(); y++) { + width_parallel_length_map[x][y] = idb_spacing_table->get_spacing_table()[x][y]; + } + } } - - SpacingTable& spacing_table = routing_layer.get_spacing_table(); - std::vector& width_list = spacing_table.get_width_list(); - std::vector& parallel_length_list = spacing_table.get_parallel_length_list(); - GridMap& width_parallel_length_map = spacing_table.get_width_parallel_length_map(); - - width_list = idb_spacing_table->get_width_list(); - parallel_length_list = idb_spacing_table->get_parallel_length_list(); - width_parallel_length_map.init(width_list.size(), parallel_length_list.size()); - for (int32_t x = 0; x < width_parallel_length_map.get_x_size(); x++) { - for (int32_t y = 0; y < width_parallel_length_map.get_y_size(); y++) { - width_parallel_length_map[x][y] = idb_spacing_table->get_spacing_table()[x][y]; + // eol + { + idb::IdbLayerRouting* idb_routing_layer = dynamic_cast(idb_layer); + if (!idb_routing_layer->get_lef58_spacing_eol_list().empty()) { + int32_t eol_spacing = idb_routing_layer->get_lef58_spacing_eol_list().front().get()->get_eol_space(); + int32_t eol_within = idb_routing_layer->get_lef58_spacing_eol_list().front().get()->get_eol_within().value(); + for (std::shared_ptr& idb_rule_eol : idb_routing_layer->get_lef58_spacing_eol_list()) { + if (idb_rule_eol.get()->get_eol_space() < eol_spacing) { + eol_spacing = idb_rule_eol.get()->get_eol_space(); + eol_within = idb_rule_eol.get()->get_eol_within().value(); + } + } + routing_layer.set_eol_spacing(eol_spacing); + routing_layer.set_eol_within(eol_within); + } else { + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " eol_spacing is empty!"); + routing_layer.set_eol_spacing(0); + routing_layer.set_eol_within(0); } } } -void RTInterface::wrapCutSpacingTable(CutLayer& cut_layer, idb::IdbLayerCut* idb_layer) +void RTInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_layer) { - if (!idb_layer->get_spacings().empty()) { - cut_layer.set_spacing(idb_layer->get_spacings().front()->get_spacing()); - } else if (!idb_layer->get_lef58_spacing_table().empty()) { - idb::cutlayer::Lef58SpacingTable::CutSpacing cut_spacing - = idb_layer->get_lef58_spacing_table().front()->get_cutclass().get_cut_spacing(0, 0); - cut_layer.set_spacing(std::max(cut_spacing.get_cut_spacing1().value(), cut_spacing.get_cut_spacing2().value())); - } else { - cut_layer.set_spacing(0); - RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " spacing table is empty!"); + // curr layer + { + if (!idb_layer->get_spacings().empty()) { + cut_layer.set_curr_prl_spacing(0); + cut_layer.set_curr_x_spacing(idb_layer->get_spacings().front()->get_spacing()); + cut_layer.set_curr_y_spacing(idb_layer->get_spacings().front()->get_spacing()); + } else if (!idb_layer->get_lef58_spacing_table().empty()) { + idb::cutlayer::Lef58SpacingTable* spacing_table = nullptr; + for (std::shared_ptr& spacing_table_ptr : idb_layer->get_lef58_spacing_table()) { + if (spacing_table_ptr.get()->get_second_layer().has_value()) { + continue; + } + spacing_table = spacing_table_ptr.get(); + } + if (spacing_table != nullptr) { + idb::cutlayer::Lef58SpacingTable::CutSpacing cut_spacing = spacing_table->get_cutclass().get_cut_spacing(0, 0); + + int32_t curr_prl_spacing = -1 * spacing_table->get_prl().value().get_prl(); + int32_t curr_x_spacing = cut_spacing.get_cut_spacing1().value(); + int32_t curr_y_spacing = cut_spacing.get_cut_spacing2().value(); + cut_layer.set_curr_prl_spacing(curr_prl_spacing); + cut_layer.set_curr_x_spacing(curr_x_spacing); + cut_layer.set_curr_y_spacing(curr_y_spacing); + } else { + cut_layer.set_curr_prl_spacing(0); + cut_layer.set_curr_x_spacing(0); + cut_layer.set_curr_y_spacing(0); + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " curr layer spacing is empty!"); + } + } else { + cut_layer.set_curr_prl_spacing(0); + cut_layer.set_curr_x_spacing(0); + cut_layer.set_curr_y_spacing(0); + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " curr layer spacing is empty!"); + } + } + // below layer + { + if (!idb_layer->get_lef58_spacing_table().empty()) { + idb::cutlayer::Lef58SpacingTable* spacing_table = nullptr; + for (std::shared_ptr& spacing_table_ptr : idb_layer->get_lef58_spacing_table()) { + if (!spacing_table_ptr.get()->get_second_layer().has_value()) { + continue; + } + spacing_table = spacing_table_ptr.get(); + } + if (spacing_table != nullptr) { + idb::cutlayer::Lef58SpacingTable::CutSpacing cut_spacing = spacing_table->get_cutclass().get_cut_spacing(0, 0); + + int32_t below_prl_spacing = -1 * spacing_table->get_prl().value().get_prl(); + int32_t below_x_spacing = cut_spacing.get_cut_spacing1().value(); + int32_t below_y_spacing = cut_spacing.get_cut_spacing2().value(); + cut_layer.set_below_prl_spacing(below_prl_spacing); + cut_layer.set_below_x_spacing(below_x_spacing); + cut_layer.set_below_y_spacing(below_y_spacing); + } else { + cut_layer.set_below_prl_spacing(0); + cut_layer.set_below_x_spacing(0); + cut_layer.set_below_y_spacing(0); + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " below layer spacing is empty!"); + } + } else { + cut_layer.set_below_prl_spacing(0); + cut_layer.set_below_x_spacing(0); + cut_layer.set_below_y_spacing(0); + RTLOG.warn(Loc::current(), "The idb layer ", idb_layer->get_name(), " below layer spacing is empty!"); + } } } @@ -452,8 +550,7 @@ void RTInterface::wrapLayerViaMasterList() layer_via_master_list.resize(idb_routing_layers.size()); std::vector& idb_via_list = idb_via_list_lib->get_via_list(); - for (size_t i = 0; i < idb_via_list.size(); i++) { - idb::IdbVia* idb_via = idb_via_list[i]; + for (idb::IdbVia* idb_via : idb_via_list) { if (idb_via == nullptr) { RTLOG.error(Loc::current(), "The via is empty!"); } @@ -501,13 +598,16 @@ void RTInterface::wrapObstacleList() std::vector& routing_obstacle_list = RTDM.getDatabase().get_routing_obstacle_list(); std::vector& cut_obstacle_list = RTDM.getDatabase().get_cut_obstacle_list(); std::vector& instance_list = dmInst->get_idb_def_service()->get_design()->get_instance_list()->get_instance_list(); - idb::IdbSpecialNetList* idb_special_net_list = dmInst->get_idb_def_service()->get_design()->get_special_net_list(); + std::vector& idb_special_net_list + = dmInst->get_idb_def_service()->get_design()->get_special_net_list()->get_net_list(); + std::vector& idb_io_pin_list = dmInst->get_idb_def_service()->get_design()->get_io_pin_list()->get_pin_list(); int32_t total_routing_obstacle_num = 0; int32_t total_cut_obstacle_num = 0; { // instance for (idb::IdbInstance* instance : instance_list) { + // instance obs for (idb::IdbLayerShape* obs_box : instance->get_obs_box_list()) { if (obs_box->get_layer()->is_routing()) { total_routing_obstacle_num += obs_box->get_rect_list().size(); @@ -515,6 +615,7 @@ void RTInterface::wrapObstacleList() total_cut_obstacle_num += obs_box->get_rect_list().size(); } } + // instance pin without net for (idb::IdbPin* idb_pin : instance->get_pin_list()->get_pin_list()) { if (idb_pin->get_net() != nullptr) { continue; @@ -526,10 +627,14 @@ void RTInterface::wrapObstacleList() total_cut_obstacle_num += port_box->get_rect_list().size(); } } + for (idb::IdbVia* idb_via : idb_pin->get_via_list()) { + total_routing_obstacle_num += 2; + total_cut_obstacle_num += idb_via->get_cut_layer_shape().get_rect_list().size(); + } } } // special net - for (idb::IdbSpecialNet* idb_net : idb_special_net_list->get_net_list()) { + for (idb::IdbSpecialNet* idb_net : idb_special_net_list) { for (idb::IdbSpecialWire* idb_wire : idb_net->get_wire_list()->get_wire_list()) { for (idb::IdbSpecialWireSegment* idb_segment : idb_wire->get_segment_list()) { if (idb_segment->is_via()) { @@ -542,6 +647,19 @@ void RTInterface::wrapObstacleList() } } } + // io pin + for (idb::IdbPin* idb_io_pin : idb_io_pin_list) { + if (idb_io_pin->get_net() != nullptr) { + continue; + } + for (idb::IdbLayerShape* port_box : idb_io_pin->get_port_box_list()) { + if (port_box->get_layer()->is_routing()) { + total_routing_obstacle_num += port_box->get_rect_list().size(); + } else if (port_box->get_layer()->is_cut()) { + total_cut_obstacle_num += port_box->get_rect_list().size(); + } + } + } } routing_obstacle_list.reserve(total_routing_obstacle_num); cut_obstacle_list.reserve(total_cut_obstacle_num); @@ -580,10 +698,38 @@ void RTInterface::wrapObstacleList() } } } + for (idb::IdbVia* idb_via : idb_pin->get_via_list()) { + { + idb::IdbLayerShape idb_shape_top = idb_via->get_top_layer_shape(); + idb::IdbRect idb_box_top = idb_shape_top.get_bounding_box(); + Obstacle obstacle; + obstacle.set_real_ll(idb_box_top.get_low_x(), idb_box_top.get_low_y()); + obstacle.set_real_ur(idb_box_top.get_high_x(), idb_box_top.get_high_y()); + obstacle.set_layer_idx(idb_shape_top.get_layer()->get_id()); + routing_obstacle_list.push_back(std::move(obstacle)); + } + { + idb::IdbLayerShape idb_shape_bottom = idb_via->get_bottom_layer_shape(); + idb::IdbRect idb_box_bottom = idb_shape_bottom.get_bounding_box(); + Obstacle obstacle; + obstacle.set_real_ll(idb_box_bottom.get_low_x(), idb_box_bottom.get_low_y()); + obstacle.set_real_ur(idb_box_bottom.get_high_x(), idb_box_bottom.get_high_y()); + obstacle.set_layer_idx(idb_shape_bottom.get_layer()->get_id()); + routing_obstacle_list.push_back(std::move(obstacle)); + } + idb::IdbLayerShape idb_shape_cut = idb_via->get_cut_layer_shape(); + for (idb::IdbRect* idb_rect : idb_shape_cut.get_rect_list()) { + Obstacle obstacle; + obstacle.set_real_ll(idb_rect->get_low_x(), idb_rect->get_low_y()); + obstacle.set_real_ur(idb_rect->get_high_x(), idb_rect->get_high_y()); + obstacle.set_layer_idx(idb_shape_cut.get_layer()->get_id()); + cut_obstacle_list.push_back(std::move(obstacle)); + } + } } } // special net - for (idb::IdbSpecialNet* idb_net : idb_special_net_list->get_net_list()) { + for (idb::IdbSpecialNet* idb_net : idb_special_net_list) { for (idb::IdbSpecialWire* idb_wire : idb_net->get_wire_list()->get_wire_list()) { for (idb::IdbSpecialWireSegment* idb_segment : idb_wire->get_segment_list()) { if (idb_segment->is_via()) { @@ -617,6 +763,25 @@ void RTInterface::wrapObstacleList() } } } + // io pin + for (idb::IdbPin* idb_io_pin : idb_io_pin_list) { + if (idb_io_pin->get_net() != nullptr) { + continue; + } + for (idb::IdbLayerShape* port_box : idb_io_pin->get_port_box_list()) { + for (idb::IdbRect* rect : port_box->get_rect_list()) { + Obstacle obstacle; + obstacle.set_real_ll(rect->get_low_x(), rect->get_low_y()); + obstacle.set_real_ur(rect->get_high_x(), rect->get_high_y()); + obstacle.set_layer_idx(port_box->get_layer()->get_id()); + if (port_box->get_layer()->is_routing()) { + routing_obstacle_list.push_back(std::move(obstacle)); + } else if (port_box->get_layer()->is_cut()) { + cut_obstacle_list.push_back(std::move(obstacle)); + } + } + } + } } RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } @@ -674,8 +839,8 @@ bool RTInterface::isSkipping(idb::IdbNet* idb_net) } pin_num++; } - for (auto* io_pin : idb_net->get_io_pins()->get_pin_list()) { - if (io_pin->get_term()->get_port_number() <= 0) { + for (idb::IdbPin* idb_pin : idb_net->get_io_pins()->get_pin_list()) { + if (idb_pin->get_term()->get_port_number() <= 0) { continue; } pin_num++; @@ -701,13 +866,13 @@ void RTInterface::wrapPinList(Net& net, idb::IdbNet* idb_net) wrapPinShapeList(pin, idb_pin); pin_list.push_back(std::move(pin)); } - for (auto* io_pin : idb_net->get_io_pins()->get_pin_list()) { - if (io_pin->get_term()->get_port_number() <= 0) { + for (idb::IdbPin* idb_pin : idb_net->get_io_pins()->get_pin_list()) { + if (idb_pin->get_term()->get_port_number() <= 0) { continue; } Pin pin; - pin.set_pin_name(io_pin->get_pin_name()); - wrapPinShapeList(pin, io_pin); + pin.set_pin_name(idb_pin->get_pin_name()); + wrapPinShapeList(pin, idb_pin); pin_list.push_back(std::move(pin)); } } @@ -730,6 +895,34 @@ void RTInterface::wrapPinShapeList(Pin& pin, idb::IdbPin* idb_pin) } } } + for (idb::IdbVia* idb_via : idb_pin->get_via_list()) { + { + idb::IdbLayerShape idb_shape_top = idb_via->get_top_layer_shape(); + idb::IdbRect idb_box_top = idb_shape_top.get_bounding_box(); + EXTLayerRect pin_shape; + pin_shape.set_real_ll(idb_box_top.get_low_x(), idb_box_top.get_low_y()); + pin_shape.set_real_ur(idb_box_top.get_high_x(), idb_box_top.get_high_y()); + pin_shape.set_layer_idx(idb_shape_top.get_layer()->get_id()); + routing_shape_list.push_back(std::move(pin_shape)); + } + { + idb::IdbLayerShape idb_shape_bottom = idb_via->get_bottom_layer_shape(); + idb::IdbRect idb_box_bottom = idb_shape_bottom.get_bounding_box(); + EXTLayerRect pin_shape; + pin_shape.set_real_ll(idb_box_bottom.get_low_x(), idb_box_bottom.get_low_y()); + pin_shape.set_real_ur(idb_box_bottom.get_high_x(), idb_box_bottom.get_high_y()); + pin_shape.set_layer_idx(idb_shape_bottom.get_layer()->get_id()); + routing_shape_list.push_back(std::move(pin_shape)); + } + idb::IdbLayerShape idb_shape_cut = idb_via->get_cut_layer_shape(); + for (idb::IdbRect* idb_rect : idb_shape_cut.get_rect_list()) { + EXTLayerRect pin_shape; + pin_shape.set_real_ll(idb_rect->get_low_x(), idb_rect->get_low_y()); + pin_shape.set_real_ur(idb_rect->get_high_x(), idb_rect->get_high_y()); + pin_shape.set_layer_idx(idb_shape_cut.get_layer()->get_id()); + cut_shape_list.push_back(std::move(pin_shape)); + } + } } void RTInterface::wrapDrivenPin(Net& net, idb::IdbNet* idb_net) @@ -783,6 +976,7 @@ void RTInterface::output() outputTrackGrid(); outputGCellGrid(); outputNetList(); + outputSummary(); } void RTInterface::outputTrackGrid() @@ -885,6 +1079,9 @@ void RTInterface::outputNetList() if (idb_net_list == nullptr) { RTLOG.error(Loc::current(), "The idb net list is empty!"); } + for (idb::IdbNet* idb_net : idb_net_list->get_net_list()) { + idb_net->clear_wire_list(); + } for (auto& [net_idx, idb_segment_list] : net_idb_segment_map) { std::string net_name = net_list[net_idx].get_net_name(); idb::IdbNet* idb_net = idb_net_list->find_net(net_name); @@ -911,6 +1108,139 @@ void RTInterface::outputNetList() } } +void RTInterface::outputSummary() +{ + ieda_feature::RTSummary& top_rt_summary = featureInst->get_summary()->get_summary_irt(); + + Summary& rt_summary = RTDM.getDatabase().get_summary(); + + // pa_summary + { + top_rt_summary.pa_summary.routing_access_point_num_map = rt_summary.pa_summary.routing_access_point_num_map; + for (auto& [type, access_point_num] : rt_summary.pa_summary.type_access_point_num_map) { + top_rt_summary.pa_summary.type_access_point_num_map[GetAccessPointTypeName()(type)] = access_point_num; + } + top_rt_summary.pa_summary.total_access_point_num = rt_summary.pa_summary.total_access_point_num; + } + // sa_summary + { + top_rt_summary.sa_summary.routing_supply_map = rt_summary.sa_summary.routing_supply_map; + top_rt_summary.sa_summary.total_supply = rt_summary.sa_summary.total_supply; + } + // tg_summary + { + top_rt_summary.tg_summary.total_demand = rt_summary.tg_summary.total_demand; + top_rt_summary.tg_summary.total_overflow = rt_summary.tg_summary.total_overflow; + top_rt_summary.tg_summary.total_wire_length = rt_summary.tg_summary.total_wire_length; + for (auto& [clock_name, timing_map] : rt_summary.tg_summary.clock_timing) { + ieda_feature::ClockTiming clock_timing; + clock_timing.clock_name = clock_name; + clock_timing.setup_tns = timing_map["TNS"]; + clock_timing.setup_wns = timing_map["WNS"]; + clock_timing.suggest_freq = timing_map["Freq(MHz)"]; + top_rt_summary.tg_summary.clocks_timing.push_back(clock_timing); + } + top_rt_summary.tg_summary.power_info + = {rt_summary.tg_summary.power_map["static_power"], rt_summary.tg_summary.power_map["dynamic_power"]}; + } + // la_summary + { + top_rt_summary.la_summary.routing_demand_map = rt_summary.la_summary.routing_demand_map; + top_rt_summary.la_summary.total_demand = rt_summary.la_summary.total_demand; + top_rt_summary.la_summary.routing_overflow_map = rt_summary.la_summary.routing_overflow_map; + top_rt_summary.la_summary.total_overflow = rt_summary.la_summary.total_overflow; + top_rt_summary.la_summary.routing_wire_length_map = rt_summary.la_summary.routing_wire_length_map; + top_rt_summary.la_summary.total_wire_length = rt_summary.la_summary.total_wire_length; + top_rt_summary.la_summary.cut_via_num_map = rt_summary.la_summary.cut_via_num_map; + top_rt_summary.la_summary.total_via_num = rt_summary.la_summary.total_via_num; + for (auto& [clock_name, timing_map] : rt_summary.la_summary.clock_timing) { + ieda_feature::ClockTiming clock_timing; + clock_timing.clock_name = clock_name; + clock_timing.setup_tns = timing_map["TNS"]; + clock_timing.setup_wns = timing_map["WNS"]; + clock_timing.suggest_freq = timing_map["Freq(MHz)"]; + top_rt_summary.la_summary.clocks_timing.push_back(clock_timing); + } + top_rt_summary.la_summary.power_info + = {rt_summary.la_summary.power_map["static_power"], rt_summary.la_summary.power_map["dynamic_power"]}; + } + // gr_summary + { + for (auto& [iter, gr_summary] : rt_summary.iter_gr_summary_map) { + ieda_feature::GRSummary& top_gr_summary = top_rt_summary.iter_gr_summary_map[iter]; + top_gr_summary.routing_demand_map = gr_summary.routing_demand_map; + top_gr_summary.total_demand = gr_summary.total_demand; + top_gr_summary.routing_overflow_map = gr_summary.routing_overflow_map; + top_gr_summary.total_overflow = gr_summary.total_overflow; + top_gr_summary.routing_wire_length_map = gr_summary.routing_wire_length_map; + top_gr_summary.total_wire_length = gr_summary.total_wire_length; + top_gr_summary.cut_via_num_map = gr_summary.cut_via_num_map; + top_gr_summary.total_via_num = gr_summary.total_via_num; + for (auto& [clock_name, timing_map] : gr_summary.clock_timing) { + ieda_feature::ClockTiming clock_timing; + clock_timing.clock_name = clock_name; + clock_timing.setup_tns = timing_map["TNS"]; + clock_timing.setup_wns = timing_map["WNS"]; + clock_timing.suggest_freq = timing_map["Freq(MHz)"]; + top_gr_summary.clocks_timing.push_back(clock_timing); + } + top_gr_summary.power_info = {gr_summary.power_map["static_power"], gr_summary.power_map["dynamic_power"]}; + } + } + // ta_summary + { + top_rt_summary.ta_summary.routing_wire_length_map = rt_summary.ta_summary.routing_wire_length_map; + top_rt_summary.ta_summary.total_wire_length = rt_summary.ta_summary.total_wire_length; + top_rt_summary.ta_summary.routing_violation_num_map = rt_summary.ta_summary.routing_violation_num_map; + top_rt_summary.ta_summary.total_violation_num = rt_summary.ta_summary.total_violation_num; + } + // dr_summary + { + for (auto& [iter, dr_summary] : rt_summary.iter_dr_summary_map) { + ieda_feature::DRSummary& top_dr_summary = top_rt_summary.iter_dr_summary_map[iter]; + top_dr_summary.routing_wire_length_map = dr_summary.routing_wire_length_map; + top_dr_summary.total_wire_length = dr_summary.total_wire_length; + top_dr_summary.cut_via_num_map = dr_summary.cut_via_num_map; + top_dr_summary.total_via_num = dr_summary.total_via_num; + top_dr_summary.routing_patch_num_map = dr_summary.routing_patch_num_map; + top_dr_summary.total_patch_num = dr_summary.total_patch_num; + top_dr_summary.routing_violation_num_map = dr_summary.routing_violation_num_map; + top_dr_summary.total_violation_num = dr_summary.total_violation_num; + + for (auto& [clock_name, timing_map] : dr_summary.clock_timing) { + ieda_feature::ClockTiming clock_timing; + clock_timing.clock_name = clock_name; + clock_timing.setup_tns = timing_map["TNS"]; + clock_timing.setup_wns = timing_map["WNS"]; + clock_timing.suggest_freq = timing_map["Freq(MHz)"]; + top_dr_summary.clocks_timing.push_back(clock_timing); + } + top_dr_summary.power_info = {dr_summary.power_map["static_power"], dr_summary.power_map["dynamic_power"]}; + } + } + // er_summary + { + top_rt_summary.er_summary.routing_demand_map = rt_summary.er_summary.routing_demand_map; + top_rt_summary.er_summary.total_demand = rt_summary.er_summary.total_demand; + top_rt_summary.er_summary.routing_overflow_map = rt_summary.er_summary.routing_overflow_map; + top_rt_summary.er_summary.total_overflow = rt_summary.er_summary.total_overflow; + top_rt_summary.er_summary.routing_wire_length_map = rt_summary.er_summary.routing_wire_length_map; + top_rt_summary.er_summary.total_wire_length = rt_summary.er_summary.total_wire_length; + top_rt_summary.er_summary.cut_via_num_map = rt_summary.er_summary.cut_via_num_map; + top_rt_summary.er_summary.total_via_num = rt_summary.er_summary.total_via_num; + for (auto& [clock_name, timing_map] : rt_summary.er_summary.clock_timing) { + ieda_feature::ClockTiming clock_timing; + clock_timing.clock_name = clock_name; + clock_timing.setup_tns = timing_map["TNS"]; + clock_timing.setup_wns = timing_map["WNS"]; + clock_timing.suggest_freq = timing_map["Freq(MHz)"]; + top_rt_summary.er_summary.clocks_timing.push_back(clock_timing); + } + top_rt_summary.er_summary.power_info + = {rt_summary.er_summary.power_map["static_power"], rt_summary.er_summary.power_map["dynamic_power"]}; + } +} + #endif #if 1 // 获得IdbSegment @@ -1152,7 +1482,7 @@ void RTInterface::updateTimingAndPower(std::vectorget_real_ll_x(); - ls_shape.ll_y = fixed_rect->get_real_ll_y(); - ls_shape.ur_x = fixed_rect->get_real_ur_x(); - ls_shape.ur_y = fixed_rect->get_real_ur_y(); - ls_panel.hard_shape_list.push_back(ls_shape); - } - } - break; + for (auto& [net_idx, fixed_rect_set] : ta_panel.get_net_fixed_rect_map()) { + for (auto& fixed_rect : fixed_rect_set) { + lsa::LSShape ls_shape; + ls_shape.net_id = net_idx; + ls_shape.ll_x = fixed_rect->get_real_ll_x(); + ls_shape.ll_y = fixed_rect->get_real_ll_y(); + ls_shape.ur_x = fixed_rect->get_real_ur_x(); + ls_shape.ur_y = fixed_rect->get_real_ur_y(); + ls_panel.hard_shape_list.push_back(ls_shape); + } + } + for (auto& [net_idx, rect_list] : ta_panel.get_net_access_result_map()) { + for (auto& rect : rect_list) { + lsa::LSShape ls_shape; + ls_shape.net_id = net_idx; + ls_shape.ll_x = rect.get_ll_x(); + ls_shape.ll_y = rect.get_ll_y(); + ls_shape.ur_x = rect.get_ur_x(); + ls_shape.ur_y = rect.get_ur_y(); + ls_panel.hard_shape_list.push_back(ls_shape); + } + } + for (auto& [net_idx, patch_set] : ta_panel.get_net_access_patch_map()) { + for (auto& patch : patch_set) { + lsa::LSShape ls_shape; + ls_shape.net_id = net_idx; + ls_shape.ll_x = patch->get_real_ll_x(); + ls_shape.ll_y = patch->get_real_ll_y(); + ls_shape.ur_x = patch->get_real_ur_x(); + ls_shape.ur_y = patch->get_real_ur_y(); + ls_panel.hard_shape_list.push_back(ls_shape); + } + } + for (auto& [net_idx, rect_list] : ta_panel.get_net_detailed_result_map()) { + for (auto& rect : rect_list) { + lsa::LSShape ls_shape; + ls_shape.net_id = net_idx; + ls_shape.ll_x = rect.get_ll_x(); + ls_shape.ll_y = rect.get_ll_y(); + ls_shape.ur_x = rect.get_ur_x(); + ls_shape.ur_y = rect.get_ur_y(); + ls_panel.hard_shape_list.push_back(ls_shape); } } } diff --git a/src/operation/iRT/interface/RTInterface.hpp b/src/operation/iRT/interface/RTInterface.hpp index 5a6c3c18a..c7718c5a3 100644 --- a/src/operation/iRT/interface/RTInterface.hpp +++ b/src/operation/iRT/interface/RTInterface.hpp @@ -54,6 +54,7 @@ class PlanarCoord; namespace ieda_feature { class RTSummary; +class FeatureManager; } // namespace ieda_feature #endif @@ -69,6 +70,8 @@ class RTInterface static void destroyInst(); #if 1 // 外部调用RT的API + +#if 1 // iRT void initRT(std::map config_map); void runEGR(); void runRT(); @@ -76,9 +79,11 @@ class RTInterface void clearDef(); #endif +#endif + #if 1 // RT调用外部的API -#if 1 // iDB +#if 1 // TopData #if 1 // input void input(std::map& config_map); @@ -90,8 +95,8 @@ class RTInterface void wrapRow(); void wrapLayerList(); void wrapTrackAxis(RoutingLayer& routing_layer, idb::IdbLayerRouting* idb_layer); - void wrapRoutingSpacingTable(RoutingLayer& routing_layer, idb::IdbLayerRouting* idb_layer); - void wrapCutSpacingTable(CutLayer& cut_layer, idb::IdbLayerCut* idb_layer); + void wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLayerRouting* idb_layer); + void wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_layer); void wrapLayerInfo(); void wrapLayerViaMasterList(); void wrapObstacleList(); @@ -109,6 +114,7 @@ class RTInterface void outputTrackGrid(); void outputGCellGrid(); void outputNetList(); + void outputSummary(); #endif #if 1 // 获得IdbSegment @@ -136,10 +142,6 @@ class RTInterface std::map>& clock_timing, std::map& power); #endif -#if 1 // ieda_feature - ieda_feature::RTSummary outputSummary(); -#endif - #if 1 // flute void initFlute(); void destroyFlute(); diff --git a/src/operation/iRT/source/data_manager/DataManager.cpp b/src/operation/iRT/source/data_manager/DataManager.cpp index cea12c119..3288e4fdb 100644 --- a/src/operation/iRT/source/data_manager/DataManager.cpp +++ b/src/operation/iRT/source/data_manager/DataManager.cpp @@ -103,7 +103,7 @@ void DataManager::updateFixedRectToGCellMap(ChangeType change_type, int32_t net_ } } if (change_type == ChangeType::kDel) { - // 由于在database内的obstacle_list引用过来,所以不需要delete,也不能delete + // 由于在database内的obstacle_list引用过来,所以不需要delete,也不能delete } } @@ -121,7 +121,7 @@ void DataManager::updateAccessNetPointToGCellMap(ChangeType change_type, int32_t } } if (change_type == ChangeType::kDel) { - // 由于在pin内的access_point_list引用过来,所以不需要delete,也不能delete + // 由于在pin内的access_point_list引用过来,所以不需要delete,也不能delete } } @@ -573,14 +573,16 @@ void DataManager::buildConfig() _config.sa_temp_directory_path = _config.temp_directory_path + "supply_analyzer/"; // ******** TopologyGenerator ******** // _config.tg_temp_directory_path = _config.temp_directory_path + "topology_generator/"; - // ********** InitialRouter ********** // - _config.ir_temp_directory_path = _config.temp_directory_path + "initial_router/"; + // ********** LayerAssigner ********** // + _config.la_temp_directory_path = _config.temp_directory_path + "layer_assigner/"; // ********** GlobalRouter ********** // _config.gr_temp_directory_path = _config.temp_directory_path + "global_router/"; // ********** TrackAssigner ********** // _config.ta_temp_directory_path = _config.temp_directory_path + "track_assigner/"; // ********** DetailedRouter ********** // _config.dr_temp_directory_path = _config.temp_directory_path + "detailed_router/"; + // ********** EarlyRouter ********** // + _config.er_temp_directory_path = _config.temp_directory_path + "early_router/"; ///////////////////////////////////////////// // ********** RT ********** // RTUTIL.removeDir(_config.temp_directory_path); @@ -596,14 +598,16 @@ void DataManager::buildConfig() RTUTIL.createDir(_config.sa_temp_directory_path); // ********* TopologyGenerator ********* // RTUTIL.createDir(_config.tg_temp_directory_path); - // ********** InitialRouter ********** // - RTUTIL.createDir(_config.ir_temp_directory_path); + // ********** LayerAssigner ********** // + RTUTIL.createDir(_config.la_temp_directory_path); // ********** GlobalRouter ********** // RTUTIL.createDir(_config.gr_temp_directory_path); // ********** TrackAssigner ********** // RTUTIL.createDir(_config.ta_temp_directory_path); // ********** DetailedRouter ********** // RTUTIL.createDir(_config.dr_temp_directory_path); + // ********** EarlyRouter ********** // + RTUTIL.createDir(_config.er_temp_directory_path); ///////////////////////////////////////////// RTLOG.openLogFileStream(_config.log_file_path); } @@ -643,10 +647,15 @@ void DataManager::transLayerList() } void DataManager::makeLayerList() +{ + makeRoutingLayerList(); + makeCutLayerList(); +} + +void DataManager::makeRoutingLayerList() { Die& die = _database.get_die(); std::vector& routing_layer_list = _database.get_routing_layer_list(); - std::vector& cut_layer_list = _database.get_cut_layer_list(); auto getFrequentNum = [](const std::vector& num_list) { if (num_list.empty()) { @@ -668,17 +677,11 @@ void DataManager::makeLayerList() }; int32_t step_length; { - std::vector width_list; - std::vector routing_spacing_list; - std::vector cut_spacing_list; + std::vector pitch_list; for (RoutingLayer& routing_layer : routing_layer_list) { - width_list.push_back(routing_layer.get_min_width()); - routing_spacing_list.push_back(routing_layer.getMinSpacing(PlanarRect(0, 0, 0, 0))); + pitch_list.push_back(routing_layer.getPreferTrackGridList().front().get_step_length()); } - for (CutLayer& cut_layer : cut_layer_list) { - cut_spacing_list.push_back(cut_layer.getMinSpacing()); - } - step_length = getFrequentNum(width_list) + std::min(getFrequentNum(routing_spacing_list), getFrequentNum(cut_spacing_list)); + step_length = getFrequentNum(pitch_list); } auto getScaleGrid = [](int32_t real_ll_scale, int32_t real_ur_scale, int32_t step_length) { int32_t start_line = real_ll_scale + step_length; @@ -709,6 +712,22 @@ void DataManager::makeLayerList() } } +void DataManager::makeCutLayerList() +{ + std::vector& cut_layer_list = _database.get_cut_layer_list(); + + for (size_t i = 1; i < cut_layer_list.size(); i++) { + CutLayer& pre_cut_layer = cut_layer_list[i - 1]; + CutLayer& curr_cut_layer = cut_layer_list[i]; + pre_cut_layer.set_above_prl_spacing(curr_cut_layer.get_below_prl_spacing()); + pre_cut_layer.set_above_x_spacing(curr_cut_layer.get_below_x_spacing()); + pre_cut_layer.set_above_y_spacing(curr_cut_layer.get_below_y_spacing()); + } + cut_layer_list.back().set_above_prl_spacing(0); + cut_layer_list.back().set_above_x_spacing(0); + cut_layer_list.back().set_above_y_spacing(0); +} + void DataManager::checkLayerList() { std::vector& routing_layer_list = _database.get_routing_layer_list(); @@ -720,7 +739,6 @@ void DataManager::checkLayerList() if (cut_layer_list.empty()) { RTLOG.error(Loc::current(), "The cut_layer_list is empty!"); } - for (RoutingLayer& routing_layer : routing_layer_list) { std::string& layer_name = routing_layer.get_layer_name(); if (routing_layer.get_prefer_direction() == Direction::kNone) { @@ -738,27 +756,48 @@ void DataManager::checkLayerList() "' is wrong!"); } } - SpacingTable& spacing_table = routing_layer.get_spacing_table(); - if (spacing_table.get_width_list().empty()) { - RTLOG.error(Loc::current(), "The layer '", layer_name, "' spacing width list is empty!"); + SpacingTable& prl_spacing_table = routing_layer.get_prl_spacing_table(); + if (prl_spacing_table.get_width_list().empty()) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' spacing width_list is empty!"); } - for (int32_t width : spacing_table.get_width_list()) { - if (width < 0) { - RTLOG.error(Loc::current(), "The layer '", layer_name, "' width < 0!"); - } + if (prl_spacing_table.get_parallel_length_list().empty()) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' spacing parallel_length_list is empty!"); } - for (int32_t parallel_length : spacing_table.get_parallel_length_list()) { - if (parallel_length < 0) { - RTLOG.error(Loc::current(), "The layer '", layer_name, "' parallel_length < 0!"); - } + if (routing_layer.get_eol_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' eol_spacing == -1!"); } - GridMap& width_parallel_length_map = spacing_table.get_width_parallel_length_map(); - for (int32_t width_idx = 0; width_idx < width_parallel_length_map.get_x_size(); width_idx++) { - for (int32_t parallel_length_idx = 0; parallel_length_idx < width_parallel_length_map.get_y_size(); parallel_length_idx++) { - if (width_parallel_length_map[width_idx][parallel_length_idx] < 0) { - RTLOG.error(Loc::current(), "The layer '", layer_name, "' spacing < 0!"); - } - } + if (routing_layer.get_eol_within() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' eol_within == -1!"); + } + } + for (CutLayer& cut_layer : cut_layer_list) { + std::string& layer_name = cut_layer.get_layer_name(); + if (cut_layer.get_curr_prl_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' curr_prl_spacing == -1!"); + } + if (cut_layer.get_curr_x_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' curr_x_spacing == -1!"); + } + if (cut_layer.get_curr_y_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' curr_y_spacing == -1!"); + } + if (cut_layer.get_above_prl_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' above_prl_spacing == -1!"); + } + if (cut_layer.get_above_x_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' above_x_spacing == -1!"); + } + if (cut_layer.get_above_y_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' above_y_spacing == -1!"); + } + if (cut_layer.get_below_prl_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' below_prl_spacing == -1!"); + } + if (cut_layer.get_below_x_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' below_x_spacing == -1!"); + } + if (cut_layer.get_below_y_spacing() == -1) { + RTLOG.error(Loc::current(), "The layer '", layer_name, "' below_y_spacing == -1!"); } } } @@ -899,7 +938,7 @@ std::vector DataManager::makeGCellGridList(Direction direction) int32_t die_start_scale = (direction == Direction::kVertical ? die.get_real_ll_x() : die.get_real_ll_y()); int32_t die_end_scale = (direction == Direction::kVertical ? die.get_real_ur_x() : die.get_real_ur_y()); int32_t row_mid_scale = (direction == Direction::kVertical ? row.get_start_x() : row.get_start_y()); - // 为了防止与track重合,减去一个recommended_pitch的一半 + // 为了防止与track重合,减去一个recommended_pitch的一半 row_mid_scale -= (getOnlyPitch() / 2); int32_t step_length = row.get_height(); @@ -922,36 +961,7 @@ std::vector DataManager::makeGCellGridList(Direction direction) } } gcell_scale_list.erase(std::unique(gcell_scale_list.begin(), gcell_scale_list.end()), gcell_scale_list.end()); - return makeGCellGridList(gcell_scale_list); -} - -std::vector DataManager::makeGCellGridList(std::vector& gcell_scale_list) -{ - std::vector gcell_grid_list; - - for (size_t i = 1; i < gcell_scale_list.size(); i++) { - int32_t pre_scale = gcell_scale_list[i - 1]; - int32_t curr_scale = gcell_scale_list[i]; - - ScaleGrid gcell_grid; - gcell_grid.set_start_line(pre_scale); - gcell_grid.set_step_length(curr_scale - pre_scale); - gcell_grid.set_step_num(1); - gcell_grid.set_end_line(curr_scale); - gcell_grid_list.push_back(gcell_grid); - } - // merge - RTUTIL.merge(gcell_grid_list, [](ScaleGrid& sentry, ScaleGrid& soldier) { - if (sentry.get_step_length() != soldier.get_step_length()) { - return false; - } - sentry.set_start_line(std::min(sentry.get_start_line(), soldier.get_start_line())); - sentry.set_step_num(sentry.get_step_num() + 1); - sentry.set_end_line(std::max(sentry.get_end_line(), soldier.get_end_line())); - return true; - }); - - return gcell_grid_list; + return RTUTIL.makeScaleGridList(gcell_scale_list); } void DataManager::checkGCellAxis() @@ -1376,10 +1386,10 @@ void DataManager::printConfig() RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "TopologyGenerator"); RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "tg_temp_directory_path"); RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(3), _config.tg_temp_directory_path); - // ********** InitialRouter ********** // - RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "InitialRouter"); - RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "ir_temp_directory_path"); - RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(3), _config.ir_temp_directory_path); + // ********** LayerAssigner ********** // + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "LayerAssigner"); + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "la_temp_directory_path"); + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(3), _config.la_temp_directory_path); // ********** GlobalRouter ********** // RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "GlobalRouter"); RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "gr_temp_directory_path"); @@ -1392,6 +1402,10 @@ void DataManager::printConfig() RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "DetailedRouter"); RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "dr_temp_directory_path"); RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(3), _config.dr_temp_directory_path); + // ********** EarlyRouter ********** // + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(1), "EarlyRouter"); + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(2), "er_temp_directory_path"); + RTLOG.info(Loc::current(), RTUTIL.getSpaceByTabNum(3), _config.er_temp_directory_path); ///////////////////////////////////////////// } diff --git a/src/operation/iRT/source/data_manager/DataManager.hpp b/src/operation/iRT/source/data_manager/DataManager.hpp index 4692b0945..757b5183f 100644 --- a/src/operation/iRT/source/data_manager/DataManager.hpp +++ b/src/operation/iRT/source/data_manager/DataManager.hpp @@ -23,7 +23,6 @@ #include "Monitor.hpp" #include "NetShape.hpp" #include "SortStatus.hpp" -#include "Summary.hpp" namespace irt { @@ -71,14 +70,12 @@ class DataManager Config& getConfig() { return _config; } Database& getDatabase() { return _database; } - Summary& getSummary() { return _summary; } private: static DataManager* _dm_instance; - // config & database & summary + // config & database Config _config; Database _database; - Summary _summary; DataManager() = default; DataManager(const DataManager& other) = delete; @@ -93,6 +90,8 @@ class DataManager void buildLayerList(); void transLayerList(); void makeLayerList(); + void makeRoutingLayerList(); + void makeCutLayerList(); void checkLayerList(); void buildLayerInfo(); void buildLayerViaMasterList(); @@ -102,7 +101,6 @@ class DataManager void buildGCellAxis(); void makeGCellAxis(); std::vector makeGCellGridList(Direction direction); - std::vector makeGCellGridList(std::vector& gcell_scale_list); void checkGCellAxis(); void buildDie(); void makeDie(); diff --git a/src/operation/iRT/source/data_manager/advance/AccessPointType.hpp b/src/operation/iRT/source/data_manager/advance/AccessPointType.hpp index e45d000ac..38d90cec1 100644 --- a/src/operation/iRT/source/data_manager/advance/AccessPointType.hpp +++ b/src/operation/iRT/source/data_manager/advance/AccessPointType.hpp @@ -24,7 +24,7 @@ enum class AccessPointType { kNone, kTrackGrid, - kOnShape + kNoAccess }; struct GetAccessPointTypeName @@ -36,12 +36,12 @@ struct GetAccessPointTypeName case AccessPointType::kNone: access_point_name = "none"; break; + case AccessPointType::kNoAccess: + access_point_name = "no_access"; + break; case AccessPointType::kTrackGrid: access_point_name = "track_grid"; break; - case AccessPointType::kOnShape: - access_point_name = "on_shape"; - break; default: RTLOG.error(Loc::current(), "Unrecognized type!"); break; diff --git a/src/operation/iRT/source/data_manager/advance/Config.hpp b/src/operation/iRT/source/data_manager/advance/Config.hpp index 0a38d0270..9d0824a0d 100644 --- a/src/operation/iRT/source/data_manager/advance/Config.hpp +++ b/src/operation/iRT/source/data_manager/advance/Config.hpp @@ -49,14 +49,16 @@ class Config std::string sa_temp_directory_path; // building // ******** TopologyGenerator ******** // std::string tg_temp_directory_path; // building - // ********** InitialRouter ********** // - std::string ir_temp_directory_path; // building + // ********** LayerAssigner ********** // + std::string la_temp_directory_path; // building // ********** GlobalRouter ********** // std::string gr_temp_directory_path; // building // ********** TrackAssigner ********** // std::string ta_temp_directory_path; // building // ********** DetailedRouter ********** // std::string dr_temp_directory_path; // building + // ********** EarlyRouter ********** // + std::string er_temp_directory_path; // building ///////////////////////////////////////////// }; diff --git a/src/operation/iRT/source/data_manager/advance/CutLayer.hpp b/src/operation/iRT/source/data_manager/advance/CutLayer.hpp index 5c92d92cf..6ff17d542 100644 --- a/src/operation/iRT/source/data_manager/advance/CutLayer.hpp +++ b/src/operation/iRT/source/data_manager/advance/CutLayer.hpp @@ -30,20 +30,45 @@ class CutLayer int32_t get_layer_idx() const { return _layer_idx; } int32_t get_layer_order() const { return _layer_order; } std::string& get_layer_name() { return _layer_name; } - int32_t get_spacing() const { return _spacing; } + int32_t get_curr_prl_spacing() const { return _curr_prl_spacing; } + int32_t get_curr_x_spacing() const { return _curr_x_spacing; } + int32_t get_curr_y_spacing() const { return _curr_y_spacing; } + int32_t get_above_prl_spacing() const { return _above_prl_spacing; } + int32_t get_above_x_spacing() const { return _above_x_spacing; } + int32_t get_above_y_spacing() const { return _above_y_spacing; } + int32_t get_below_prl_spacing() const { return _below_prl_spacing; } + int32_t get_below_x_spacing() const { return _below_x_spacing; } + int32_t get_below_y_spacing() const { return _below_y_spacing; } // setter void set_layer_idx(const int32_t layer_idx) { _layer_idx = layer_idx; } void set_layer_order(const int32_t layer_order) { _layer_order = layer_order; } void set_layer_name(const std::string& layer_name) { _layer_name = layer_name; } - void set_spacing(const int32_t spacing) { _spacing = spacing; } + void set_curr_prl_spacing(const int32_t curr_prl_spacing) { _curr_prl_spacing = curr_prl_spacing; } + void set_curr_x_spacing(const int32_t curr_x_spacing) { _curr_x_spacing = curr_x_spacing; } + void set_curr_y_spacing(const int32_t curr_y_spacing) { _curr_y_spacing = curr_y_spacing; } + void set_above_prl_spacing(const int32_t above_prl_spacing) { _above_prl_spacing = above_prl_spacing; } + void set_above_x_spacing(const int32_t above_x_spacing) { _above_x_spacing = above_x_spacing; } + void set_above_y_spacing(const int32_t above_y_spacing) { _above_y_spacing = above_y_spacing; } + void set_below_prl_spacing(const int32_t below_prl_spacing) { _below_prl_spacing = below_prl_spacing; } + void set_below_x_spacing(const int32_t below_x_spacing) { _below_x_spacing = below_x_spacing; } + void set_below_y_spacing(const int32_t below_y_spacing) { _below_y_spacing = below_y_spacing; } // function - int32_t getMinSpacing() { return _spacing; } - private: int32_t _layer_idx = -1; int32_t _layer_order = -1; std::string _layer_name; - int32_t _spacing = -1; + // curr + int32_t _curr_prl_spacing = -1; + int32_t _curr_x_spacing = -1; + int32_t _curr_y_spacing = -1; + // above + int32_t _above_prl_spacing = -1; + int32_t _above_x_spacing = -1; + int32_t _above_y_spacing = -1; + // below + int32_t _below_prl_spacing = -1; + int32_t _below_x_spacing = -1; + int32_t _below_y_spacing = -1; }; } // namespace irt diff --git a/src/operation/iRT/source/data_manager/advance/Database.hpp b/src/operation/iRT/source/data_manager/advance/Database.hpp index f6cd302a7..6f611c90f 100644 --- a/src/operation/iRT/source/data_manager/advance/Database.hpp +++ b/src/operation/iRT/source/data_manager/advance/Database.hpp @@ -25,6 +25,7 @@ #include "RTHeader.hpp" #include "RoutingLayer.hpp" #include "Row.hpp" +#include "Summary.hpp" #include "Utility.hpp" #include "ViaMaster.hpp" @@ -58,6 +59,7 @@ class Database std::vector& get_net_list() { return _net_list; } GridMap& get_gcell_map() { return _gcell_map; } int32_t get_detection_distance() const { return _detection_distance; } + Summary& get_summary() { return _summary; } // setter void set_design_name(const std::string& design_name) { _design_name = design_name; } void set_lef_file_path_list(const std::vector& lef_file_path_list) { _lef_file_path_list = lef_file_path_list; } @@ -89,6 +91,7 @@ class Database std::vector _net_list; GridMap _gcell_map; int32_t _detection_distance = -1; + Summary _summary; }; } // namespace irt diff --git a/src/operation/iRT/source/data_manager/advance/GCell.hpp b/src/operation/iRT/source/data_manager/advance/GCell.hpp index 79b59015a..5db6828cf 100644 --- a/src/operation/iRT/source/data_manager/advance/GCell.hpp +++ b/src/operation/iRT/source/data_manager/advance/GCell.hpp @@ -77,7 +77,7 @@ class GCell : public PlanarRect // function private: - // obstacle & pin_shape 如果是routing则true,cut则false + // obstacle & pin_shape 如果是routing则true,cut则false std::map>>> _type_layer_net_fixed_rect_map; // access point 只有routing层有 std::map> _net_access_point_map; diff --git a/src/operation/iRT/source/data_manager/advance/RoutingLayer.hpp b/src/operation/iRT/source/data_manager/advance/RoutingLayer.hpp index dfd352cbe..7a798027b 100644 --- a/src/operation/iRT/source/data_manager/advance/RoutingLayer.hpp +++ b/src/operation/iRT/source/data_manager/advance/RoutingLayer.hpp @@ -38,7 +38,9 @@ class RoutingLayer int32_t get_min_area() const { return _min_area; } Direction& get_prefer_direction() { return _prefer_direction; } ScaleAxis& get_track_axis() { return _track_axis; } - SpacingTable& get_spacing_table() { return _spacing_table; } + SpacingTable& get_prl_spacing_table() { return _prl_spacing_table; } + int32_t get_eol_spacing() const { return _eol_spacing; } + int32_t get_eol_within() const { return _eol_within; } // setter void set_layer_idx(const int32_t layer_idx) { _layer_idx = layer_idx; } void set_layer_order(const int32_t layer_order) { _layer_order = layer_order; } @@ -47,18 +49,19 @@ class RoutingLayer void set_min_area(const int32_t min_area) { _min_area = min_area; } void set_prefer_direction(const Direction& prefer_direction) { _prefer_direction = prefer_direction; } void set_track_axis(const ScaleAxis& track_axis) { _track_axis = track_axis; } - void set_spacing_table(const SpacingTable& spacing_table) { _spacing_table = spacing_table; } - + void set_prl_spacing_table(const SpacingTable& prl_spacing_table) { _prl_spacing_table = prl_spacing_table; } + void set_eol_spacing(const int32_t eol_spacing) { _eol_spacing = eol_spacing; } + void set_eol_within(const int32_t eol_within) { _eol_within = eol_within; } // function bool isPreferH() const { return _prefer_direction == Direction::kHorizontal; } std::vector& getXTrackGridList() { return _track_axis.get_x_grid_list(); } std::vector& getYTrackGridList() { return _track_axis.get_y_grid_list(); } std::vector& getPreferTrackGridList() { return isPreferH() ? getYTrackGridList() : getXTrackGridList(); } std::vector& getNonPreferTrackGridList() { return isPreferH() ? getXTrackGridList() : getYTrackGridList(); } - int32_t getMinSpacing(const PlanarRect& rect) + int32_t getPRLSpacing(const PlanarRect& rect) { - std::vector& width_list = _spacing_table.get_width_list(); - GridMap& width_parallel_length_map = _spacing_table.get_width_parallel_length_map(); + std::vector& width_list = _prl_spacing_table.get_width_list(); + GridMap& width_parallel_length_map = _prl_spacing_table.get_width_parallel_length_map(); for (size_t i = 0; (i + 1) < width_list.size(); i++) { if (width_list[i] <= rect.getWidth() && rect.getWidth() < width_list[i + 1]) { @@ -67,16 +70,6 @@ class RoutingLayer } return width_parallel_length_map.back().front(); } - std::vector getPreferOrientationList() - { - std::vector orientation_list; - if (_prefer_direction == Direction::kHorizontal) { - orientation_list = {Orientation::kEast, Orientation::kWest}; - } else { - orientation_list = {Orientation::kSouth, Orientation::kNorth}; - } - return orientation_list; - } private: int32_t _layer_idx = -1; @@ -86,7 +79,11 @@ class RoutingLayer int32_t _min_area = 0; Direction _prefer_direction = Direction::kNone; ScaleAxis _track_axis; - SpacingTable _spacing_table; + // prl + SpacingTable _prl_spacing_table; + // eol + int32_t _eol_spacing = -1; + int32_t _eol_within = -1; }; } // namespace irt diff --git a/src/operation/iRT/source/data_manager/advance/Summary.hpp b/src/operation/iRT/source/data_manager/advance/Summary.hpp index 7b107bc24..3306ec870 100644 --- a/src/operation/iRT/source/data_manager/advance/Summary.hpp +++ b/src/operation/iRT/source/data_manager/advance/Summary.hpp @@ -28,6 +28,8 @@ class PASummary std::map routing_access_point_num_map; std::map type_access_point_num_map; int32_t total_access_point_num = 0; + std::map routing_violation_num_map; + int32_t total_violation_num = 0; }; class SASummary @@ -51,11 +53,11 @@ class TGSummary std::map power_map; }; -class IRSummary +class LASummary { public: - IRSummary() = default; - ~IRSummary() = default; + LASummary() = default; + ~LASummary() = default; std::map routing_demand_map; int32_t total_demand = 0; std::map routing_overflow_map; @@ -113,6 +115,23 @@ class DRSummary std::map power_map; }; +class ERSummary +{ + public: + ERSummary() = default; + ~ERSummary() = default; + std::map routing_demand_map; + int32_t total_demand = 0; + std::map routing_overflow_map; + int32_t total_overflow = 0; + std::map routing_wire_length_map; + double total_wire_length = 0; + std::map cut_via_num_map; + int32_t total_via_num = 0; + std::map> clock_timing; + std::map power_map; +}; + class Summary { public: @@ -121,10 +140,11 @@ class Summary PASummary pa_summary; SASummary sa_summary; TGSummary tg_summary; - IRSummary ir_summary; + LASummary la_summary; std::map iter_gr_summary_map; TASummary ta_summary; std::map iter_dr_summary_map; + ERSummary er_summary; }; } // namespace irt diff --git a/src/operation/iRT/source/data_manager/advance/ViaMaster.hpp b/src/operation/iRT/source/data_manager/advance/ViaMaster.hpp index 733a303a9..798e87714 100644 --- a/src/operation/iRT/source/data_manager/advance/ViaMaster.hpp +++ b/src/operation/iRT/source/data_manager/advance/ViaMaster.hpp @@ -136,7 +136,7 @@ struct CmpViaMaster } // 对称升序(对称值越小越对称) if (sort_status == SortStatus::kEqual) { - // via_master的ll为负数,ur为正数 + // via_master的ll为负数,ur为正数 int32_t a_above_enclosure_symmetry = std::abs(a.get_above_enclosure().get_ll_x() + a.get_above_enclosure().get_ur_x()); int32_t b_above_enclosure_symmetry = std::abs(b.get_above_enclosure().get_ll_x() + b.get_above_enclosure().get_ur_x()); int32_t a_below_enclosure_symmetry = std::abs(a.get_below_enclosure().get_ll_x() + a.get_below_enclosure().get_ur_x()); diff --git a/src/operation/iRT/source/data_manager/advance/Violation.hpp b/src/operation/iRT/source/data_manager/advance/Violation.hpp index 71e53ab49..69ac926c6 100644 --- a/src/operation/iRT/source/data_manager/advance/Violation.hpp +++ b/src/operation/iRT/source/data_manager/advance/Violation.hpp @@ -18,6 +18,7 @@ #include "EXTLayerRect.hpp" #include "RTHeader.hpp" +#include "SortStatus.hpp" #include "ViolationType.hpp" namespace irt { @@ -30,13 +31,18 @@ class Violation // getter ViolationType get_violation_type() const { return _violation_type; } EXTLayerRect& get_violation_shape() { return _violation_shape; } - bool get_is_routing() { return _is_routing; } + bool get_is_routing() const { return _is_routing; } std::set& get_violation_net_set() { return _violation_net_set; } + int32_t get_required_size() const { return _required_size; } + // const getter + const EXTLayerRect& get_violation_shape() const { return _violation_shape; } + const std::set& get_violation_net_set() const { return _violation_net_set; } // setter void set_violation_type(const ViolationType& violation_type) { _violation_type = violation_type; } void set_violation_shape(const EXTLayerRect& violation_shape) { _violation_shape = violation_shape; } void set_is_routing(const bool is_routing) { _is_routing = is_routing; } void set_violation_net_set(const std::set& violation_net_set) { _violation_net_set = violation_net_set; } + void set_required_size(const int32_t required_size) { _required_size = required_size; } // function private: @@ -44,6 +50,109 @@ class Violation EXTLayerRect _violation_shape; bool _is_routing = true; std::set _violation_net_set; + int32_t _required_size = 0; +}; + +struct CmpViolation +{ + bool operator()(const Violation& a, const Violation& b) const + { + SortStatus sort_status = SortStatus::kEqual; + // 类型升序 + if (sort_status == SortStatus::kEqual) { + ViolationType a_violation_type = a.get_violation_type(); + ViolationType b_violation_type = b.get_violation_type(); + if (a_violation_type < b_violation_type) { + sort_status = SortStatus::kTrue; + } else if (a_violation_type > b_violation_type) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + // real_rect比较 + if (sort_status == SortStatus::kEqual) { + const PlanarRect& a_real_rect = a.get_violation_shape().get_real_rect(); + const PlanarRect& b_real_rect = b.get_violation_shape().get_real_rect(); + if (a_real_rect != b_real_rect) { + if (CmpPlanarRectByXASC()(a_real_rect, b_real_rect)) { + sort_status = SortStatus::kTrue; + } else { + sort_status = SortStatus::kFalse; + } + } else { + sort_status = SortStatus::kEqual; + } + } + // grid_rect比较 + if (sort_status == SortStatus::kEqual) { + const PlanarRect& a_grid_rect = a.get_violation_shape().get_grid_rect(); + const PlanarRect& b_grid_rect = b.get_violation_shape().get_grid_rect(); + if (a_grid_rect != b_grid_rect) { + if (CmpPlanarRectByXASC()(a_grid_rect, b_grid_rect)) { + sort_status = SortStatus::kTrue; + } else { + sort_status = SortStatus::kFalse; + } + } else { + sort_status = SortStatus::kEqual; + } + } + // layer_idx升序 + if (sort_status == SortStatus::kEqual) { + int32_t a_layer_idx = a.get_violation_shape().get_layer_idx(); + int32_t b_layer_idx = b.get_violation_shape().get_layer_idx(); + if (a_layer_idx < b_layer_idx) { + sort_status = SortStatus::kTrue; + } else if (a_layer_idx > b_layer_idx) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + // is_routing升序 + if (sort_status == SortStatus::kEqual) { + bool a_is_routing = a.get_is_routing(); + bool b_is_routing = b.get_is_routing(); + if (a_is_routing < b_is_routing) { + sort_status = SortStatus::kTrue; + } else if (a_is_routing > b_is_routing) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + // violation_net_set升序 + if (sort_status == SortStatus::kEqual) { + const std::set& a_violation_net_set = a.get_violation_net_set(); + const std::set& b_violation_net_set = b.get_violation_net_set(); + if (a_violation_net_set < b_violation_net_set) { + sort_status = SortStatus::kTrue; + } else if (a_violation_net_set > b_violation_net_set) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + // required_size升序 + if (sort_status == SortStatus::kEqual) { + int32_t a_required_size = a.get_required_size(); + int32_t b_required_size = b.get_required_size(); + if (a_required_size < b_required_size) { + sort_status = SortStatus::kTrue; + } else if (a_required_size > b_required_size) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + if (sort_status == SortStatus::kTrue) { + return true; + } else if (sort_status == SortStatus::kFalse) { + return false; + } + return false; + } }; } // namespace irt diff --git a/src/operation/iRT/source/data_manager/advance/ViolationType.hpp b/src/operation/iRT/source/data_manager/advance/ViolationType.hpp index b3367d935..7f3701056 100644 --- a/src/operation/iRT/source/data_manager/advance/ViolationType.hpp +++ b/src/operation/iRT/source/data_manager/advance/ViolationType.hpp @@ -23,6 +23,7 @@ namespace irt { enum class ViolationType { kNone, + kAdjacentCutSpacing, kCornerFillSpacing, kCutEOLSpacing, kCutShort, @@ -32,6 +33,7 @@ enum class ViolationType kEnclosureEdge, kEnclosureParallel, kFloatingPatch, + kJogToJogSpacing, kMaxViaStack, kMetalShort, kMinHole, @@ -56,6 +58,9 @@ struct GetViolationTypeName case ViolationType::kNone: violation_rule_name = "none"; break; + case ViolationType::kAdjacentCutSpacing: + violation_rule_name = "adjacent_cut_spacing"; + break; case ViolationType::kCornerFillSpacing: violation_rule_name = "corner_fill_spacing"; break; @@ -83,6 +88,9 @@ struct GetViolationTypeName case ViolationType::kFloatingPatch: violation_rule_name = "floating_patch"; break; + case ViolationType::kJogToJogSpacing: + violation_rule_name = "jog_to_jog_spacing"; + break; case ViolationType::kMaxViaStack: violation_rule_name = "max_via_stack"; break; @@ -135,7 +143,11 @@ struct GetViolationTypeByName ViolationType operator()(const std::string& violation_rule_name) const { ViolationType violation_rule; - if (violation_rule_name == "corner_fill_spacing") { + if (violation_rule_name == "adjacent_cut_spacing") { + violation_rule = ViolationType::kAdjacentCutSpacing; + } else if (violation_rule_name == "corner_fill_spacing") { + violation_rule = ViolationType::kCornerFillSpacing; + } else if (violation_rule_name == "corner_fill_spacing") { violation_rule = ViolationType::kCornerFillSpacing; } else if (violation_rule_name == "cut_eol_spacing") { violation_rule = ViolationType::kCutEOLSpacing; @@ -153,6 +165,8 @@ struct GetViolationTypeByName violation_rule = ViolationType::kEnclosureParallel; } else if (violation_rule_name == "floating_patch") { violation_rule = ViolationType::kFloatingPatch; + } else if (violation_rule_name == "jog_to_jog_spacing") { + violation_rule = ViolationType::kJogToJogSpacing; } else if (violation_rule_name == "max_via_stack") { violation_rule = ViolationType::kMaxViaStack; } else if (violation_rule_name == "metal_short") { diff --git a/src/operation/iRT/source/module/CMakeLists.txt b/src/operation/iRT/source/module/CMakeLists.txt index f56a88182..d63d91504 100644 --- a/src/operation/iRT/source/module/CMakeLists.txt +++ b/src/operation/iRT/source/module/CMakeLists.txt @@ -3,10 +3,11 @@ add_subdirectory(${IRT_MODULE}/gds_plotter) add_subdirectory(${IRT_MODULE}/pin_accessor) add_subdirectory(${IRT_MODULE}/supply_analyzer) add_subdirectory(${IRT_MODULE}/topology_generator) +add_subdirectory(${IRT_MODULE}/layer_assigner) add_subdirectory(${IRT_MODULE}/global_router) -add_subdirectory(${IRT_MODULE}/initial_router) add_subdirectory(${IRT_MODULE}/track_assigner) add_subdirectory(${IRT_MODULE}/detailed_router) +add_subdirectory(${IRT_MODULE}/early_router) add_library(irt_module INTERFACE) @@ -17,8 +18,9 @@ target_link_libraries(irt_module irt_pin_accessor irt_supply_analyzer irt_topology_generator - irt_initial_router + irt_layer_assigner irt_global_router irt_track_assigner irt_detailed_router + irt_early_router ) diff --git a/src/operation/iRT/source/module/detailed_router/DetailedRouter.cpp b/src/operation/iRT/source/module/detailed_router/DetailedRouter.cpp index fb2096b73..92de5e78b 100644 --- a/src/operation/iRT/source/module/detailed_router/DetailedRouter.cpp +++ b/src/operation/iRT/source/module/detailed_router/DetailedRouter.cpp @@ -61,9 +61,7 @@ void DetailedRouter::route() Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); DRModel dr_model = initDRModel(); - // debugPlotDRModel(dr_model, "before"); iterativeDRModel(dr_model); - // debugPlotDRModel(dr_model, "after"); RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } @@ -104,27 +102,45 @@ DRNet DetailedRouter::convertToDRNet(Net& net) void DetailedRouter::iterativeDRModel(DRModel& dr_model) { - int32_t cost_unit = 8; + int32_t cost_unit = RTDM.getOnlyPitch(); + double prefer_wire_unit = 1; + double non_prefer_wire_unit = 2.5; + double via_unit = cost_unit; + double fixed_rect_unit = 4 * non_prefer_wire_unit * cost_unit; + double routed_rect_unit = 2 * via_unit; + double violation_unit = 4 * non_prefer_wire_unit * cost_unit; /** * prefer_wire_unit, non_prefer_wire_unit, via_unit, size, offset, fixed_rect_unit, routed_rect_unit, violation_unit, initial_rip_up, * max_routed_times */ std::vector dr_parameter_list; - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, 0, 4 * cost_unit, 1 * cost_unit, 1 * cost_unit, true, 4); - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, -3, 8 * cost_unit, 2 * cost_unit, 2 * cost_unit, false, 4); - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, -6, 16 * cost_unit, 4 * cost_unit, 4 * cost_unit, false, 4); - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, 0, 32 * cost_unit, 8 * cost_unit, 8 * cost_unit, false, 4); - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, -3, 64 * cost_unit, 16 * cost_unit, 16 * cost_unit, false, 4); - dr_parameter_list.emplace_back(1, 2.5, RTDM.getOnlyPitch(), 9, -6, 128 * cost_unit, 32 * cost_unit, 32 * cost_unit, false, 4); + // clang-format off + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 0, fixed_rect_unit, routed_rect_unit, violation_unit, true, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 1, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 2, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 3, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 4, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 0, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 1, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 2, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 3, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + dr_parameter_list.emplace_back(prefer_wire_unit, non_prefer_wire_unit, via_unit, 5, 4, fixed_rect_unit, routed_rect_unit, violation_unit, false, 3); + // clang-format on for (size_t i = 0, iter = 1; i < dr_parameter_list.size(); i++, iter++) { Monitor iter_monitor; RTLOG.info(Loc::current(), "***** Begin iteration ", iter, "/", dr_parameter_list.size(), "(", RTUTIL.getPercentage(iter, dr_parameter_list.size()), ") *****"); + // debugPlotDRModel(dr_model, "before"); setDRParameter(dr_model, iter, dr_parameter_list[i]); initDRBoxMap(dr_model); buildBoxSchedule(dr_model); + splitNetResult(dr_model); + // debugPlotDRModel(dr_model, "middle"); routeDRBoxMap(dr_model); uploadNetResult(dr_model); + uploadViolation(dr_model); + updateBestResult(dr_model); + // debugPlotDRModel(dr_model, "after"); updateSummary(dr_model); printSummary(dr_model); outputNetCSV(dr_model); @@ -135,6 +151,7 @@ void DetailedRouter::iterativeDRModel(DRModel& dr_model) break; } } + selectBestResult(dr_model); } void DetailedRouter::setDRParameter(DRModel& dr_model, int32_t iter, DRParameter& dr_parameter) @@ -205,7 +222,7 @@ void DetailedRouter::buildBoxSchedule(DRModel& dr_model) { GridMap& dr_box_map = dr_model.get_dr_box_map(); - int32_t range = 2; + int32_t range = 3; std::vector> dr_box_id_list_list; for (int32_t start_x = 0; start_x < range; start_x++) { @@ -222,6 +239,83 @@ void DetailedRouter::buildBoxSchedule(DRModel& dr_model) dr_model.set_dr_box_id_list_list(dr_box_id_list_list); } +void DetailedRouter::splitNetResult(DRModel& dr_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + Die& die = RTDM.getDatabase().get_die(); + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { + std::vector*> del_segment_list; + std::vector> new_segment_list; + for (Segment* segment : segment_set) { + LayerCoord& first_coord = segment->get_first(); + LayerCoord& second_coord = segment->get_second(); + if (first_coord.get_layer_idx() != second_coord.get_layer_idx()) { + continue; + } + if (RTUTIL.isHorizontal(first_coord, second_coord)) { + int32_t first_x = first_coord.get_x(); + int32_t second_x = second_coord.get_x(); + RTUTIL.swapByASC(first_x, second_x); + std::set x_pre_set; + std::set x_mid_set; + std::set x_post_set; + RTUTIL.getTrackScaleSet(gcell_axis.get_x_grid_list(), first_x, second_x, x_pre_set, x_mid_set, x_post_set); + x_mid_set.erase(first_x); + x_mid_set.erase(second_x); + if (x_mid_set.empty()) { + continue; + } + std::vector x_scale_list; + x_scale_list.push_back(first_x); + for (int32_t x_scale : x_mid_set) { + x_scale_list.push_back(x_scale); + } + x_scale_list.push_back(second_x); + del_segment_list.push_back(segment); + for (size_t i = 1; i < x_scale_list.size(); i++) { + new_segment_list.emplace_back(LayerCoord(x_scale_list[i - 1], first_coord.get_y(), first_coord.get_layer_idx()), + LayerCoord(x_scale_list[i], first_coord.get_y(), first_coord.get_layer_idx())); + } + } else if (RTUTIL.isVertical(first_coord, second_coord)) { + int32_t first_y = first_coord.get_y(); + int32_t second_y = second_coord.get_y(); + RTUTIL.swapByASC(first_y, second_y); + std::set y_pre_set; + std::set y_mid_set; + std::set y_post_set; + RTUTIL.getTrackScaleSet(gcell_axis.get_y_grid_list(), first_y, second_y, y_pre_set, y_mid_set, y_post_set); + y_mid_set.erase(first_y); + y_mid_set.erase(second_y); + if (y_mid_set.empty()) { + continue; + } + std::vector y_scale_list; + y_scale_list.push_back(first_y); + for (int32_t y_scale : y_mid_set) { + y_scale_list.push_back(y_scale); + } + y_scale_list.push_back(second_y); + del_segment_list.push_back(segment); + for (size_t i = 1; i < y_scale_list.size(); i++) { + new_segment_list.emplace_back(LayerCoord(first_coord.get_x(), y_scale_list[i - 1], first_coord.get_layer_idx()), + LayerCoord(first_coord.get_x(), y_scale_list[i], first_coord.get_layer_idx())); + } + } + } + for (Segment* del_segment : del_segment_list) { + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kDel, net_idx, del_segment); + } + for (Segment& new_segment : new_segment_list) { + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kAdd, net_idx, new Segment(new_segment)); + } + } + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + void DetailedRouter::routeDRBoxMap(DRModel& dr_model) { Monitor monitor; @@ -250,12 +344,13 @@ void DetailedRouter::routeDRBoxMap(DRModel& dr_model) buildLayerNodeMap(dr_box); buildDRNodeNeighbor(dr_box); buildOrientNetMap(dr_box); + exemptPinShape(dr_box); // debugCheckDRBox(dr_box); // debugPlotDRBox(dr_box, -1, "before"); routeDRBox(dr_box); // debugPlotDRBox(dr_box, -1, "after"); - uploadViolation(dr_box); } + selectBestResult(dr_box); freeDRBox(dr_box); } routed_box_num += dr_box_id_list.size(); @@ -279,14 +374,25 @@ void DetailedRouter::buildAccessResult(DRBox& dr_box) void DetailedRouter::buildNetResult(DRBox& dr_box) { + PlanarRect& box_region = dr_box.get_box_rect().get_real_rect(); + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(dr_box.get_box_rect())) { for (Segment* segment : segment_set) { dr_box.get_net_detailed_result_map()[net_idx].push_back(*segment); + if (RTUTIL.isInside(box_region, segment->get_first()) && RTUTIL.isInside(box_region, segment->get_second())) { + if (RTUTIL.isInside(box_region, segment->get_first(), false) || RTUTIL.isInside(box_region, segment->get_second(), false)) { + // 线段在box_region内,但不能贴边 + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kDel, net_idx, segment); + } + } } } for (auto& [net_idx, patch_set] : RTDM.getNetDetailedPatchMap(dr_box.get_box_rect())) { for (EXTLayerRect* patch : patch_set) { dr_box.get_net_detailed_patch_map()[net_idx].push_back(*patch); + if (RTUTIL.isInside(box_region, patch->get_real_rect())) { + RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kDel, net_idx, patch); + } } } } @@ -500,7 +606,7 @@ void DetailedRouter::buildDRNodeNeighbor(DRBox& dr_box) } } } - // 对在graph边缘的,进行非track_grid上处理邻居,防止offgrid + // 对在graph边缘的,进行非track_grid上处理邻居,防止offgrid { std::vector coord_list; coord_list.push_back(dr_node_map[0][0]); @@ -575,20 +681,38 @@ void DetailedRouter::buildOrientNetMap(DRBox& dr_box) } } for (Violation& violation : dr_box.get_violation_list()) { - updateViolationToGraph(dr_box, ChangeType::kAdd, violation); + addViolationToGraph(dr_box, violation); + } +} + +void DetailedRouter::exemptPinShape(DRBox& dr_box) +{ + std::vector>& layer_node_map = dr_box.get_layer_node_map(); + for (GridMap& dr_node_map : layer_node_map) { + for (int32_t x = 0; x < dr_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < dr_node_map.get_y_size(); y++) { + DRNode& dr_node = dr_node_map[x][y]; + for (auto& [orient, net_set] : dr_node.get_orient_fixed_rect_map()) { + if (RTUTIL.exist(net_set, -1) && net_set.size() >= 2) { + net_set.erase(-1); + } + } + } + } } } void DetailedRouter::routeDRBox(DRBox& dr_box) { - std::vector dr_task_list = initTaskSchedule(dr_box); - while (!dr_task_list.empty()) { - for (DRTask* dr_task : dr_task_list) { - routeDRTask(dr_box, dr_task); - dr_task->addRoutedTimes(); + std::vector routing_task_list = initTaskSchedule(dr_box); + while (!routing_task_list.empty()) { + for (DRTask* routing_task : routing_task_list) { + routeDRTask(dr_box, routing_task); + routing_task->addRoutedTimes(); } updateViolationList(dr_box); - dr_task_list = getTaskScheduleByViolation(dr_box); + updateBestResult(dr_box); + updateTaskSchedule(dr_box, routing_task_list); } } @@ -596,15 +720,15 @@ std::vector DetailedRouter::initTaskSchedule(DRBox& dr_box) { bool initial_rip_up = dr_box.get_dr_parameter()->get_initial_rip_up(); - std::vector dr_task_list; + std::vector routing_task_list; if (initial_rip_up) { for (DRTask* dr_task : dr_box.get_dr_task_list()) { - dr_task_list.push_back(dr_task); + routing_task_list.push_back(dr_task); } } else { - dr_task_list = getTaskScheduleByViolation(dr_box); + updateTaskSchedule(dr_box, routing_task_list); } - return dr_task_list; + return routing_task_list; } void DetailedRouter::routeDRTask(DRBox& dr_box, DRTask* dr_task) @@ -617,8 +741,6 @@ void DetailedRouter::routeDRTask(DRBox& dr_box, DRTask* dr_task) resetSinglePath(dr_box); } updateTaskResult(dr_box); - patchSingleTask(dr_box); - updateTaskPatch(dr_box); resetSingleTask(dr_box); } @@ -725,7 +847,7 @@ void DetailedRouter::expandSearching(DRBox& dr_box) if (neighbor_node->isOpen() && know_cost < neighbor_node->get_known_cost()) { neighbor_node->set_known_cost(know_cost); neighbor_node->set_parent_node(path_head_node); - // 对优先队列中的值修改了,需要重新建堆 + // 对优先队列中的值修改了,需要重新建堆 std::make_heap(open_queue.begin(), open_queue.end(), CmpDRNodeCost()); } else if (neighbor_node->isNone()) { neighbor_node->set_known_cost(know_cost); @@ -782,7 +904,7 @@ void DetailedRouter::resetStartAndEnd(DRBox& dr_box) DRNode* path_head_node = dr_box.get_path_head_node(); int32_t end_node_list_idx = dr_box.get_end_node_list_idx(); - // 对于抵达的终点pin,只保留到达的node + // 对于抵达的终点pin,只保留到达的node end_node_list_list[end_node_list_idx].clear(); end_node_list_list[end_node_list_idx].push_back(path_head_node); @@ -798,7 +920,7 @@ void DetailedRouter::resetStartAndEnd(DRBox& dr_box) } } if (start_node_list_list.size() == 1) { - // 初始化时,要把start_node_list_list的pin只留一个ap点 + // 初始化时,要把start_node_list_list的pin只留一个ap点 // 后续只要将end_node_list_list的pin保留一个ap点 start_node_list_list.front().clear(); start_node_list_list.front().push_back(path_node); @@ -865,38 +987,6 @@ std::vector> DetailedRouter::getRoutingSegmentList(DRBox& dr return routing_segment_list; } -void DetailedRouter::patchSingleTask(DRBox& dr_box) -{ -} - -std::vector DetailedRouter::getPatchViolationList(DRBox& dr_box) -{ - return {}; -} - -void DetailedRouter::updateTaskPatch(DRBox& dr_box) -{ - std::vector new_routing_patch_list = getRoutingPatchList(dr_box); - - int32_t curr_net_idx = dr_box.get_curr_dr_task()->get_net_idx(); - std::vector& routing_patch_list = dr_box.get_net_detailed_patch_map()[curr_net_idx]; - - // 原结果从graph删除,由于task有对应net_idx,所以不需要在布线前进行删除也不会影响结果 - for (EXTLayerRect& routing_patch : routing_patch_list) { - updateNetResultToGraph(dr_box, ChangeType::kDel, curr_net_idx, routing_patch); - } - routing_patch_list = new_routing_patch_list; - // 新结果添加到graph - for (EXTLayerRect& routing_patch : routing_patch_list) { - updateNetResultToGraph(dr_box, ChangeType::kAdd, curr_net_idx, routing_patch); - } -} - -std::vector DetailedRouter::getRoutingPatchList(DRBox& dr_box) -{ - return dr_box.get_routing_patch_list(); -} - void DetailedRouter::resetSingleTask(DRBox& dr_box) { dr_box.set_curr_dr_task(nullptr); @@ -905,7 +995,6 @@ void DetailedRouter::resetSingleTask(DRBox& dr_box) dr_box.get_path_node_list().clear(); dr_box.get_single_task_visited_node_list().clear(); dr_box.get_routing_segment_list().clear(); - dr_box.get_routing_patch_list().clear(); } // manager open list @@ -1047,17 +1136,13 @@ double DetailedRouter::getEstimateViaCost(DRBox& dr_box, DRNode* start_node, DRN void DetailedRouter::updateViolationList(DRBox& dr_box) { - std::vector new_violation_list = getCostViolationList(dr_box); - - std::vector& violation_list = dr_box.get_violation_list(); - // 原结果从graph删除 - for (Violation& violation : violation_list) { - updateViolationToGraph(dr_box, ChangeType::kDel, violation); + dr_box.get_violation_list().clear(); + for (Violation new_violation : getCostViolationList(dr_box)) { + dr_box.get_violation_list().push_back(new_violation); } - violation_list = new_violation_list; // 新结果添加到graph - for (Violation& violation : violation_list) { - updateViolationToGraph(dr_box, ChangeType::kAdd, violation); + for (Violation& violation : dr_box.get_violation_list()) { + addViolationToGraph(dr_box, violation); } } @@ -1082,60 +1167,113 @@ std::vector DetailedRouter::getCostViolationList(DRBox& dr_box) } } } - std::map*>> net_env_result_map; + std::map*>> net_result_map; for (auto& [net_idx, segment_set] : dr_box.get_net_access_result_map()) { for (Segment* segment : segment_set) { - net_env_result_map[net_idx].push_back(segment); + net_result_map[net_idx].push_back(segment); } } - std::map> net_env_patch_map; + for (auto& [net_idx, segment_list] : dr_box.get_net_detailed_result_map()) { + for (Segment& segment : segment_list) { + net_result_map[net_idx].emplace_back(&segment); + } + } + std::map> net_patch_map; for (auto& [net_idx, patch_set] : dr_box.get_net_access_patch_map()) { for (EXTLayerRect* patch : patch_set) { - net_env_patch_map[net_idx].push_back(patch); + net_patch_map[net_idx].push_back(patch); } } - std::map>>& net_check_result_map = dr_box.get_net_detailed_result_map(); - std::map>& net_check_patch_map = dr_box.get_net_detailed_patch_map(); + for (auto& [net_idx, patch_list] : dr_box.get_net_detailed_patch_map()) { + for (EXTLayerRect& patch : patch_list) { + net_patch_map[net_idx].emplace_back(&patch); + } + } + std::set need_checked_net_set; + for (DRTask* dr_task : dr_box.get_dr_task_list()) { + need_checked_net_set.insert(dr_task->get_net_idx()); + } DETask de_task; - de_task.set_process_type_set({DEProcessType::kRoutingCost, DEProcessType::kCutCost}); + de_task.set_process_type(DEProcessType::kMultiNet); de_task.set_top_name(top_name); de_task.set_check_region(check_region); de_task.set_env_shape_list(env_shape_list); de_task.set_net_pin_shape_map(net_pin_shape_map); - de_task.set_net_env_result_map(net_env_result_map); - de_task.set_net_env_patch_map(net_env_patch_map); - de_task.set_net_check_result_map(net_check_result_map); - de_task.set_net_check_patch_map(net_check_patch_map); + de_task.set_net_result_map(net_result_map); + de_task.set_net_patch_map(net_patch_map); + de_task.set_need_checked_net_set(need_checked_net_set); return RTDE.getViolationList(de_task); } -std::vector DetailedRouter::getTaskScheduleByViolation(DRBox& dr_box) +void DetailedRouter::updateBestResult(DRBox& dr_box) +{ + std::map>>& best_net_detailed_result_map = dr_box.get_best_net_detailed_result_map(); + std::map>& best_net_detailed_patch_map = dr_box.get_best_net_detailed_patch_map(); + std::vector& best_violation_list = dr_box.get_best_violation_list(); + + int32_t curr_violation_num = static_cast(dr_box.get_violation_list().size()); + if (!best_net_detailed_result_map.empty() || !best_net_detailed_patch_map.empty()) { + if (static_cast(best_violation_list.size()) < curr_violation_num) { + return; + } + } + best_net_detailed_result_map = dr_box.get_net_detailed_result_map(); + best_net_detailed_patch_map = dr_box.get_net_detailed_patch_map(); + best_violation_list = dr_box.get_violation_list(); +} + +void DetailedRouter::updateTaskSchedule(DRBox& dr_box, std::vector& routing_task_list) { int32_t max_routed_times = dr_box.get_dr_parameter()->get_max_routed_times(); - std::set violation_net_set; + std::set visited_routing_task_set; + std::vector new_routing_task_list; for (Violation& violation : dr_box.get_violation_list()) { - for (int32_t violation_net : violation.get_violation_net_set()) { - violation_net_set.insert(violation_net); + for (DRTask* dr_task : dr_box.get_dr_task_list()) { + if (!RTUTIL.exist(violation.get_violation_net_set(), dr_task->get_net_idx())) { + continue; + } + if (dr_task->get_routed_times() < max_routed_times && !RTUTIL.exist(visited_routing_task_set, dr_task)) { + visited_routing_task_set.insert(dr_task); + new_routing_task_list.push_back(dr_task); + } + break; } } - std::vector dr_task_list; + routing_task_list = new_routing_task_list; + + std::vector new_dr_task_list; for (DRTask* dr_task : dr_box.get_dr_task_list()) { - if (!RTUTIL.exist(violation_net_set, dr_task->get_net_idx())) { - continue; + if (!RTUTIL.exist(visited_routing_task_set, dr_task)) { + new_dr_task_list.push_back(dr_task); } - if (dr_task->get_routed_times() >= max_routed_times) { - continue; - } - dr_task_list.push_back(dr_task); } - return dr_task_list; + for (DRTask* routing_task : routing_task_list) { + new_dr_task_list.push_back(routing_task); + } + dr_box.set_dr_task_list(new_dr_task_list); } -void DetailedRouter::uploadViolation(DRBox& dr_box) +void DetailedRouter::selectBestResult(DRBox& dr_box) { - for (Violation& violation : dr_box.get_violation_list()) { + updateBestResult(dr_box); + uploadBestResult(dr_box); +} + +void DetailedRouter::uploadBestResult(DRBox& dr_box) +{ + for (auto& [net_idx, segment_list] : dr_box.get_best_net_detailed_result_map()) { + for (Segment& segment : segment_list) { + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kAdd, net_idx, new Segment(segment)); + } + } + for (auto& [net_idx, patch_list] : dr_box.get_best_net_detailed_patch_map()) { + for (EXTLayerRect& patch : patch_list) { + RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kAdd, net_idx, new EXTLayerRect(patch)); + } + } + for (Violation& violation : dr_box.get_best_violation_list()) { RTDM.updateViolationToGCellMap(ChangeType::kAdd, new Violation(violation)); } } @@ -1163,57 +1301,183 @@ void DetailedRouter::uploadNetResult(DRModel& dr_model) RTLOG.info(Loc::current(), "Starting..."); Die& die = RTDM.getDatabase().get_die(); - GridMap& dr_box_map = dr_model.get_dr_box_map(); + std::vector& dr_net_list = dr_model.get_dr_net_list(); - for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { - for (Segment* segment : segment_set) { - RTDM.updateNetDetailedResultToGCellMap(ChangeType::kDel, net_idx, segment); + // detailed result + { + std::map*>> net_detailed_result_map = RTDM.getNetDetailedResultMap(die); + for (auto& [net_idx, segment_set] : net_detailed_result_map) { + std::vector> routing_segment_list; + for (Segment* segment : segment_set) { + routing_segment_list.emplace_back(segment->get_first(), segment->get_second()); + } + std::vector candidate_root_coord_list; + std::map, CmpLayerCoordByXASC> key_coord_pin_map; + std::vector& dr_pin_list = dr_net_list[net_idx].get_dr_pin_list(); + for (size_t i = 0; i < dr_pin_list.size(); i++) { + LayerCoord coord = dr_pin_list[i].get_access_point().getRealLayerCoord(); + candidate_root_coord_list.push_back(coord); + key_coord_pin_map[coord].insert(static_cast(i)); + } + MTree coord_tree = RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map); + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { + RTDM.updateNetDetailedResultToGCellMap( + ChangeType::kAdd, net_idx, new Segment(coord_segment.get_first()->value(), coord_segment.get_second()->value())); + } + } + for (auto& [net_idx, segment_set] : net_detailed_result_map) { + for (Segment* segment : segment_set) { + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kDel, net_idx, segment); + } } } - std::map>> net_result_map; - for (int32_t x = 0; x < dr_box_map.get_x_size(); x++) { - for (int32_t y = 0; y < dr_box_map.get_y_size(); y++) { - DRBox& dr_box = dr_box_map[x][y]; - for (auto& [net_idx, segment_list] : dr_box.get_net_detailed_result_map()) { - for (Segment& segment : segment_list) { - net_result_map[net_idx].push_back(segment); + // detailed patch + { + std::map> net_detailed_patch_map = RTDM.getNetDetailedPatchMap(die); + std::map*>> net_detailed_result_map = RTDM.getNetDetailedResultMap(die); + for (auto& [net_idx, patch_set] : net_detailed_patch_map) { + std::map> layer_rect_map; + for (Segment* segment : net_detailed_result_map[net_idx]) { + for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { + if (!net_shape.get_is_routing()) { + continue; + } + layer_rect_map[net_shape.get_layer_idx()].push_back(net_shape.get_rect()); + } + } + std::vector del_patch_list; + for (EXTLayerRect* patch : patch_set) { + bool is_used = false; + for (PlanarRect& rect : layer_rect_map[patch->get_layer_idx()]) { + if (RTUTIL.isClosedOverlap(patch->get_real_rect(), rect)) { + is_used = true; + break; + } + } + if (!is_used) { + del_patch_list.push_back(patch); + } + } + for (EXTLayerRect* del_patch : del_patch_list) { + RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kDel, net_idx, del_patch); + } + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void DetailedRouter::uploadViolation(DRModel& dr_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + Die& die = RTDM.getDatabase().get_die(); + + for (Violation* violation : RTDM.getViolationSet(die)) { + RTDM.updateViolationToGCellMap(ChangeType::kDel, violation); + } + for (Violation violation : getCostViolationList(dr_model)) { + RTDM.updateViolationToGCellMap(ChangeType::kAdd, new Violation(violation)); + } + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +std::vector DetailedRouter::getCostViolationList(DRModel& dr_model) +{ + Die& die = RTDM.getDatabase().get_die(); + + std::string top_name = RTUTIL.getString("dr_model"); + PlanarRect check_region = die.get_real_rect(); + std::vector> env_shape_list; + std::map>> net_pin_shape_map; + for (auto& [is_routing, layer_net_fixed_rect_map] : RTDM.getTypeLayerNetFixedRectMap(die)) { + for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { + for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { + if (net_idx == -1) { + for (auto& fixed_rect : fixed_rect_set) { + env_shape_list.emplace_back(fixed_rect, is_routing); + } + } else { + for (auto& fixed_rect : fixed_rect_set) { + net_pin_shape_map[net_idx].emplace_back(fixed_rect, is_routing); + } } } } } - std::vector& dr_net_list = dr_model.get_dr_net_list(); - for (auto& [net_idx, routing_segment_list] : net_result_map) { - DRNet& dr_net = dr_net_list[net_idx]; - - std::vector candidate_root_coord_list; - std::map, CmpLayerCoordByXASC> key_coord_pin_map; - std::vector& dr_pin_list = dr_net.get_dr_pin_list(); - for (size_t i = 0; i < dr_pin_list.size(); i++) { - LayerCoord coord = dr_pin_list[i].get_access_point().getRealLayerCoord(); - candidate_root_coord_list.push_back(coord); - key_coord_pin_map[coord].insert(static_cast(i)); + std::map*>> net_result_map; + for (auto& [net_idx, segment_set] : RTDM.getNetAccessResultMap(die)) { + for (Segment* segment : segment_set) { + net_result_map[net_idx].push_back(segment); } - MTree coord_tree = RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map); - for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { - RTDM.updateNetDetailedResultToGCellMap( - ChangeType::kAdd, net_idx, new Segment(coord_segment.get_first()->value(), coord_segment.get_second()->value())); + } + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { + for (Segment* segment : segment_set) { + net_result_map[net_idx].push_back(segment); + } + } + std::map> net_patch_map; + for (auto& [net_idx, patch_set] : RTDM.getNetAccessPatchMap(die)) { + for (EXTLayerRect* patch : patch_set) { + net_patch_map[net_idx].push_back(patch); } } for (auto& [net_idx, patch_set] : RTDM.getNetDetailedPatchMap(die)) { for (EXTLayerRect* patch : patch_set) { - RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kDel, net_idx, patch); + net_patch_map[net_idx].push_back(patch); } } - for (int32_t x = 0; x < dr_box_map.get_x_size(); x++) { - for (int32_t y = 0; y < dr_box_map.get_y_size(); y++) { - DRBox& dr_box = dr_box_map[x][y]; - for (auto& [net_idx, patch_list] : dr_box.get_net_detailed_patch_map()) { - for (EXTLayerRect& patch : patch_list) { - RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kAdd, net_idx, new EXTLayerRect(patch)); - } - } + std::set need_checked_net_set; + for (DRNet& dr_net : dr_model.get_dr_net_list()) { + need_checked_net_set.insert(dr_net.get_net_idx()); + } + + DETask de_task; + de_task.set_process_type(DEProcessType::kMultiNet); + de_task.set_top_name(top_name); + de_task.set_check_region(check_region); + de_task.set_env_shape_list(env_shape_list); + de_task.set_net_pin_shape_map(net_pin_shape_map); + de_task.set_net_result_map(net_result_map); + de_task.set_net_patch_map(net_patch_map); + de_task.set_need_checked_net_set(need_checked_net_set); + return RTDE.getViolationList(de_task); +} + +void DetailedRouter::updateBestResult(DRModel& dr_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + Die& die = RTDM.getDatabase().get_die(); + + std::map>>& best_net_detailed_result_map = dr_model.get_best_net_detailed_result_map(); + std::map>& best_net_detailed_patch_map = dr_model.get_best_net_detailed_patch_map(); + std::vector& best_violation_list = dr_model.get_best_violation_list(); + + int32_t curr_violation_num = getViolationNum(); + if (!best_net_detailed_result_map.empty() || !best_net_detailed_patch_map.empty()) { + if (static_cast(best_violation_list.size()) < curr_violation_num) { + return; } } + best_net_detailed_result_map.clear(); + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { + for (Segment* segment : segment_set) { + best_net_detailed_result_map[net_idx].push_back(*segment); + } + } + best_net_detailed_patch_map.clear(); + for (auto& [net_idx, patch_set] : RTDM.getNetDetailedPatchMap(die)) { + for (EXTLayerRect* patch : patch_set) { + best_net_detailed_patch_map[net_idx].push_back(*patch); + } + } + best_violation_list.clear(); + for (Violation* violation : RTDM.getViolationSet(die)) { + best_violation_list.push_back(*violation); + } RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } @@ -1227,13 +1491,61 @@ bool DetailedRouter::stopIteration(DRModel& dr_model) return false; } +void DetailedRouter::selectBestResult(DRModel& dr_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + dr_model.set_iter(dr_model.get_iter() + 1); + uploadBestResult(dr_model); + updateSummary(dr_model); + printSummary(dr_model); + outputNetCSV(dr_model); + outputViolationCSV(dr_model); + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void DetailedRouter::uploadBestResult(DRModel& dr_model) +{ + Die& die = RTDM.getDatabase().get_die(); + + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { + for (Segment* 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.updateNetAccessPatchToGCellMap(ChangeType::kDel, net_idx, patch); + } + } + for (Violation* violation : RTDM.getViolationSet(die)) { + RTDM.updateViolationToGCellMap(ChangeType::kDel, violation); + } + + for (auto& [net_idx, segment_list] : dr_model.get_best_net_detailed_result_map()) { + for (Segment& segment : segment_list) { + RTDM.updateNetDetailedResultToGCellMap(ChangeType::kAdd, net_idx, new Segment(segment)); + } + } + for (auto& [net_idx, patch_list] : dr_model.get_best_net_detailed_patch_map()) { + for (EXTLayerRect& patch : patch_list) { + RTDM.updateNetAccessPatchToGCellMap(ChangeType::kAdd, net_idx, new EXTLayerRect(patch)); + } + } + for (Violation violation : dr_model.get_best_violation_list()) { + RTDM.updateViolationToGCellMap(ChangeType::kAdd, new Violation(violation)); + } +} + #if 1 // update env void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect* fixed_rect, bool is_routing) { NetShape net_shape(net_idx, fixed_rect->getRealLayerRect(), is_routing); - for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { + for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { dr_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1247,7 +1559,7 @@ void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_typ void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, Segment& segment) { for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, segment)) { - for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { + for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { dr_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1262,12 +1574,12 @@ void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_typ void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch) { NetShape net_shape(net_idx, patch.getRealLayerRect(), true); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { + for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { - pa_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); + dr_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); } else if (change_type == ChangeType::kDel) { - pa_node->get_orient_fixed_rect_map()[orientation].erase(net_shape.get_net_idx()); + dr_node->get_orient_fixed_rect_map()[orientation].erase(net_shape.get_net_idx()); } } } @@ -1276,7 +1588,7 @@ void DetailedRouter::updateFixedRectToGraph(DRBox& dr_box, ChangeType change_typ void DetailedRouter::updateNetResultToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, Segment& segment) { for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, segment)) { - for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { + for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { dr_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1291,43 +1603,125 @@ void DetailedRouter::updateNetResultToGraph(DRBox& dr_box, ChangeType change_typ void DetailedRouter::updateNetResultToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch) { NetShape net_shape(net_idx, patch.getRealLayerRect(), true); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { + for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { - pa_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); + dr_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); } else if (change_type == ChangeType::kDel) { - pa_node->get_orient_routed_rect_map()[orientation].erase(net_shape.get_net_idx()); + dr_node->get_orient_routed_rect_map()[orientation].erase(net_shape.get_net_idx()); } } } } -void DetailedRouter::updateViolationToGraph(DRBox& dr_box, ChangeType change_type, Violation& violation) +void DetailedRouter::addViolationToGraph(DRBox& dr_box, Violation& violation) { - NetShape net_shape(-1, violation.get_violation_shape().getRealLayerRect(), violation.get_is_routing()); - for (auto& [dr_node, orientation_set] : getNodeOrientationMap(dr_box, net_shape)) { - for (Orientation orientation : orientation_set) { - if (change_type == ChangeType::kAdd) { - dr_node->get_orient_violation_number_map()[orientation]++; - } else if (change_type == ChangeType::kDel) { - dr_node->get_orient_violation_number_map()[orientation]--; + LayerRect searched_rect; + { + EXTLayerRect& violation_shape = violation.get_violation_shape(); + searched_rect.set_rect(RTUTIL.getEnlargedRect(violation_shape.get_real_rect(), RTDM.getOnlyPitch())); + if (violation.get_is_routing()) { + searched_rect.set_layer_idx(violation_shape.get_layer_idx()); + } else { + RTLOG.error(Loc::current(), "The violation layer is cut!"); + } + } + std::vector> overlap_segment_list; + for (auto& [net_idx, segment_list] : dr_box.get_net_detailed_result_map()) { + if (!RTUTIL.exist(violation.get_violation_net_set(), net_idx)) { + continue; + } + for (Segment& segment : segment_list) { + if (!RTUTIL.isOverlap(searched_rect, segment)) { + continue; + } + overlap_segment_list.push_back(segment); + break; + } + } + addViolationToGraph(dr_box, searched_rect, overlap_segment_list); +} + +void DetailedRouter::addViolationToGraph(DRBox& dr_box, LayerRect& searched_rect, std::vector>& overlap_segment_list) +{ + ScaleAxis& box_track_axis = dr_box.get_box_track_axis(); + std::vector>& layer_node_map = dr_box.get_layer_node_map(); + + for (Segment& overlap_segment : overlap_segment_list) { + LayerCoord& first_coord = overlap_segment.get_first(); + LayerCoord& second_coord = overlap_segment.get_second(); + if (first_coord == second_coord) { + continue; + } + PlanarRect real_rect = RTUTIL.getEnlargedRect(first_coord, second_coord, 0); + if (!RTUTIL.existTrackGrid(real_rect, box_track_axis)) { + continue; + } + PlanarRect grid_rect = RTUTIL.getTrackGrid(real_rect, box_track_axis); + std::map> distance_node_map; + { + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + for (int32_t layer_idx = first_layer_idx; layer_idx <= second_layer_idx; layer_idx++) { + for (int32_t x = grid_rect.get_ll_x(); x <= grid_rect.get_ur_x(); x++) { + for (int32_t y = grid_rect.get_ll_y(); y <= grid_rect.get_ur_y(); y++) { + DRNode* dr_node = &layer_node_map[layer_idx][x][y]; + if (searched_rect.get_layer_idx() != dr_node->get_layer_idx()) { + continue; + } + int32_t distance = 0; + if (!RTUTIL.isInside(searched_rect.get_rect(), dr_node->get_planar_coord())) { + distance = RTUTIL.getManhattanDistance(searched_rect.getMidPoint(), dr_node->get_planar_coord()); + } + distance_node_map[distance].insert(dr_node); + } + } + } + } + std::set valid_node_set; + if (!distance_node_map[0].empty()) { + valid_node_set = distance_node_map[0]; + } else { + for (auto& [distance, node_set] : distance_node_map) { + valid_node_set.insert(node_set.begin(), node_set.end()); + if (valid_node_set.size() >= 2) { + break; + } + } + } + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + Orientation oppo_orientation = RTUTIL.getOppositeOrientation(orientation); + for (DRNode* valid_node : valid_node_set) { + if (LayerCoord(*valid_node) != first_coord) { + valid_node->get_orient_violation_number_map()[oppo_orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), oppo_orientation)) { + valid_node->get_neighbor_node_map()[oppo_orientation]->get_orient_violation_number_map()[orientation]++; + } + } + if (LayerCoord(*valid_node) != second_coord) { + valid_node->get_orient_violation_number_map()[orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), orientation)) { + valid_node->get_neighbor_node_map()[orientation]->get_orient_violation_number_map()[oppo_orientation]++; + } } } } } -std::map> DetailedRouter::getNodeOrientationMap(DRBox& dr_box, NetShape& net_shape) +std::map> DetailedRouter::getNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, bool need_enlarged) { std::map> node_orientation_map; if (net_shape.get_is_routing()) { - node_orientation_map = getRoutingNodeOrientationMap(dr_box, net_shape); + node_orientation_map = getRoutingNodeOrientationMap(dr_box, net_shape, need_enlarged); } else { - node_orientation_map = getCutNodeOrientationMap(dr_box, net_shape); + node_orientation_map = getCutNodeOrientationMap(dr_box, net_shape, need_enlarged); } return node_orientation_map; } -std::map> DetailedRouter::getRoutingNodeOrientationMap(DRBox& dr_box, NetShape& net_shape) +std::map> DetailedRouter::getRoutingNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, + bool need_enlarged) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::map& layer_enclosure_map = RTDM.getDatabase().get_layer_enclosure_map(); @@ -1336,7 +1730,19 @@ std::map> DetailedRouter::getRoutingNodeOrientati } int32_t layer_idx = net_shape.get_layer_idx(); RoutingLayer& routing_layer = routing_layer_list[layer_idx]; - int32_t min_spacing = routing_layer.getMinSpacing(net_shape.get_rect()); + // x_spacing y_spacing + std::vector> spacing_pair_list; + { + // prl + int32_t prl_spacing = routing_layer.getPRLSpacing(net_shape.get_rect()); + spacing_pair_list.emplace_back(prl_spacing, prl_spacing); + // eol + if (routing_layer.isPreferH()) { + spacing_pair_list.emplace_back(routing_layer.get_eol_spacing(), routing_layer.get_eol_within()); + } else { + spacing_pair_list.emplace_back(routing_layer.get_eol_within(), routing_layer.get_eol_spacing()); + } + } int32_t half_wire_width = routing_layer.get_min_width() / 2; PlanarRect& enclosure = layer_enclosure_map[layer_idx]; int32_t enclosure_half_x_span = enclosure.getXSpan() / 2; @@ -1345,12 +1751,19 @@ std::map> DetailedRouter::getRoutingNodeOrientati GridMap& dr_node_map = dr_box.get_layer_node_map()[layer_idx]; std::map> node_orientation_map; // wire 与 net_shape - { - // 膨胀size为 min_spacing + half_wire_width - int32_t enlarged_size = min_spacing + half_wire_width; + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = half_wire_width; + int32_t enlarged_y_size = half_wire_width; + if (need_enlarged) { + // 膨胀size为 half_wire_width + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } // 贴合的也不算违例 - enlarged_size -= 1; - PlanarRect planar_enlarged_rect = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_size); + enlarged_x_size -= 1; + enlarged_y_size -= 1; + PlanarRect planar_enlarged_rect + = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(planar_enlarged_rect, dr_box.get_box_track_axis())) { DRNode& node = dr_node_map[grid_coord.get_x()][grid_coord.get_y()]; for (const Orientation& orientation : orientation_set) { @@ -1366,10 +1779,14 @@ std::map> DetailedRouter::getRoutingNodeOrientati } } // enclosure 与 net_shape - { - // 膨胀size为 min_spacing + enclosure_half_span - int32_t enlarged_x_size = min_spacing + enclosure_half_x_span; - int32_t enlarged_y_size = min_spacing + enclosure_half_y_span; + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = enclosure_half_x_span; + int32_t enlarged_y_size = enclosure_half_y_span; + if (need_enlarged) { + // 膨胀size为 enclosure_half_span + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } // 贴合的也不算违例 enlarged_x_size -= 1; enlarged_y_size -= 1; @@ -1393,7 +1810,7 @@ std::map> DetailedRouter::getRoutingNodeOrientati return node_orientation_map; } -std::map> DetailedRouter::getCutNodeOrientationMap(DRBox& dr_box, NetShape& net_shape) +std::map> DetailedRouter::getCutNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, bool need_enlarged) { std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); std::map>& cut_to_adjacent_routing_map = RTDM.getDatabase().get_cut_to_adjacent_routing_map(); @@ -1401,39 +1818,76 @@ std::map> DetailedRouter::getCutNodeOrientationMa if (net_shape.get_is_routing()) { RTLOG.error(Loc::current(), "The type of net_shape is routing!"); } - std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[net_shape.get_layer_idx()]; - if (adjacent_routing_layer_idx_list.size() != 2) { - // 如果相邻层只有一个,将不会在那一层打via - return {}; + CutLayer& cut_layer = cut_layer_list[net_shape.get_layer_idx()]; + std::map>> cut_spacing_map; + { + int32_t curr_cut_layer_idx = net_shape.get_layer_idx(); + if (0 <= curr_cut_layer_idx && curr_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[curr_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_curr_x_spacing(), cut_layer.get_curr_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_curr_prl_spacing(), cut_layer.get_curr_y_spacing()); + cut_spacing_map[curr_cut_layer_idx] = spacing_pair_list; + } + } + int32_t below_cut_layer_idx = net_shape.get_layer_idx() - 1; + if (0 <= below_cut_layer_idx && below_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[below_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_below_x_spacing(), cut_layer.get_below_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_below_prl_spacing(), cut_layer.get_below_y_spacing()); + cut_spacing_map[below_cut_layer_idx] = spacing_pair_list; + } + } + int32_t above_cut_layer_idx = net_shape.get_layer_idx() + 1; + if (0 <= above_cut_layer_idx && above_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[above_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_above_x_spacing(), cut_layer.get_above_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_above_prl_spacing(), cut_layer.get_above_y_spacing()); + cut_spacing_map[above_cut_layer_idx] = spacing_pair_list; + } + } } - int32_t below_routing_layer_idx = adjacent_routing_layer_idx_list.front(); - int32_t above_routing_layer_idx = adjacent_routing_layer_idx_list.back(); - RTUTIL.swapByASC(below_routing_layer_idx, above_routing_layer_idx); - - std::vector>& layer_node_map = dr_box.get_layer_node_map(); std::map> node_orientation_map; - - // 膨胀size为 min_spacing + cut_shape_half_span - int32_t cut_spacing = cut_layer_list[net_shape.get_layer_idx()].getMinSpacing(); - PlanarRect& cut_shape = layer_via_master_list[below_routing_layer_idx].front().get_cut_shape_list().front(); - int32_t enlarged_x_size = cut_spacing + cut_shape.getXSpan() / 2; - int32_t enlarged_y_size = cut_spacing + cut_shape.getYSpan() / 2; - // 贴合的也不算违例 - enlarged_x_size -= 1; - enlarged_y_size -= 1; - PlanarRect space_enlarged_rect - = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); - for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(space_enlarged_rect, dr_box.get_box_track_axis())) { - if (!RTUTIL.exist(orientation_set, Orientation::kAbove) && !RTUTIL.exist(orientation_set, Orientation::kBelow)) { - continue; - } - DRNode& below_node = layer_node_map[below_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; - if (RTUTIL.exist(below_node.get_neighbor_node_map(), Orientation::kAbove)) { - node_orientation_map[&below_node].insert(Orientation::kAbove); - } - DRNode& above_node = layer_node_map[above_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; - if (RTUTIL.exist(above_node.get_neighbor_node_map(), Orientation::kBelow)) { - node_orientation_map[&above_node].insert(Orientation::kBelow); + for (auto& [cut_layer_idx, spacing_pair_list] : cut_spacing_map) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[cut_layer_idx]; + int32_t below_routing_layer_idx = adjacent_routing_layer_idx_list.front(); + int32_t above_routing_layer_idx = adjacent_routing_layer_idx_list.back(); + RTUTIL.swapByASC(below_routing_layer_idx, above_routing_layer_idx); + PlanarRect& cut_shape = layer_via_master_list[below_routing_layer_idx].front().get_cut_shape_list().front(); + int32_t cut_shape_half_x_span = cut_shape.getXSpan() / 2; + int32_t cut_shape_half_y_span = cut_shape.getYSpan() / 2; + std::vector>& layer_node_map = dr_box.get_layer_node_map(); + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = cut_shape_half_x_span; + int32_t enlarged_y_size = cut_shape_half_y_span; + if (need_enlarged) { + // 膨胀size为 cut_shape_half_span + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } + // 贴合的也不算违例 + enlarged_x_size -= 1; + enlarged_y_size -= 1; + PlanarRect space_enlarged_rect + = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); + for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(space_enlarged_rect, dr_box.get_box_track_axis())) { + if (!RTUTIL.exist(orientation_set, Orientation::kAbove) && !RTUTIL.exist(orientation_set, Orientation::kBelow)) { + continue; + } + DRNode& below_node = layer_node_map[below_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; + if (RTUTIL.exist(below_node.get_neighbor_node_map(), Orientation::kAbove)) { + node_orientation_map[&below_node].insert(Orientation::kAbove); + } + DRNode& above_node = layer_node_map[above_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; + if (RTUTIL.exist(above_node.get_neighbor_node_map(), Orientation::kBelow)) { + node_orientation_map[&above_node].insert(Orientation::kBelow); + } + } } } return node_orientation_map; @@ -1450,17 +1904,17 @@ void DetailedRouter::updateSummary(DRModel& dr_model) std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); std::vector>& layer_via_master_list = RTDM.getDatabase().get_layer_via_master_list(); + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - std::map& routing_wire_length_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_wire_length; - std::map& cut_via_num_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].cut_via_num_map; - int32_t& total_via_num = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_via_num; - std::map& routing_violation_num_map - = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].routing_violation_num_map; - int32_t& total_violation_num = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_violation_num; - std::map>& clock_timing - = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].clock_timing; - std::map& power_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].power_map; + + std::map& routing_wire_length_map = summary.iter_dr_summary_map[dr_model.get_iter()].routing_wire_length_map; + double& total_wire_length = summary.iter_dr_summary_map[dr_model.get_iter()].total_wire_length; + std::map& cut_via_num_map = summary.iter_dr_summary_map[dr_model.get_iter()].cut_via_num_map; + int32_t& total_via_num = summary.iter_dr_summary_map[dr_model.get_iter()].total_via_num; + std::map& routing_violation_num_map = summary.iter_dr_summary_map[dr_model.get_iter()].routing_violation_num_map; + int32_t& total_violation_num = summary.iter_dr_summary_map[dr_model.get_iter()].total_violation_num; + std::map>& clock_timing = summary.iter_dr_summary_map[dr_model.get_iter()].clock_timing; + std::map& power_map = summary.iter_dr_summary_map[dr_model.get_iter()].power_map; std::vector& dr_net_list = dr_model.get_dr_net_list(); @@ -1522,17 +1976,17 @@ void DetailedRouter::printSummary(DRModel& dr_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - std::map& routing_wire_length_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_wire_length; - std::map& cut_via_num_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].cut_via_num_map; - int32_t& total_via_num = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_via_num; - std::map& routing_violation_num_map - = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].routing_violation_num_map; - int32_t& total_violation_num = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].total_violation_num; - std::map>& clock_timing - = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].clock_timing; - std::map& power_map = RTDM.getSummary().iter_dr_summary_map[dr_model.get_iter()].power_map; + + std::map& routing_wire_length_map = summary.iter_dr_summary_map[dr_model.get_iter()].routing_wire_length_map; + double& total_wire_length = summary.iter_dr_summary_map[dr_model.get_iter()].total_wire_length; + std::map& cut_via_num_map = summary.iter_dr_summary_map[dr_model.get_iter()].cut_via_num_map; + int32_t& total_via_num = summary.iter_dr_summary_map[dr_model.get_iter()].total_via_num; + std::map& routing_violation_num_map = summary.iter_dr_summary_map[dr_model.get_iter()].routing_violation_num_map; + int32_t& total_violation_num = summary.iter_dr_summary_map[dr_model.get_iter()].total_violation_num; + std::map>& clock_timing = summary.iter_dr_summary_map[dr_model.get_iter()].clock_timing; + std::map& power_map = summary.iter_dr_summary_map[dr_model.get_iter()].power_map; fort::char_table routing_wire_length_map_table; { @@ -1571,26 +2025,23 @@ void DetailedRouter::printSummary(DRModel& dr_model) routing_violation_num_map_table << fort::header << "Total" << total_violation_num << RTUTIL.getPercentage(total_violation_num, total_violation_num) << fort::endr; } - fort::char_table timing_and_power_table; + fort::char_table timing_table; + fort::char_table power_table; if (enable_timing) { - timing_and_power_table << fort::header << "Clock" - << "TNS" - << "WNS" - << "Freq(MHz)" << fort::endr; + timing_table << fort::header << "clock_name" + << "tns" + << "wns" + << "freq" << fort::endr; for (auto& [clock_name, timing_map] : clock_timing) { - timing_and_power_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; + timing_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; } + power_table << fort::header << "power_type" << "power_value" << fort::endr; for (auto& [type, power] : power_map) { - timing_and_power_table << fort::header << "type" << type << fort::endr; - timing_and_power_table << fort::header << "power" << power << fort::endr; + power_table << type << power << fort::endr; } } - std::vector table_list; - table_list.push_back(routing_wire_length_map_table); - table_list.push_back(cut_via_num_map_table); - table_list.push_back(routing_violation_num_map_table); - table_list.push_back(timing_and_power_table); - RTUTIL.printTableList(table_list); + RTUTIL.printTableList({routing_wire_length_map_table, cut_via_num_map_table, routing_violation_num_map_table}); + RTUTIL.printTableList({timing_table, power_table}); } void DetailedRouter::outputNetCSV(DRModel& dr_model) @@ -1840,8 +2291,8 @@ void DetailedRouter::debugPlotDRModel(DRModel& dr_model, std::string flag) // violation { - GPStruct violation_struct("violation"); for (Violation* violation : RTDM.getViolationSet(die)) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation->get_violation_type()))); EXTLayerRect& violation_shape = violation->get_violation_shape(); GPBoundary gp_boundary; @@ -1853,8 +2304,8 @@ void DetailedRouter::debugPlotDRModel(DRModel& dr_model, std::string flag) gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(dr_temp_directory_path, flag, "_dr_model.gds"); @@ -1933,7 +2384,7 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s std::vector>& layer_via_master_list = RTDM.getDatabase().get_layer_via_master_list(); std::string& dr_temp_directory_path = RTDM.getConfig().dr_temp_directory_path; - PlanarRect box_rect = dr_box.get_box_rect().get_real_rect(); + PlanarRect box_region = dr_box.get_box_rect().get_real_rect(); int32_t point_size = 5; @@ -1945,7 +2396,7 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s GPBoundary gp_boundary; gp_boundary.set_layer_idx(0); gp_boundary.set_data_type(0); - gp_boundary.set_rect(box_rect); + gp_boundary.set_rect(box_region); base_region_struct.push(gp_boundary); gp_gds.addStruct(base_region_struct); } @@ -1953,18 +2404,18 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s // gcell_axis { GPStruct gcell_axis_struct("gcell_axis"); - for (int32_t x : RTUTIL.getScaleList(box_rect.get_ll_x(), box_rect.get_ur_x(), gcell_axis.get_x_grid_list())) { + for (int32_t x : RTUTIL.getScaleList(box_region.get_ll_x(), box_region.get_ur_x(), gcell_axis.get_x_grid_list())) { GPPath gp_path; gp_path.set_layer_idx(0); gp_path.set_data_type(1); - gp_path.set_segment(x, box_rect.get_ll_y(), x, box_rect.get_ur_y()); + gp_path.set_segment(x, box_region.get_ll_y(), x, box_region.get_ur_y()); gcell_axis_struct.push(gp_path); } - for (int32_t y : RTUTIL.getScaleList(box_rect.get_ll_y(), box_rect.get_ur_y(), gcell_axis.get_y_grid_list())) { + for (int32_t y : RTUTIL.getScaleList(box_region.get_ll_y(), box_region.get_ur_y(), gcell_axis.get_y_grid_list())) { GPPath gp_path; gp_path.set_layer_idx(0); gp_path.set_data_type(1); - gp_path.set_segment(box_rect.get_ll_x(), y, box_rect.get_ur_x(), y); + gp_path.set_segment(box_region.get_ll_x(), y, box_region.get_ur_x(), y); gcell_axis_struct.push(gp_path); } gp_gds.addStruct(gcell_axis_struct); @@ -2162,8 +2613,8 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s // box_track_axis { GPStruct box_track_axis_struct("box_track_axis"); - PlanarCoord& real_ll = box_rect.get_ll(); - PlanarCoord& real_ur = box_rect.get_ur(); + PlanarCoord& real_ll = box_region.get_ll(); + PlanarCoord& real_ur = box_region.get_ur(); ScaleAxis& box_track_axis = dr_box.get_box_track_axis(); std::vector x_list = RTUTIL.getScaleList(real_ll.get_x(), real_ur.get_x(), box_track_axis.get_x_grid_list()); std::vector y_list = RTUTIL.getScaleList(real_ll.get_y(), real_ur.get_y(), box_track_axis.get_y_grid_list()); @@ -2319,8 +2770,8 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s // violation { - GPStruct violation_struct("violation"); for (Violation& violation : dr_box.get_violation_list()) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation.get_violation_type()))); EXTLayerRect& violation_shape = violation.get_violation_shape(); GPBoundary gp_boundary; @@ -2332,8 +2783,8 @@ void DetailedRouter::debugPlotDRBox(DRBox& dr_box, int32_t curr_task_idx, std::s gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(dr_temp_directory_path, flag, "_dr_box_", dr_box.get_dr_box_id().get_x(), "_", diff --git a/src/operation/iRT/source/module/detailed_router/DetailedRouter.hpp b/src/operation/iRT/source/module/detailed_router/DetailedRouter.hpp index de67ed881..f9267e919 100644 --- a/src/operation/iRT/source/module/detailed_router/DetailedRouter.hpp +++ b/src/operation/iRT/source/module/detailed_router/DetailedRouter.hpp @@ -59,6 +59,7 @@ class DetailedRouter void setDRParameter(DRModel& dr_model, int32_t iter, DRParameter& dr_parameter); void initDRBoxMap(DRModel& dr_model); void buildBoxSchedule(DRModel& dr_model); + void splitNetResult(DRModel& dr_model); void routeDRBoxMap(DRModel& dr_model); void buildFixedRect(DRBox& dr_box); void buildAccessResult(DRBox& dr_box); @@ -70,9 +71,9 @@ class DetailedRouter void buildLayerNodeMap(DRBox& dr_box); void buildDRNodeNeighbor(DRBox& dr_box); void buildOrientNetMap(DRBox& dr_box); + void exemptPinShape(DRBox& dr_box); void routeDRBox(DRBox& dr_box); std::vector initTaskSchedule(DRBox& dr_box); - std::vector getTaskScheduleByViolation(DRBox& dr_box); void routeDRTask(DRBox& dr_box, DRTask* dr_task); void initSingleTask(DRBox& dr_box, DRTask* dr_task); bool isConnectedAllEnd(DRBox& dr_box); @@ -87,10 +88,6 @@ class DetailedRouter void resetSinglePath(DRBox& dr_box); void updateTaskResult(DRBox& dr_box); std::vector> getRoutingSegmentList(DRBox& dr_box); - void patchSingleTask(DRBox& dr_box); - std::vector getPatchViolationList(DRBox& dr_box); - void updateTaskPatch(DRBox& dr_box); - std::vector getRoutingPatchList(DRBox& dr_box); void resetSingleTask(DRBox& dr_box); void pushToOpenList(DRBox& dr_box, DRNode* curr_node); DRNode* popFromOpenList(DRBox& dr_box); @@ -104,11 +101,19 @@ class DetailedRouter double getEstimateViaCost(DRBox& dr_box, DRNode* start_node, DRNode* end_node); void updateViolationList(DRBox& dr_box); std::vector getCostViolationList(DRBox& dr_box); - void uploadViolation(DRBox& dr_box); + void updateBestResult(DRBox& dr_box); + void updateTaskSchedule(DRBox& dr_box, std::vector& routing_task_list); + void selectBestResult(DRBox& dr_box); + void uploadBestResult(DRBox& dr_box); void freeDRBox(DRBox& dr_box); int32_t getViolationNum(); void uploadNetResult(DRModel& dr_model); + void uploadViolation(DRModel& dr_model); + std::vector getCostViolationList(DRModel& dr_model); + void updateBestResult(DRModel& dr_model); bool stopIteration(DRModel& dr_model); + void selectBestResult(DRModel& dr_model); + void uploadBestResult(DRModel& dr_model); #if 1 // update env void updateFixedRectToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect* fixed_rect, bool is_routing); @@ -116,10 +121,11 @@ class DetailedRouter void updateFixedRectToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch); void updateNetResultToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, Segment& segment); void updateNetResultToGraph(DRBox& dr_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch); - void updateViolationToGraph(DRBox& dr_box, ChangeType change_type, Violation& violation); - std::map> getNodeOrientationMap(DRBox& dr_box, NetShape& net_shape); - std::map> getRoutingNodeOrientationMap(DRBox& dr_box, NetShape& net_shape); - std::map> getCutNodeOrientationMap(DRBox& dr_box, NetShape& net_shape); + void addViolationToGraph(DRBox& dr_box, Violation& violation); + void addViolationToGraph(DRBox& dr_box, LayerRect& searched_rect, std::vector>& overlap_segment_list); + std::map> getNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, bool need_enlarged); + std::map> getRoutingNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, bool need_enlarged); + std::map> getCutNodeOrientationMap(DRBox& dr_box, NetShape& net_shape, bool need_enlarged); #endif #if 1 // exhibit diff --git a/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRBox.hpp b/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRBox.hpp index 327c48994..af8e435f2 100644 --- a/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRBox.hpp +++ b/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRBox.hpp @@ -49,6 +49,9 @@ class DRBox std::vector& get_violation_list() { return _violation_list; } ScaleAxis& get_box_track_axis() { return _box_track_axis; } std::vector>& get_layer_node_map() { return _layer_node_map; } + std::map>>& get_best_net_detailed_result_map() { return _best_net_detailed_result_map; } + std::map>& get_best_net_detailed_patch_map() { return _best_net_detailed_patch_map; } + std::vector& get_best_violation_list() { return _best_violation_list; } // setter void set_box_rect(const EXTPlanarRect& box_rect) { _box_rect = box_rect; } void set_dr_box_id(const DRBoxId& dr_box_id) { _dr_box_id = dr_box_id; } @@ -78,6 +81,15 @@ class DRBox void set_violation_list(const std::vector& violation_list) { _violation_list = violation_list; } void set_box_track_axis(const ScaleAxis& box_track_axis) { _box_track_axis = box_track_axis; } void set_layer_node_map(const std::vector>& layer_node_map) { _layer_node_map = layer_node_map; } + void set_best_net_detailed_result_map(const std::map>>& best_net_detailed_result_map) + { + _best_net_detailed_result_map = best_net_detailed_result_map; + } + void set_best_net_detailed_patch_map(const std::map>& best_net_detailed_patch_map) + { + _best_net_detailed_patch_map = best_net_detailed_patch_map; + } + void set_best_violation_list(const std::vector& best_violation_list) { _best_violation_list = best_violation_list; } // function #if 1 // astar // single task @@ -87,7 +99,6 @@ class DRBox std::vector& get_path_node_list() { return _path_node_list; } std::vector& get_single_task_visited_node_list() { return _single_task_visited_node_list; } std::vector>& get_routing_segment_list() { return _routing_segment_list; } - std::vector& get_routing_patch_list() { return _routing_patch_list; } void set_curr_dr_task(DRTask* curr_dr_task) { _curr_dr_task = curr_dr_task; } void set_start_node_list_list(const std::vector>& start_node_list_list) { @@ -103,7 +114,6 @@ class DRBox { _routing_segment_list = routing_segment_list; } - void set_routing_patch_list(const std::vector& routing_patch_list) { _routing_patch_list = routing_patch_list; } // single path PriorityQueue, CmpDRNodeCost>& get_open_queue() { return _open_queue; } std::vector& get_single_path_visited_node_list() { return _single_path_visited_node_list; } @@ -131,6 +141,9 @@ class DRBox std::vector _violation_list; ScaleAxis _box_track_axis; std::vector> _layer_node_map; + std::map>> _best_net_detailed_result_map; + std::map> _best_net_detailed_patch_map; + std::vector _best_violation_list; #if 1 // astar // single task DRTask* _curr_dr_task = nullptr; @@ -139,7 +152,6 @@ class DRBox std::vector _path_node_list; std::vector _single_task_visited_node_list; std::vector> _routing_segment_list; - std::vector _routing_patch_list; // single path PriorityQueue, CmpDRNodeCost> _open_queue; std::vector _single_path_visited_node_list; diff --git a/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRModel.hpp b/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRModel.hpp index 76377effc..630b7e439 100644 --- a/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRModel.hpp +++ b/src/operation/iRT/source/module/detailed_router/dr_data_manager/DRModel.hpp @@ -34,12 +34,24 @@ class DRModel DRParameter& get_dr_parameter() { return _dr_parameter; } GridMap& get_dr_box_map() { return _dr_box_map; } std::vector>& get_dr_box_id_list_list() { return _dr_box_id_list_list; } + std::map>>& get_best_net_detailed_result_map() { return _best_net_detailed_result_map; } + std::map>& get_best_net_detailed_patch_map() { return _best_net_detailed_patch_map; } + std::vector& get_best_violation_list() { return _best_violation_list; } // setter void set_dr_net_list(const std::vector& dr_net_list) { _dr_net_list = dr_net_list; } void set_iter(const int32_t iter) { _iter = iter; } void set_dr_parameter(const DRParameter& dr_parameter) { _dr_parameter = dr_parameter; } void set_dr_box_map(const GridMap& dr_box_map) { _dr_box_map = dr_box_map; } void set_dr_box_id_list_list(const std::vector>& dr_box_id_list_list) { _dr_box_id_list_list = dr_box_id_list_list; } + void set_best_net_detailed_result_map(const std::map>>& best_net_detailed_result_map) + { + _best_net_detailed_result_map = best_net_detailed_result_map; + } + void set_best_net_detailed_patch_map(const std::map>& best_net_detailed_patch_map) + { + _best_net_detailed_patch_map = best_net_detailed_patch_map; + } + void set_best_violation_list(const std::vector& best_violation_list) { _best_violation_list = best_violation_list; } private: std::vector _dr_net_list; @@ -47,6 +59,9 @@ class DRModel DRParameter _dr_parameter; GridMap _dr_box_map; std::vector> _dr_box_id_list_list; + std::map>> _best_net_detailed_result_map; + std::map> _best_net_detailed_patch_map; + std::vector _best_violation_list; }; } // namespace irt diff --git a/src/operation/iRT/source/module/detailed_router/framwork.txt b/src/operation/iRT/source/module/detailed_router/framwork.txt index 0a5833be0..173d7947d 100644 --- a/src/operation/iRT/source/module/detailed_router/framwork.txt +++ b/src/operation/iRT/source/module/detailed_router/framwork.txt @@ -1,26 +1,29 @@ initDRModel:初始化dr_net iterativeDRModel:迭代DRModel setDRParameter:设置参数 - initDRBoxMap:构建DRBox框架,里面主要数据为空 + initDRBoxMap:构建DRBox框架,里面主要数据为空 buildBoxSchedule:构建Box布线的调度表 + splitNetResult:以Box边界分割线网结果 routeDRBoxMap: - buildFixedRect:将GCellMap中的fix_rect以指针的方式添加到Box的type_layer_net_fixed_rect_map - buildAccessResult:将GCellmap中的access_result(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 - buildNetResult:将GCellMap中的net_result以实体的方式拷贝到Box的net_result_map - buildViolation:将GCellMap中的violation以实体的方式拷贝到Box的violation_list,并在GCellMap中删除 + buildFixedRect:将GCellmap中的fix_rect(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 + buildAccessResult:将GCellmap中的access结果(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 + buildNetResult:将GCellMap中的net_result以实体的方式拷贝到Box的net_result_map,对于完全在Box内的,在GCellMap中删除 + buildViolation:将GCellMap中的violation以实体的方式拷贝到Box的violation_list,对于完全在Box内的,在GCellMap中删除 initDRTaskList:构建DRTask buildBoxTrackAxis:构建Box内的track_axis - buildLayerNodeMap:构建Box的Graph,只有节点,其他信息后续构建 + buildLayerNodeMap:构建Box的Graph,只有节点,其他信息后续构建 buildDRNodeNeighbor:将所有节点连接 - buildOrientNetMap:构建Graph的cost,环境从Box中得到,在dr阶段net_access_result为fix结果 + buildOrientNetMap:构建Graph的cost,环境从Box中得到,在dr阶段net_access_result为fix结果 routeDRBox: initTaskSchedule:初始化task布线调度表 - routeDRTask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 - updateViolationList:首先得到Violation存到Box下面,然后Violation结果从graph中删除,再加入新的结果 + routeDRTask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 + updateViolationList:首先得到Violation存到Box下面,然后Violation结果从graph中删除,再加入新的结果 getTaskScheduleByViolation:通过Violation得到新的布线调度 - uploadViolation:将violation加入gcell_map + uploadNetResult:构建布线数据,并加入GCellMap + uploadViolation:将violation加入GCellMap freeDRBox:析构 - uploadNetResult:将所有的box布线结果去环优化,然后删除所有GCellMap的结果再添加 + uploadNetResult:将所有的box布线结果去环优化,然后删除所有GCellMap的结果再添加 + uploadViolation:将整个版图结果进行检查并将violation加入GCellMap diff --git a/src/operation/iRT/source/module/drc_engine/DRCEngine.cpp b/src/operation/iRT/source/module/drc_engine/DRCEngine.cpp index 72a8aff10..ebc695d71 100644 --- a/src/operation/iRT/source/module/drc_engine/DRCEngine.cpp +++ b/src/operation/iRT/source/module/drc_engine/DRCEngine.cpp @@ -49,23 +49,109 @@ void DRCEngine::destroyInst() // function +void DRCEngine::init() +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + updateIgnoreViolationSet(); + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void DRCEngine::updateIgnoreViolationSet() +{ + Die& die = RTDM.getDatabase().get_die(); + std::vector& net_list = RTDM.getDatabase().get_net_list(); + + std::string top_name = RTUTIL.getString("ignore_violation"); + PlanarRect check_region = die.get_real_rect(); + std::vector> env_shape_list; + std::map>> net_pin_shape_map; + for (auto& [is_routing, layer_net_fixed_rect_map] : RTDM.getTypeLayerNetFixedRectMap(die)) { + for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { + for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { + if (net_idx == -1) { + for (auto& fixed_rect : fixed_rect_set) { + env_shape_list.emplace_back(fixed_rect, is_routing); + } + } else { + for (auto& fixed_rect : fixed_rect_set) { + net_pin_shape_map[net_idx].emplace_back(fixed_rect, is_routing); + } + } + } + } + } + std::map*>> net_result_map; + for (auto& [net_idx, segment_set] : RTDM.getNetAccessResultMap(die)) { + for (Segment* segment : segment_set) { + net_result_map[net_idx].push_back(segment); + } + } + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) { + for (Segment* segment : segment_set) { + net_result_map[net_idx].push_back(segment); + } + } + std::map> net_patch_map; + for (auto& [net_idx, patch_set] : RTDM.getNetAccessPatchMap(die)) { + for (EXTLayerRect* patch : patch_set) { + net_patch_map[net_idx].push_back(patch); + } + } + for (auto& [net_idx, patch_set] : RTDM.getNetDetailedPatchMap(die)) { + for (EXTLayerRect* patch : patch_set) { + net_patch_map[net_idx].push_back(patch); + } + } + std::set need_checked_net_set; + for (Net& net : net_list) { + need_checked_net_set.insert(net.get_net_idx()); + } + + DETask de_task; + de_task.set_process_type(DEProcessType::kMultiNet); + de_task.set_top_name(top_name); + de_task.set_check_region(check_region); + de_task.set_env_shape_list(env_shape_list); + de_task.set_net_pin_shape_map(net_pin_shape_map); + de_task.set_net_result_map(net_result_map); + de_task.set_net_patch_map(net_patch_map); + de_task.set_need_checked_net_set(need_checked_net_set); + for (Violation violation : getViolationList(de_task, false)) { + _ignore_violation_set.insert(violation); + } +} + std::vector DRCEngine::getViolationList(DETask& de_task) { - // return {}; - // return getViolationListBySelf(de_task); - return getViolationListByOther(de_task); + return getViolationList(de_task, true); } // private DRCEngine* DRCEngine::_de_instance = nullptr; -std::vector DRCEngine::getViolationListBySelf(DETask& de_task) +std::vector DRCEngine::getViolationList(DETask& de_task, bool post_process) +{ + getViolationListByInterface(de_task); + + // getViolationListBySelf(de_task); + filterViolationList(de_task); + if (post_process) { + fixViolationNetSet(de_task); + explandViolationList(de_task); + buildViolationList(de_task); + } + return de_task.get_violation_list(); +} + +void DRCEngine::getViolationListBySelf(DETask& de_task) { buildTask(de_task); writeTask(de_task); readTask(de_task); - return de_task.get_violation_list(); } void DRCEngine::buildTask(DETask& de_task) @@ -94,14 +180,13 @@ void DRCEngine::writeTask(DETask& de_task) std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); std::vector>& layer_via_master_list = RTDM.getDatabase().get_layer_via_master_list(); + std::map>& cut_to_adjacent_routing_map = RTDM.getDatabase().get_cut_to_adjacent_routing_map(); std::string& top_name = de_task.get_top_name(); std::vector>& env_shape_list = de_task.get_env_shape_list(); std::map>>& net_pin_shape_map = de_task.get_net_pin_shape_map(); - std::map*>>& net_env_result_map = de_task.get_net_env_result_map(); - std::map>& net_env_patch_map = de_task.get_net_env_patch_map(); - std::map>>& net_check_result_map = de_task.get_net_check_result_map(); - std::map>& net_check_patch_map = de_task.get_net_check_patch_map(); + std::map*>>& net_result_map = de_task.get_net_result_map(); + std::map>& net_patch_map = de_task.get_net_patch_map(); std::string& def_file_path = de_task.get_def_file_path(); std::string& netlist_file_path = de_task.get_netlist_file_path(); std::string& prepared_file_path = de_task.get_prepared_file_path(); @@ -109,19 +194,14 @@ void DRCEngine::writeTask(DETask& de_task) std::set net_idx_set; // 获取所有net { + net_idx_set.insert(-1); for (auto& [net_idx, pin_shape_list] : net_pin_shape_map) { net_idx_set.insert(net_idx); } - for (auto& [net_idx, segment_list] : net_env_result_map) { + for (auto& [net_idx, segment_list] : net_result_map) { net_idx_set.insert(net_idx); } - for (auto& [net_idx, patch_list] : net_env_patch_map) { - net_idx_set.insert(net_idx); - } - for (auto& [net_idx, segment_list] : net_check_result_map) { - net_idx_set.insert(net_idx); - } - for (auto& [net_idx, patch_list] : net_check_patch_map) { + for (auto& [net_idx, patch_list] : net_patch_map) { net_idx_set.insert(net_idx); } } @@ -146,122 +226,154 @@ void DRCEngine::writeTask(DETask& de_task) x_track_grid.get_step_length(), " LAYER ", routing_layer.get_layer_name(), " ;", "\n"); } RTUTIL.pushStream(def_file, "\n"); - // 构建blockage - RTUTIL.pushStream(def_file, "BLOCKAGES ", env_shape_list.size(), " ;", "\n"); - for (auto& [env_shape, is_routing] : env_shape_list) { - std::string layer_name; - if (is_routing) { - layer_name = routing_layer_list[env_shape->get_layer_idx()].get_layer_name(); + // 构建via + std::map cut_shape_via_map; + for (int32_t net_idx : net_idx_set) { + if (net_idx == -1) { + for (auto& [env_shape, is_routing] : env_shape_list) { + PlanarRect& real_rect = env_shape->get_real_rect(); + int32_t layer_idx = env_shape->get_layer_idx(); + PlanarCoord mid_point = real_rect.getMidPoint(); + if (!is_routing) { + if (cut_to_adjacent_routing_map[layer_idx].size() < 2) { + continue; + } + LayerRect cut_shape(real_rect.get_ll_x() - mid_point.get_x(), real_rect.get_ll_y() - mid_point.get_y(), + real_rect.get_ur_x() - mid_point.get_x(), real_rect.get_ur_y() - mid_point.get_y(), layer_idx); + cut_shape_via_map[cut_shape] = ""; + } + } } else { - layer_name = cut_layer_list[env_shape->get_layer_idx()].get_layer_name(); + if (RTUTIL.exist(net_pin_shape_map, net_idx)) { + for (auto& [pin_shape, is_routing] : net_pin_shape_map[net_idx]) { + PlanarRect& real_rect = pin_shape->get_real_rect(); + int32_t layer_idx = pin_shape->get_layer_idx(); + PlanarCoord mid_point = real_rect.getMidPoint(); + if (!is_routing) { + if (cut_to_adjacent_routing_map[layer_idx].size() < 2) { + continue; + } + LayerRect cut_shape(real_rect.get_ll_x() - mid_point.get_x(), real_rect.get_ll_y() - mid_point.get_y(), + real_rect.get_ur_x() - mid_point.get_x(), real_rect.get_ur_y() - mid_point.get_y(), layer_idx); + cut_shape_via_map[cut_shape] = ""; + } + } + } } - RTUTIL.pushStream(def_file, " - LAYER ", layer_name, " RECT ( ", env_shape->get_real_ll_x(), " ", env_shape->get_real_ll_y(), - " ) ( ", env_shape->get_real_ur_x(), " ", env_shape->get_real_ur_y(), " ) ;", "\n"); } - RTUTIL.pushStream(def_file, "END BLOCKAGES", "\n"); + RTUTIL.pushStream(def_file, "VIAS ", cut_shape_via_map.size(), " ;", "\n"); + for (auto& [cut_shape, via_name] : cut_shape_via_map) { + std::vector layer_name_list; + for (int32_t routing_layer_idx : cut_to_adjacent_routing_map[cut_shape.get_layer_idx()]) { + layer_name_list.push_back(routing_layer_list[routing_layer_idx].get_layer_name()); + } + layer_name_list.push_back(cut_layer_list[cut_shape.get_layer_idx()].get_layer_name()); + via_name = RTUTIL.getString("VIA_CUT_", cut_shape.get_layer_idx(), "_", cut_shape.get_ll_x(), "_", cut_shape.get_ll_y(), "_", + cut_shape.get_ur_x(), "_", cut_shape.get_ur_y()); + RTUTIL.pushStream(def_file, "- ", via_name, "\n"); + for (std::string& layer_name : layer_name_list) { + RTUTIL.pushStream(def_file, " + RECT ", layer_name, " ( ", cut_shape.get_ll_x(), " ", cut_shape.get_ll_y(), " ) ( ", + cut_shape.get_ur_x(), " ", cut_shape.get_ur_y(), " )", "\n"); + } + RTUTIL.pushStream(def_file, " ;", "\n"); + } + RTUTIL.pushStream(def_file, "END VIAS", "\n"); RTUTIL.pushStream(def_file, "\n"); // 构建net RTUTIL.pushStream(def_file, "NETS ", net_idx_set.size(), " ;", "\n"); for (int32_t net_idx : net_idx_set) { std::string flag = " + ROUTED"; - RTUTIL.pushStream(def_file, "- net_", net_idx, "\n"); - if (RTUTIL.exist(net_pin_shape_map, net_idx)) { - for (auto& [pin_shape, is_routing] : net_pin_shape_map[net_idx]) { - std::string layer_name; + if (net_idx == -1) { + RTUTIL.pushStream(def_file, "- net_blockage", "\n"); + for (auto& [env_shape, is_routing] : env_shape_list) { + PlanarRect& real_rect = env_shape->get_real_rect(); + int32_t layer_idx = env_shape->get_layer_idx(); + PlanarCoord mid_point = real_rect.getMidPoint(); if (is_routing) { - layer_name = routing_layer_list[pin_shape->get_layer_idx()].get_layer_name(); + RTUTIL.pushStream(def_file, flag, " ", routing_layer_list[layer_idx].get_layer_name(), " ( ", mid_point.get_x(), " ", + mid_point.get_y(), " ) RECT ( ", real_rect.get_ll_x() - mid_point.get_x(), " ", + real_rect.get_ll_y() - mid_point.get_y(), " ", real_rect.get_ur_x() - mid_point.get_x(), " ", + real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); + flag = " NEW"; } else { - layer_name = cut_layer_list[pin_shape->get_layer_idx()].get_layer_name(); - } - PlanarRect& real_rect = pin_shape->get_real_rect(); - PlanarCoord mid_point = real_rect.getMidPoint(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", mid_point.get_x(), " ", mid_point.get_y(), " ) RECT ( ", - real_rect.get_ll_x() - mid_point.get_x(), " ", real_rect.get_ll_y() - mid_point.get_y(), " ", - real_rect.get_ur_x() - mid_point.get_x(), " ", real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); - flag = " NEW"; - } - } - if (RTUTIL.exist(net_env_result_map, net_idx)) { - for (Segment* segment : net_env_result_map[net_idx]) { - LayerCoord& first_coord = segment->get_first(); - LayerCoord& second_coord = segment->get_second(); - int32_t first_layer_idx = first_coord.get_layer_idx(); - int32_t second_layer_idx = second_coord.get_layer_idx(); - if (first_layer_idx != second_layer_idx) { - RTUTIL.swapByASC(first_layer_idx, second_layer_idx); - for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { - ViaMaster& via_master = layer_via_master_list[layer_idx].front(); - std::string layer_name = routing_layer_list[via_master.get_above_enclosure().get_layer_idx()].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ", - via_master.get_via_name(), "\n"); - flag = " NEW"; - } - } else { - if (RTUTIL.isHorizontal(first_coord, second_coord)) { - std::string layer_name = routing_layer_list[first_layer_idx].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ( ", - second_coord.get_x(), " * )", "\n"); - flag = " NEW"; - } else if (RTUTIL.isVertical(first_coord, second_coord)) { - std::string layer_name = routing_layer_list[first_layer_idx].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ( * ", - second_coord.get_y(), " )", "\n"); + LayerRect cut_shape(real_rect.get_ll_x() - mid_point.get_x(), real_rect.get_ll_y() - mid_point.get_y(), + real_rect.get_ur_x() - mid_point.get_x(), real_rect.get_ur_y() - mid_point.get_y(), layer_idx); + if (RTUTIL.exist(cut_shape_via_map, cut_shape)) { + std::vector& routing_layer_idx_list = cut_to_adjacent_routing_map[layer_idx]; + int32_t routing_layer_idx = *std::min_element(routing_layer_idx_list.begin(), routing_layer_idx_list.end()); + RTUTIL.pushStream(def_file, flag, " ", routing_layer_list[routing_layer_idx].get_layer_name(), " ( ", mid_point.get_x(), " ", + mid_point.get_y(), " ) ", cut_shape_via_map[cut_shape], "\n"); flag = " NEW"; } } } - } - if (RTUTIL.exist(net_env_patch_map, net_idx)) { - for (EXTLayerRect* patch : net_env_patch_map[net_idx]) { - std::string layer_name = routing_layer_list[patch->get_layer_idx()].get_layer_name(); - PlanarRect& real_rect = patch->get_real_rect(); - PlanarCoord mid_point = real_rect.getMidPoint(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", mid_point.get_x(), " ", mid_point.get_y(), " ) RECT ( ", - real_rect.get_ll_x() - mid_point.get_x(), " ", real_rect.get_ll_y() - mid_point.get_y(), " ", - real_rect.get_ur_x() - mid_point.get_x(), " ", real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); - flag = " NEW"; - } - } - if (RTUTIL.exist(net_check_result_map, net_idx)) { - for (Segment segment : net_check_result_map[net_idx]) { - LayerCoord& first_coord = segment.get_first(); - LayerCoord& second_coord = segment.get_second(); - int32_t first_layer_idx = first_coord.get_layer_idx(); - int32_t second_layer_idx = second_coord.get_layer_idx(); - if (first_layer_idx != second_layer_idx) { - RTUTIL.swapByASC(first_layer_idx, second_layer_idx); - for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { - ViaMaster& via_master = layer_via_master_list[layer_idx].front(); - std::string layer_name = routing_layer_list[via_master.get_above_enclosure().get_layer_idx()].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ", - via_master.get_via_name(), "\n"); - flag = " NEW"; - } - } else { - if (RTUTIL.isHorizontal(first_coord, second_coord)) { - std::string layer_name = routing_layer_list[first_layer_idx].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ( ", - second_coord.get_x(), " * )", "\n"); - flag = " NEW"; - } else if (RTUTIL.isVertical(first_coord, second_coord)) { - std::string layer_name = routing_layer_list[first_layer_idx].get_layer_name(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ( * ", - second_coord.get_y(), " )", "\n"); + } else { + RTUTIL.pushStream(def_file, "- net_", net_idx, "\n"); + if (RTUTIL.exist(net_pin_shape_map, net_idx)) { + for (auto& [pin_shape, is_routing] : net_pin_shape_map[net_idx]) { + PlanarRect& real_rect = pin_shape->get_real_rect(); + int32_t layer_idx = pin_shape->get_layer_idx(); + PlanarCoord mid_point = real_rect.getMidPoint(); + if (is_routing) { + RTUTIL.pushStream(def_file, flag, " ", routing_layer_list[layer_idx].get_layer_name(), " ( ", mid_point.get_x(), " ", + mid_point.get_y(), " ) RECT ( ", real_rect.get_ll_x() - mid_point.get_x(), " ", + real_rect.get_ll_y() - mid_point.get_y(), " ", real_rect.get_ur_x() - mid_point.get_x(), " ", + real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); flag = " NEW"; + } else { + LayerRect cut_shape(real_rect.get_ll_x() - mid_point.get_x(), real_rect.get_ll_y() - mid_point.get_y(), + real_rect.get_ur_x() - mid_point.get_x(), real_rect.get_ur_y() - mid_point.get_y(), layer_idx); + if (RTUTIL.exist(cut_shape_via_map, cut_shape)) { + std::vector& routing_layer_idx_list = cut_to_adjacent_routing_map[layer_idx]; + int32_t routing_layer_idx = *std::min_element(routing_layer_idx_list.begin(), routing_layer_idx_list.end()); + RTUTIL.pushStream(def_file, flag, " ", routing_layer_list[routing_layer_idx].get_layer_name(), " ( ", mid_point.get_x(), + " ", mid_point.get_y(), " ) ", cut_shape_via_map[cut_shape], "\n"); + flag = " NEW"; + } } } } - } - if (RTUTIL.exist(net_check_patch_map, net_idx)) { - for (EXTLayerRect& patch : net_check_patch_map[net_idx]) { - std::string layer_name = routing_layer_list[patch.get_layer_idx()].get_layer_name(); - PlanarRect& real_rect = patch.get_real_rect(); - PlanarCoord mid_point = real_rect.getMidPoint(); - RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", mid_point.get_x(), " ", mid_point.get_y(), " ) RECT ( ", - real_rect.get_ll_x() - mid_point.get_x(), " ", real_rect.get_ll_y() - mid_point.get_y(), " ", - real_rect.get_ur_x() - mid_point.get_x(), " ", real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); - flag = " NEW"; + if (RTUTIL.exist(net_result_map, net_idx)) { + for (Segment* segment : net_result_map[net_idx]) { + LayerCoord& first_coord = segment->get_first(); + LayerCoord& second_coord = segment->get_second(); + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + if (first_layer_idx != second_layer_idx) { + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { + ViaMaster& via_master = layer_via_master_list[layer_idx].front(); + std::string layer_name = routing_layer_list[via_master.get_above_enclosure().get_layer_idx()].get_layer_name(); + RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", first_coord.get_x(), " ", first_coord.get_y(), " ) ", + via_master.get_via_name(), "\n"); + flag = " NEW"; + } + } else { + for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { + if (!net_shape.get_is_routing()) { + RTLOG.error(Loc::current(), "The net_shape is not routing!"); + } + std::string layer_name = routing_layer_list[net_shape.get_layer_idx()].get_layer_name(); + PlanarCoord mid_point = net_shape.getMidPoint(); + RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", mid_point.get_x(), " ", mid_point.get_y(), " ) RECT ( ", + net_shape.get_ll_x() - mid_point.get_x(), " ", net_shape.get_ll_y() - mid_point.get_y(), " ", + net_shape.get_ur_x() - mid_point.get_x(), " ", net_shape.get_ur_y() - mid_point.get_y(), " )", "\n"); + flag = " NEW"; + } + } + } + } + if (RTUTIL.exist(net_patch_map, net_idx)) { + for (EXTLayerRect* patch : net_patch_map[net_idx]) { + std::string layer_name = routing_layer_list[patch->get_layer_idx()].get_layer_name(); + PlanarRect& real_rect = patch->get_real_rect(); + PlanarCoord mid_point = real_rect.getMidPoint(); + RTUTIL.pushStream(def_file, flag, " ", layer_name, " ( ", mid_point.get_x(), " ", mid_point.get_y(), " ) RECT ( ", + real_rect.get_ll_x() - mid_point.get_x(), " ", real_rect.get_ll_y() - mid_point.get_y(), " ", + real_rect.get_ur_x() - mid_point.get_x(), " ", real_rect.get_ur_y() - mid_point.get_y(), " )", "\n"); + flag = " NEW"; + } } } RTUTIL.pushStream(def_file, " ;\n"); @@ -281,7 +393,11 @@ void DRCEngine::writeTask(DETask& de_task) RTUTIL.pushStream(netlist_file, "\n"); // 构建net for (int32_t net_idx : net_idx_set) { - RTUTIL.pushStream(netlist_file, "wire net_", net_idx, " ;", "\n"); + if (net_idx == -1) { + RTUTIL.pushStream(netlist_file, "wire net_blockage ;", "\n"); + } else { + RTUTIL.pushStream(netlist_file, "wire net_", net_idx, " ;", "\n"); + } } RTUTIL.pushStream(netlist_file, "\n"); // 构建footer @@ -300,11 +416,7 @@ void DRCEngine::writeTask(DETask& de_task) void DRCEngine::readTask(DETask& de_task) { int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); - ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); std::map& routing_layer_name_to_idx_map = RTDM.getDatabase().get_routing_layer_name_to_idx_map(); - std::map>& routing_to_adjacent_cut_map = RTDM.getDatabase().get_routing_to_adjacent_cut_map(); - - std::map& violation_process_map = getViolationProcessMap(); std::string& top_name = de_task.get_top_name(); std::string& finished_file_path = de_task.get_finished_file_path(); @@ -326,91 +438,67 @@ void DRCEngine::readTask(DETask& de_task) std::ifstream* violation_file = RTUTIL.getInputFileStream(violation_file_path); std::string new_line; - std::string drc_rule_name; - std::set net_name_set; - std::string layer_name; - std::string ll_x_string; - std::string ll_y_string; - std::string ur_x_string; - std::string ur_y_string; while (std::getline(*violation_file, new_line)) { if (new_line.empty()) { continue; } + std::set net_name_set; + std::string required; + std::string drc_rule_name; + std::string layer_name; + std::string ll_x_string; + std::string ll_y_string; + std::string ur_x_string; + std::string ur_y_string; // 读取 - { - drc_rule_name = new_line; - std::getline(*violation_file, new_line); - std::istringstream net_name_set_stream(new_line); - std::string net_name; - while (std::getline(net_name_set_stream, net_name, ',')) { - if (!net_name.empty()) { - net_name_set.insert(net_name); - } + std::istringstream net_name_set_stream(new_line); + std::string net_name; + while (std::getline(net_name_set_stream, net_name, ',')) { + if (!net_name.empty()) { + net_name_set.insert(net_name); } - std::getline(*violation_file, new_line); - std::istringstream layer_bound_stream(new_line); - layer_bound_stream >> layer_name >> ll_x_string >> ll_y_string >> ur_x_string >> ur_y_string; } + std::getline(*violation_file, new_line); + std::istringstream drc_info_stream(new_line); + drc_info_stream >> required >> drc_rule_name; + std::getline(*violation_file, new_line); + std::istringstream shape_stream(new_line); + shape_stream >> layer_name >> ll_x_string >> ll_y_string >> ur_x_string >> ur_y_string; // 解析 - { - ViolationType violation_type = GetViolationTypeByName()(drc_rule_name); - if (!RTUTIL.exist(violation_process_map, violation_type)) { - // 未知规则舍弃 - RTLOG.warn(Loc::current(), "Unknow rule! '", drc_rule_name, "'"); - continue; - } - DEProcessType process_type = violation_process_map[violation_type]; - if (!RTUTIL.exist(de_task.get_process_type_set(), process_type)) { - // 非处理类型舍弃 - continue; - } - PlanarRect real_rect(static_cast(std::round(std::stod(ll_x_string) * micron_dbu)), - static_cast(std::round(std::stod(ll_y_string) * micron_dbu)), - static_cast(std::round(std::stod(ur_x_string) * micron_dbu)), - static_cast(std::round(std::stod(ur_y_string) * micron_dbu))); - if (!RTUTIL.isOverlap(de_task.get_check_region(), real_rect)) { - // 不在检查区域内的舍弃 - continue; - } - std::set violation_net_set; - for (const std::string& net_name : net_name_set) { - int32_t net_idx = std::stoi(RTUTIL.splitString(net_name, '_').back()); - if (net_idx == -1 || RTUTIL.exist(de_task.get_net_check_result_map(), net_idx) - || RTUTIL.exist(de_task.get_net_check_patch_map(), net_idx)) { - violation_net_set.insert(net_idx); - } - } - if (violation_net_set.empty() || (violation_net_set.size() == 1 && *violation_net_set.begin() == -1)) { - // net不是布线net的舍弃 - continue; - } - std::vector> layer_routing_list; - int32_t routing_layer_idx = routing_layer_name_to_idx_map[layer_name]; - layer_routing_list.emplace_back(routing_layer_idx, true); - if (process_type == DEProcessType::kCutCost) { - for (int32_t cut_layer_idx : routing_to_adjacent_cut_map[routing_layer_idx]) { - layer_routing_list.emplace_back(cut_layer_idx, false); - } - } - if (false) { - // 因为不可布线层需要打via,对于不在可布线层的违例也有意义 - continue; - } - for (std::pair layer_routing : layer_routing_list) { - EXTLayerRect ext_layer_rect; - ext_layer_rect.set_real_rect(real_rect); - ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); - ext_layer_rect.set_layer_idx(layer_routing.first); - - Violation violation; - violation.set_violation_type(violation_type); - violation.set_violation_shape(ext_layer_rect); - violation.set_is_routing(layer_routing.second); - violation.set_violation_net_set(violation_net_set); - de_task.get_violation_list().push_back(violation); + ViolationType violation_type = GetViolationTypeByName()(drc_rule_name); + if (violation_type == ViolationType::kNone) { + RTLOG.warn(Loc::current(), "Unknow rule! '", drc_rule_name, "'"); + } + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_ll(static_cast(std::round(std::stod(ll_x_string) * micron_dbu)), + static_cast(std::round(std::stod(ll_y_string) * micron_dbu))); + ext_layer_rect.set_real_ur(static_cast(std::round(std::stod(ur_x_string) * micron_dbu)), + static_cast(std::round(std::stod(ur_y_string) * micron_dbu))); + ext_layer_rect.set_layer_idx(routing_layer_name_to_idx_map[layer_name]); + std::set violation_net_set; + for (const std::string& net_name : net_name_set) { + if (net_name == "net_blockage") { + violation_net_set.insert(-1); + } else { + violation_net_set.insert(std::stoi(RTUTIL.splitString(net_name, '_').back())); } } + if (violation_net_set.size() > 2) { + RTLOG.error(Loc::current(), "The violation_net_set size > 2!"); + } + int32_t required_size; + if (required == "null") { + required_size = 0; + } else { + required_size = static_cast(std::round(std::stod(required) * micron_dbu)); + } + Violation violation; + violation.set_violation_type(violation_type); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set(violation_net_set); + violation.set_required_size(required_size); + de_task.get_violation_list().push_back(violation); } RTUTIL.closeFileStream(violation_file); } else { @@ -420,64 +508,412 @@ void DRCEngine::readTask(DETask& de_task) RTUTIL.removeDir(de_task.get_top_dir_path()); } -std::map& DRCEngine::getViolationProcessMap() -{ - static std::map violation_process_map; - static std::once_flag init_flag; - - std::call_once(init_flag, []() { - /** -   * skip             暂时无法处理的规则 -   * routing_cost     routing层加cost -   * cut_cost         cut层及相邻两routing层加cost -   * routing_patch    routing层加patch -   */ - // skip - violation_process_map[ViolationType::kFloatingPatch] = DEProcessType::kSkip; // 由于cell没有加载,所以pin shape属于漂浮 - violation_process_map[ViolationType::kOffGridOrWrongWay] = DEProcessType::kSkip; // 不在track上的布线结果 - violation_process_map[ViolationType::kMinimumWidth] = DEProcessType::kSkip; // 最小宽度违例,实际上是Floating Patch的最小宽度 - violation_process_map[ViolationType::kMinimumCut] = DEProcessType::kSkip; // 对一些时钟树net需要多cut - violation_process_map[ViolationType::kOutOfDie] = DEProcessType::kSkip; // shape超出die - // - violation_process_map[ViolationType::kEnclosureParallel] = DEProcessType::kSkip; // enclosure与merge的shepe的spacing - violation_process_map[ViolationType::kEnclosureEdge] = DEProcessType::kSkip; // enclosure与merge的shepe的spacing - violation_process_map[ViolationType::kEnclosure] = DEProcessType::kSkip; // enclosure与merge的shepe的spacing - violation_process_map[ViolationType::kMinHole] = DEProcessType::kSkip; // 围起的hole面积太小 - violation_process_map[ViolationType::kNotchSpacing] = DEProcessType::kSkip; // - violation_process_map[ViolationType::kCornerFillSpacing] = DEProcessType::kSkip; // - violation_process_map[ViolationType::kNonsufficientMetalOverlap] = DEProcessType::kSkip; // 同net的wire边碰一起 - // routing_cost - violation_process_map[ViolationType::kMetalShort] = DEProcessType::kRoutingCost; // 短路,不同一个net - violation_process_map[ViolationType::kParallelRunLengthSpacing] = DEProcessType::kRoutingCost; // 平行线spacing - violation_process_map[ViolationType::kEndOfLineSpacing] = DEProcessType::kRoutingCost; // EOL spacing - // cut_cost - violation_process_map[ViolationType::kCutEOLSpacing] = DEProcessType::kCutCost; // EOL spacing - violation_process_map[ViolationType::kCutShort] = DEProcessType::kCutCost; // 短路 - violation_process_map[ViolationType::kDifferentLayerCutSpacing] = DEProcessType::kCutCost; // 不同层的cut spacing问题 - violation_process_map[ViolationType::kSameLayerCutSpacing] = DEProcessType::kCutCost; // 同层的cut spacing问题 - violation_process_map[ViolationType::kMaxViaStack] = DEProcessType::kCutCost; // 叠的通孔太多了 - // routing_patch - violation_process_map[ViolationType::kMinStep] = DEProcessType::kRoutingPatch; // 金属层min step - violation_process_map[ViolationType::kMinimumArea] = DEProcessType::kRoutingPatch; // 金属层面积过小 - }); - - return violation_process_map; -} - -std::vector DRCEngine::getViolationListByOther(DETask& de_task) +void DRCEngine::getViolationListByInterface(DETask& de_task) { std::map>> net_result_map; - for (auto& [net_idx, segment_list] : de_task.get_net_env_result_map()) { + for (auto& [net_idx, segment_list] : de_task.get_net_result_map()) { for (Segment* segment : segment_list) { net_result_map[net_idx].push_back(*segment); } } - for (auto& [net_idx, segment_list] : de_task.get_net_check_result_map()) { - for (Segment& segment : segment_list) { - net_result_map[net_idx].push_back(segment); + for (auto& [net_idx, segment_list] : de_task.get_net_result_map()) { + for (Segment* segment : segment_list) { + net_result_map[net_idx].push_back(*segment); } } - return RTI.getViolationList(de_task.get_env_shape_list(), de_task.get_net_pin_shape_map(), net_result_map); + de_task.set_violation_list(RTI.getViolationList(de_task.get_env_shape_list(), de_task.get_net_pin_shape_map(), net_result_map)); + for (Violation& violation : de_task.get_violation_list()) { + violation.set_violation_type(ViolationType::kParallelRunLengthSpacing); + } } +void DRCEngine::filterViolationList(DETask& de_task) +{ + std::vector new_violation_list; + for (Violation& violation : de_task.get_violation_list()) { + if (violation.get_violation_type() == ViolationType::kNone) { + // 未知规则舍弃 + continue; + } + if (skipViolation(violation)) { + // 跳过的类型舍弃 + continue; + } + PlanarRect& real_rect = violation.get_violation_shape().get_real_rect(); + if (!RTUTIL.isOverlap(de_task.get_check_region(), real_rect)) { + // 不在检查区域内的舍弃 + continue; + } + std::set& violation_net_set = violation.get_violation_net_set(); + { + // 构建违例net + std::set new_violation_net_set; + for (int32_t violation_net_idx : violation_net_set) { + if (violation_net_idx == -1 || RTUTIL.exist(de_task.get_need_checked_net_set(), violation_net_idx)) { + new_violation_net_set.insert(violation_net_idx); + } + } + violation_net_set = new_violation_net_set; + } + if (violation_net_set.empty() || (violation_net_set.size() == 1 && *violation_net_set.begin() == -1)) { + // net不是布线net的舍弃 + continue; + } + if (de_task.get_process_type() == DEProcessType::kSingleNet && violation_net_set.size() > 1) { + continue; + } + if (de_task.get_process_type() == DEProcessType::kMultiNet && violation_net_set.size() < 2) { + continue; + } + if (RTUTIL.exist(_ignore_violation_set, violation)) { + // 自带的违例舍弃 + continue; + } + new_violation_list.push_back(violation); + } + de_task.set_violation_list(new_violation_list); +} + +void DRCEngine::fixViolationNetSet(DETask& de_task) +{ + // { + // for (Violation& violation : pa_box.get_violation_list()) { + // std::map>& cut_to_adjacent_routing_map = RTDM.getDatabase().get_cut_to_adjacent_routing_map(); + + // std::vector searched_rect_list; + // { + // EXTLayerRect& violation_shape = violation.get_violation_shape(); + // PlanarRect enlarged_rect = RTUTIL.getEnlargedRect(violation_shape.get_real_rect(), RTDM.getOnlyPitch()); + // if (violation.get_is_routing()) { + // searched_rect_list.emplace_back(enlarged_rect, violation_shape.get_layer_idx()); + // } else { + // for (int32_t layer_idx : cut_to_adjacent_routing_map[violation_shape.get_layer_idx()]) { + // searched_rect_list.emplace_back(enlarged_rect, layer_idx); + // } + // } + // } + // std::set violation_net_set; + // for (auto& [net_idx, task_result_map] : pa_box.get_net_task_result_map()) { + // for (auto& [task_idx, segment_list] : task_result_map) { + // for (Segment& segment : segment_list) { + // for (LayerRect& searched_rect : searched_rect_list) { + // if (!RTUTIL.isOverlap(searched_rect, segment)) { + // continue; + // } + // violation_net_set.insert(net_idx); + // if (violation_net_set.size() >= 2) { + // break; + // } + // } + // } + // } + // } + // violation.set_violation_net_set(violation_net_set); + // } + // } +} + +void DRCEngine::explandViolationList(DETask& de_task) +{ + std::vector new_violation_list; + for (Violation& violation : de_task.get_violation_list()) { + for (Violation new_violation : expandViolation(violation)) { + new_violation_list.push_back(new_violation); + } + } + de_task.set_violation_list(new_violation_list); +} + +void DRCEngine::buildViolationList(DETask& de_task) +{ + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + + for (Violation& violation : de_task.get_violation_list()) { + EXTLayerRect& violation_shape = violation.get_violation_shape(); + violation_shape.set_grid_rect(RTUTIL.getClosedGCellGridRect(violation_shape.get_real_rect(), gcell_axis)); + } +} + +#if 1 // aux + +bool DRCEngine::skipViolation(Violation& violation) +{ + std::string skip_violation; + std::vector expanded_violation_list; + buildByFunc(violation, DEFuncType::kSkipViolation, skip_violation, expanded_violation_list); + return (skip_violation == "skip"); +} + +std::vector DRCEngine::expandViolation(Violation& violation) +{ + std::string skip_violation; + std::vector expanded_violation_list; + buildByFunc(violation, DEFuncType::kExpandViolation, skip_violation, expanded_violation_list); + return expanded_violation_list; +} + +void DRCEngine::buildByFunc(Violation& violation, const DEFuncType& de_func_type, std::string& need_skip, + std::vector& expanded_violation_list) +{ + if (de_func_type == DEFuncType::kNone) { + RTLOG.error(Loc::current(), "The de_func_type is none!"); + } + PlanarRect real_rect = violation.get_violation_shape().get_real_rect(); + std::vector> layer_routing_list; + switch (violation.get_violation_type()) { + case ViolationType::kAdjacentCutSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kCornerFillSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kCutEOLSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandUpOneLayer(violation); + } + break; + case ViolationType::kCutShort: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandUpOneLayer(violation); + } + break; + case ViolationType::kDifferentLayerCutSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandUpTwoLayer(violation); + } + break; + case ViolationType::kEndOfLineSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kEnclosure: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kEnclosureEdge: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kEnclosureParallel: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kFloatingPatch: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kJogToJogSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kMaxViaStack: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, 0); + layer_routing_list = expandUpOneLayer(violation); + } + break; + case ViolationType::kMetalShort: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kMinHole: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, std::ceil(std::sqrt(violation.get_required_size()))); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kMinimumArea: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kMinimumCut: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kMinimumWidth: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kMinStep: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kNonsufficientMetalOverlap: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kNotchSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kOffGridOrWrongWay: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kOutOfDie: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "skip"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + RTLOG.error(Loc::current(), "This is skipping!"); + } + break; + case ViolationType::kParallelRunLengthSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandAdjacentOneLayer(violation); + } + break; + case ViolationType::kSameLayerCutSpacing: + if (de_func_type == DEFuncType::kSkipViolation) { + need_skip = "attend"; + } else if (de_func_type == DEFuncType::kExpandViolation) { + real_rect = enlargeRect(real_rect, violation.get_required_size()); + layer_routing_list = expandUpOneLayer(violation); + } + break; + default: + RTLOG.error(Loc::current(), "No violation type!"); + break; + } + for (std::pair& layer_routing : layer_routing_list) { + Violation expanded_violation = violation; + expanded_violation.get_violation_shape().set_real_rect(real_rect); + expanded_violation.get_violation_shape().set_layer_idx(layer_routing.first); + expanded_violation.set_is_routing(layer_routing.second); + expanded_violation_list.push_back(expanded_violation); + } +} + +PlanarRect DRCEngine::enlargeRect(PlanarRect& real_rect, int32_t required_size) +{ + int32_t enlarged_x_size = 0; + if (real_rect.getXSpan() < required_size) { + enlarged_x_size = required_size - real_rect.getXSpan(); + } + int32_t enlarged_y_size = 0; + if (real_rect.getYSpan() < required_size) { + enlarged_y_size = required_size - real_rect.getYSpan(); + } + return RTUTIL.getEnlargedRect(real_rect, enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); +} + +std::vector> DRCEngine::expandAdjacentOneLayer(Violation& violation) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + + int32_t violation_layer_idx = violation.get_violation_shape().get_layer_idx(); + + std::vector> layer_routing_list; + layer_routing_list.emplace_back(violation_layer_idx, true); + if (0 < violation_layer_idx) { + layer_routing_list.emplace_back(violation_layer_idx - 1, true); + } + if (violation_layer_idx < (static_cast(routing_layer_list.size()) - 1)) { + layer_routing_list.emplace_back(violation_layer_idx + 1, true); + } + return layer_routing_list; +} + +std::vector> DRCEngine::expandUpOneLayer(Violation& violation) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + + int32_t violation_layer_idx = violation.get_violation_shape().get_layer_idx(); + + std::vector> layer_routing_list; + layer_routing_list.emplace_back(violation_layer_idx, true); + if (violation_layer_idx < (static_cast(routing_layer_list.size()) - 1)) { + layer_routing_list.emplace_back(violation_layer_idx + 1, true); + } + return layer_routing_list; +} + +std::vector> DRCEngine::expandUpTwoLayer(Violation& violation) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + + int32_t violation_layer_idx = violation.get_violation_shape().get_layer_idx(); + + std::vector> layer_routing_list; + layer_routing_list.emplace_back(violation_layer_idx, true); + if (violation_layer_idx < (static_cast(routing_layer_list.size()) - 1)) { + layer_routing_list.emplace_back(violation_layer_idx + 1, true); + } + if (violation_layer_idx < (static_cast(routing_layer_list.size()) - 2)) { + layer_routing_list.emplace_back(violation_layer_idx + 2, true); + } + return layer_routing_list; +} + +#endif + } // namespace irt diff --git a/src/operation/iRT/source/module/drc_engine/DRCEngine.hpp b/src/operation/iRT/source/module/drc_engine/DRCEngine.hpp index 91f39fc4e..b992f7352 100644 --- a/src/operation/iRT/source/module/drc_engine/DRCEngine.hpp +++ b/src/operation/iRT/source/module/drc_engine/DRCEngine.hpp @@ -17,6 +17,7 @@ #pragma once #include "Config.hpp" +#include "DEFuncType.hpp" #include "DETask.hpp" #include "DataManager.hpp" #include "Database.hpp" @@ -33,11 +34,14 @@ class DRCEngine static DRCEngine& getInst(); static void destroyInst(); // function + void init(); + void updateIgnoreViolationSet(); std::vector getViolationList(DETask& de_task); private: // self static DRCEngine* _de_instance; + std::set _ignore_violation_set; DRCEngine() = default; DRCEngine(const DRCEngine& other) = delete; @@ -46,12 +50,27 @@ class DRCEngine DRCEngine& operator=(const DRCEngine& other) = delete; DRCEngine& operator=(DRCEngine&& other) = delete; // function - std::vector getViolationListBySelf(DETask& de_task); + std::vector getViolationList(DETask& de_task, bool post_process); + void getViolationListBySelf(DETask& de_task); void buildTask(DETask& de_task); void writeTask(DETask& de_task); void readTask(DETask& de_task); - std::map& getViolationProcessMap(); - std::vector getViolationListByOther(DETask& de_task); + void getViolationListByInterface(DETask& de_task); + void filterViolationList(DETask& de_task); + void fixViolationNetSet(DETask& de_task); + void explandViolationList(DETask& de_task); + void buildViolationList(DETask& de_task); + +#if 1 // aux + bool skipViolation(Violation& violation); + std::vector expandViolation(Violation& violation); + void buildByFunc(Violation& violation, const DEFuncType& de_func_type, std::string& need_skip, + std::vector& expanded_violation_list); + PlanarRect enlargeRect(PlanarRect& real_rect, int32_t required_size); + std::vector> expandAdjacentOneLayer(Violation& violation); + std::vector> expandUpOneLayer(Violation& violation); + std::vector> expandUpTwoLayer(Violation& violation); +#endif }; } // namespace irt diff --git a/src/operation/iRT/source/module/drc_engine/de_data_manager/DEFuncType.hpp b/src/operation/iRT/source/module/drc_engine/de_data_manager/DEFuncType.hpp new file mode 100644 index 000000000..5bc92e6bd --- /dev/null +++ b/src/operation/iRT/source/module/drc_engine/de_data_manager/DEFuncType.hpp @@ -0,0 +1,53 @@ +// *************************************************************************************** +// 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 "Logger.hpp" + +namespace irt { + +enum class DEFuncType +{ + kNone, + kSkipViolation, + kExpandViolation +}; + +struct GetDEFuncTypeName +{ + std::string operator()(const DEFuncType& process_type) const + { + std::string process_type_name; + switch (process_type) { + case DEFuncType::kNone: + process_type_name = "none"; + break; + case DEFuncType::kSkipViolation: + process_type_name = "skip_violation"; + break; + case DEFuncType::kExpandViolation: + process_type_name = "expand_violation"; + break; + default: + RTLOG.error(Loc::current(), "Unrecognized type!"); + break; + } + return process_type_name; + } +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/drc_engine/de_data_manager/DEProcessType.hpp b/src/operation/iRT/source/module/drc_engine/de_data_manager/DEProcessType.hpp index c770cdffe..4171fbcea 100644 --- a/src/operation/iRT/source/module/drc_engine/de_data_manager/DEProcessType.hpp +++ b/src/operation/iRT/source/module/drc_engine/de_data_manager/DEProcessType.hpp @@ -23,10 +23,8 @@ namespace irt { enum class DEProcessType { kNone, - kSkip, - kRoutingCost, - kCutCost, - kRoutingPatch + kSingleNet, + kMultiNet }; struct GetDEProcessTypeName @@ -38,17 +36,11 @@ struct GetDEProcessTypeName case DEProcessType::kNone: process_type_name = "none"; break; - case DEProcessType::kSkip: - process_type_name = "skip"; + case DEProcessType::kSingleNet: + process_type_name = "single_net"; break; - case DEProcessType::kRoutingCost: - process_type_name = "routing_cost"; - break; - case DEProcessType::kCutCost: - process_type_name = "cut_cost"; - break; - case DEProcessType::kRoutingPatch: - process_type_name = "routing_patch"; + case DEProcessType::kMultiNet: + process_type_name = "multi_net"; break; default: RTLOG.error(Loc::current(), "Unrecognized type!"); diff --git a/src/operation/iRT/source/module/drc_engine/de_data_manager/DETask.hpp b/src/operation/iRT/source/module/drc_engine/de_data_manager/DETask.hpp index f0e663d0b..71b1ac66d 100644 --- a/src/operation/iRT/source/module/drc_engine/de_data_manager/DETask.hpp +++ b/src/operation/iRT/source/module/drc_engine/de_data_manager/DETask.hpp @@ -28,15 +28,14 @@ class DETask DETask() = default; ~DETask() = default; // getter - std::set& get_process_type_set() { return _process_type_set; } + DEProcessType& get_process_type() { return _process_type; } std::string& get_top_name() { return _top_name; } PlanarRect& get_check_region() { return _check_region; } std::vector>& get_env_shape_list() { return _env_shape_list; } std::map>>& get_net_pin_shape_map() { return _net_pin_shape_map; } - std::map*>>& get_net_env_result_map() { return _net_env_result_map; } - std::map>& get_net_env_patch_map() { return _net_env_patch_map; } - std::map>>& get_net_check_result_map() { return _net_check_result_map; } - std::map>& get_net_check_patch_map() { return _net_check_patch_map; } + std::map*>>& get_net_result_map() { return _net_result_map; } + std::map>& get_net_patch_map() { return _net_patch_map; } + std::set& get_need_checked_net_set() { return _need_checked_net_set; } std::string& get_top_dir_path() { return _top_dir_path; } std::string& get_def_file_path() { return _def_file_path; } std::string& get_netlist_file_path() { return _netlist_file_path; } @@ -45,7 +44,7 @@ class DETask std::string& get_violation_file_path() { return _violation_file_path; } std::vector& get_violation_list() { return _violation_list; } // setter - void set_process_type_set(const std::set& process_type_set) { _process_type_set = process_type_set; } + void set_process_type(const DEProcessType& process_type) { _process_type = process_type; } void set_top_name(const std::string& top_name) { _top_name = top_name; } void set_check_region(const PlanarRect& check_region) { _check_region = check_region; } void set_env_shape_list(const std::vector>& env_shape_list) { _env_shape_list = env_shape_list; } @@ -53,22 +52,9 @@ class DETask { _net_pin_shape_map = net_pin_shape_map; } - void set_net_env_result_map(const std::map*>>& net_env_result_map) - { - _net_env_result_map = net_env_result_map; - } - void set_net_env_patch_map(const std::map>& net_env_patch_map) - { - _net_env_patch_map = net_env_patch_map; - } - void set_net_check_result_map(const std::map>>& net_check_result_map) - { - _net_check_result_map = net_check_result_map; - } - void set_net_check_patch_map(const std::map>& net_check_patch_map) - { - _net_check_patch_map = net_check_patch_map; - } + void set_net_result_map(const std::map*>>& net_result_map) { _net_result_map = net_result_map; } + void set_net_patch_map(const std::map>& net_patch_map) { _net_patch_map = net_patch_map; } + void set_need_checked_net_set(const std::set& need_checked_net_set) { _need_checked_net_set = need_checked_net_set; } void set_top_dir_path(const std::string& top_dir_path) { _top_dir_path = top_dir_path; } void set_def_file_path(const std::string& def_file_path) { _def_file_path = def_file_path; } void set_netlist_file_path(const std::string& netlist_file_path) { _netlist_file_path = netlist_file_path; } @@ -78,15 +64,14 @@ class DETask void set_violation_list(const std::vector& violation_list) { _violation_list = violation_list; } // function private: - std::set _process_type_set; + DEProcessType _process_type; std::string _top_name; PlanarRect _check_region; std::vector> _env_shape_list; std::map>> _net_pin_shape_map; - std::map*>> _net_env_result_map; - std::map> _net_env_patch_map; - std::map>> _net_check_result_map; - std::map> _net_check_patch_map; + std::map*>> _net_result_map; + std::map> _net_patch_map; + std::set _need_checked_net_set; std::string _top_dir_path; std::string _def_file_path; std::string _netlist_file_path; diff --git a/src/operation/iRT/source/module/early_router/CMakeLists.txt b/src/operation/iRT/source/module/early_router/CMakeLists.txt new file mode 100644 index 000000000..9716aecce --- /dev/null +++ b/src/operation/iRT/source/module/early_router/CMakeLists.txt @@ -0,0 +1,25 @@ +if(DEBUG_IRT_EARLY_ROUTER) + message(STATUS "RT: DEBUG_IRT_EARLY_ROUTER") + set(CMAKE_BUILD_TYPE "Debug") +else() + message(STATUS "RT: RELEASE_IRT_EARLY_ROUTER") + set(CMAKE_BUILD_TYPE "Release") +endif() + +add_library(irt_early_router + ## module early_router + ${IRT_MODULE}/early_router/EarlyRouter.cpp +) + +target_link_libraries(irt_early_router + PUBLIC + irt_data_manager + irt_module + irt_toolkit +) + +target_include_directories(irt_early_router + PUBLIC + ${IRT_MODULE}/early_router/er_data_manager + ${IRT_MODULE}/early_router +) diff --git a/src/operation/iRT/source/module/early_router/EarlyRouter.cpp b/src/operation/iRT/source/module/early_router/EarlyRouter.cpp new file mode 100644 index 000000000..98d688a59 --- /dev/null +++ b/src/operation/iRT/source/module/early_router/EarlyRouter.cpp @@ -0,0 +1,1638 @@ +// *************************************************************************************** +// 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 "EarlyRouter.hpp" + +#include "GDSPlotter.hpp" +#include "Monitor.hpp" +#include "RTInterface.hpp" +#include "Utility.hpp" + +namespace irt { + +// public + +void EarlyRouter::initInst() +{ + if (_er_instance == nullptr) { + _er_instance = new EarlyRouter(); + } +} + +EarlyRouter& EarlyRouter::getInst() +{ + if (_er_instance == nullptr) { + RTLOG.error(Loc::current(), "The instance not initialized!"); + } + return *_er_instance; +} + +void EarlyRouter::destroyInst() +{ + if (_er_instance != nullptr) { + delete _er_instance; + _er_instance = nullptr; + } +} + +// function + +void EarlyRouter::route() +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + ERModel er_model = initERModel(); + setERParameter(er_model); + generateAccessPoint(er_model); + initERTaskList(er_model); + buildPlanarNodeMap(er_model); + buildPlanarNodeNeighbor(er_model); + buildPlanarOrientSupply(er_model); + // debugCheckPlanarNodeMap(er_model); + generateTopoTree(er_model); + buildLayerNodeMap(er_model); + buildLayerNodeNeighbor(er_model); + buildLayerOrientSupply(er_model); + // debugCheckLayerNodeMap(er_model); + generateGlobalTree(er_model); + updateSummary(er_model); + printSummary(er_model); + outputGuide(er_model); + outputDemandCSV(er_model); + outputOverflowCSV(er_model); + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +// private + +EarlyRouter* EarlyRouter::_er_instance = nullptr; + +ERModel EarlyRouter::initERModel() +{ + std::vector& net_list = RTDM.getDatabase().get_net_list(); + + ERModel er_model; + er_model.set_er_net_list(convertToERNetList(net_list)); + return er_model; +} + +std::vector EarlyRouter::convertToERNetList(std::vector& net_list) +{ + std::vector er_net_list; + er_net_list.reserve(net_list.size()); + for (size_t i = 0; i < net_list.size(); i++) { + er_net_list.emplace_back(convertToERNet(net_list[i])); + } + return er_net_list; +} + +ERNet EarlyRouter::convertToERNet(Net& net) +{ + ERNet er_net; + er_net.set_origin_net(&net); + er_net.set_net_idx(net.get_net_idx()); + er_net.set_connect_type(net.get_connect_type()); + for (Pin& pin : net.get_pin_list()) { + er_net.get_er_pin_list().push_back(ERPin(pin)); + } + er_net.set_bounding_box(net.get_bounding_box()); + return er_net; +} + +void EarlyRouter::setERParameter(ERModel& er_model) +{ + int32_t topo_spilt_length = 10; + double congestion_unit = 2; + double prefer_wire_unit = 1; + double via_unit = 1; + /** + * topo_spilt_length, congestion_unit, prefer_wire_unit, via_unit + */ + // clang-format off + ERParameter er_parameter(topo_spilt_length, congestion_unit, prefer_wire_unit, via_unit); + // clang-format on + RTLOG.info(Loc::current(), "topo_spilt_length: ", er_parameter.get_topo_spilt_length()); + RTLOG.info(Loc::current(), "congestion_unit: ", er_parameter.get_congestion_unit()); + RTLOG.info(Loc::current(), "prefer_wire_unit: ", er_parameter.get_prefer_wire_unit()); + RTLOG.info(Loc::current(), "via_unit: ", er_parameter.get_via_unit()); + er_model.set_er_parameter(er_parameter); +} + +void EarlyRouter::generateAccessPoint(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + + std::vector& er_net_list = er_model.get_er_net_list(); + + for (ERNet& er_net : er_net_list) { + for (ERPin& er_pin : er_net.get_er_pin_list()) { + std::vector& routing_shape_list = er_pin.get_routing_shape_list(); + + LayerCoord layer_coord; + { + int32_t max_area = INT32_MIN; + LayerRect max_area_shape = routing_shape_list.front().getRealLayerRect(); + for (EXTLayerRect& routing_shape : er_pin.get_routing_shape_list()) { + PlanarRect& real_shape = routing_shape.get_real_rect(); + if (max_area < real_shape.getArea()) { + max_area = real_shape.getArea(); + max_area_shape.set_rect(real_shape); + } + } + layer_coord.set_coord(max_area_shape.getMidPoint()); + layer_coord.set_layer_idx(max_area_shape.get_layer_idx()); + } + er_pin.set_access_point(AccessPoint(er_pin.get_pin_idx(), layer_coord, AccessPointType::kNoAccess)); + } + + std::vector 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(); + access_point.set_grid_coord(RTUTIL.getGCellGridCoordByBBox(access_point.get_real_coord(), gcell_axis, bounding_box)); + } + } + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::initERTaskList(ERModel& er_model) +{ + std::vector& er_net_list = er_model.get_er_net_list(); + std::vector& er_task_list = er_model.get_er_task_list(); + er_task_list.reserve(er_net_list.size()); + for (ERNet& er_net : er_net_list) { + er_task_list.push_back(&er_net); + } + std::sort(er_task_list.begin(), er_task_list.end(), CmpERNet()); +} + +void EarlyRouter::buildPlanarNodeMap(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + GridMap& planar_node_map = er_model.get_planar_node_map(); + planar_node_map.init(gcell_map.get_x_size(), gcell_map.get_y_size()); +#pragma omp parallel for collapse(2) + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + ERNode& er_node = planar_node_map[x][y]; + er_node.set_coord(x, y); + } + } + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::buildPlanarNodeNeighbor(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + + GridMap& planar_node_map = er_model.get_planar_node_map(); +#pragma omp parallel for collapse(2) + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + std::map& neighbor_node_map = planar_node_map[x][y].get_neighbor_node_map(); + if (x != 0) { + neighbor_node_map[Orientation::kWest] = &planar_node_map[x - 1][y]; + } + if (x != (planar_node_map.get_x_size() - 1)) { + neighbor_node_map[Orientation::kEast] = &planar_node_map[x + 1][y]; + } + if (y != 0) { + neighbor_node_map[Orientation::kSouth] = &planar_node_map[x][y - 1]; + } + if (y != (planar_node_map.get_y_size() - 1)) { + neighbor_node_map[Orientation::kNorth] = &planar_node_map[x][y + 1]; + } + } + } + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::buildPlanarOrientSupply(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + GridMap& planar_node_map = er_model.get_planar_node_map(); + +#pragma omp parallel for collapse(2) + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + std::map planar_orient_supply_map; + for (auto& [layer_idx, orient_supply_map] : gcell_map[x][y].get_routing_orient_supply_map()) { + for (auto& [orient, supply] : orient_supply_map) { + planar_orient_supply_map[orient] += supply; + } + } + planar_node_map[x][y].set_orient_supply_map(planar_orient_supply_map); + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::generateTopoTree(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + std::vector& er_task_list = er_model.get_er_task_list(); + + int32_t batch_size = RTUTIL.getBatchSize(er_task_list.size()); + + Monitor stage_monitor; + for (size_t i = 0; i < er_task_list.size(); i++) { + routePlanarNet(er_model, er_task_list[i]); + if ((i + 1) % batch_size == 0 || (i + 1) == er_task_list.size()) { + RTLOG.info(Loc::current(), "Routed ", (i + 1), "/", er_task_list.size(), "(", RTUTIL.getPercentage(i + 1, er_task_list.size()), + ") nets", stage_monitor.getStatsInfo()); + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::routePlanarNet(ERModel& er_model, ERNet* er_net) +{ + std::vector> routing_segment_list; + for (Segment& planar_topo : getPlanarTopoList(er_model, er_net)) { + for (Segment& routing_segment : getRoutingSegmentList(er_model, planar_topo)) { + routing_segment_list.push_back(routing_segment); + } + } + MTree coord_tree = getPlanarCoordTree(er_net, routing_segment_list); + updatePlanarDemand(er_model, coord_tree); + if (!RTUTIL.getSegListByTree(coord_tree).empty()) { + er_net->set_topo_tree(coord_tree); + } +} + +std::vector> EarlyRouter::getPlanarTopoList(ERModel& er_model, ERNet* er_net) +{ + int32_t topo_spilt_length = er_model.get_er_parameter().get_topo_spilt_length(); + + std::vector planar_coord_list; + { + for (ERPin& er_pin : er_net->get_er_pin_list()) { + planar_coord_list.push_back(er_pin.get_access_point().get_grid_coord()); + } + std::sort(planar_coord_list.begin(), planar_coord_list.end(), CmpPlanarCoordByXASC()); + planar_coord_list.erase(std::unique(planar_coord_list.begin(), planar_coord_list.end()), planar_coord_list.end()); + } + std::vector> planar_topo_list; + for (Segment& planar_topo : RTI.getPlanarTopoList(planar_coord_list)) { + PlanarCoord& first_coord = planar_topo.get_first(); + PlanarCoord& second_coord = planar_topo.get_second(); + int32_t span_x = std::abs(first_coord.get_x() - second_coord.get_x()); + int32_t span_y = std::abs(first_coord.get_y() - second_coord.get_y()); + if (span_x > 1 && span_y > 1 && (span_x > topo_spilt_length || span_y > topo_spilt_length)) { + int32_t stick_num_x; + if (span_x % topo_spilt_length == 0) { + stick_num_x = (span_x / topo_spilt_length - 1); + } else { + stick_num_x = (span_x < topo_spilt_length) ? (span_x - 1) : (span_x / topo_spilt_length); + } + int32_t stick_num_y; + if (span_y % topo_spilt_length == 0) { + stick_num_y = (span_y / topo_spilt_length - 1); + } else { + stick_num_y = (span_y < topo_spilt_length) ? (span_y - 1) : (span_y / topo_spilt_length); + } + int32_t stick_num = std::min(stick_num_x, stick_num_y); + + std::vector coord_list; + coord_list.push_back(first_coord); + double delta_x = static_cast(second_coord.get_x() - first_coord.get_x()) / (stick_num + 1); + double delta_y = static_cast(second_coord.get_y() - first_coord.get_y()) / (stick_num + 1); + for (int32_t i = 1; i <= stick_num; i++) { + coord_list.emplace_back(std::round(first_coord.get_x() + i * delta_x), std::round(first_coord.get_y() + i * delta_y)); + } + coord_list.push_back(second_coord); + for (size_t i = 1; i < coord_list.size(); i++) { + planar_topo_list.emplace_back(coord_list[i - 1], coord_list[i]); + } + } else { + planar_topo_list.emplace_back(first_coord, second_coord); + } + } + return planar_topo_list; +} + +std::vector> EarlyRouter::getRoutingSegmentList(ERModel& er_model, Segment& planar_topo) +{ + std::vector> routing_segment_list; + for (auto getRoutingSegmentList : + {std::bind(&EarlyRouter::getRoutingSegmentListByStraight, this, std::placeholders::_1, std::placeholders::_2), + std::bind(&EarlyRouter::getRoutingSegmentListByLPattern, this, std::placeholders::_1, std::placeholders::_2)}) { + if (routing_segment_list.empty()) { + routing_segment_list = getRoutingSegmentList(er_model, planar_topo); + } + } + if (routing_segment_list.empty()) { + RTLOG.error(Loc::current(), "The routing_segment_list is empty"); + } + return routing_segment_list; +} + +std::vector> EarlyRouter::getRoutingSegmentListByStraight(ERModel& er_model, Segment& planar_topo) +{ + PlanarCoord& first_coord = planar_topo.get_first(); + PlanarCoord& second_coord = planar_topo.get_second(); + if (RTUTIL.isOblique(first_coord, second_coord)) { + return {}; + } + std::vector> routing_segment_list; + routing_segment_list.emplace_back(first_coord, second_coord); + return routing_segment_list; +} + +std::vector> EarlyRouter::getRoutingSegmentListByLPattern(ERModel& er_model, Segment& planar_topo) +{ + PlanarCoord& first_coord = planar_topo.get_first(); + PlanarCoord& second_coord = planar_topo.get_second(); + if (RTUTIL.isRightAngled(first_coord, second_coord)) { + return {}; + } + std::vector> inflection_list_list; + PlanarCoord inflection_coord1(first_coord.get_x(), second_coord.get_y()); + inflection_list_list.push_back({inflection_coord1}); + PlanarCoord inflection_coord2(second_coord.get_x(), first_coord.get_y()); + inflection_list_list.push_back({inflection_coord2}); + + std::vector>> routing_segment_list_list; + for (std::vector& inflection_list : inflection_list_list) { + std::vector> routing_segment_list; + if (inflection_list.empty()) { + routing_segment_list.emplace_back(planar_topo.get_first(), planar_topo.get_second()); + } else { + routing_segment_list.emplace_back(planar_topo.get_first(), inflection_list.front()); + for (size_t i = 1; i < inflection_list.size(); i++) { + routing_segment_list.emplace_back(inflection_list[i - 1], inflection_list[i]); + } + routing_segment_list.emplace_back(inflection_list.back(), planar_topo.get_second()); + } + routing_segment_list_list.push_back(routing_segment_list); + } + + double min_cost = DBL_MAX; + size_t min_i = 0; + for (size_t i = 0; i < routing_segment_list_list.size(); i++) { + double cost = getPlanarNodeCost(er_model, routing_segment_list_list[i]); + if (cost < min_cost) { + min_cost = cost; + min_i = i; + } + } + return routing_segment_list_list[min_i]; +} + +double EarlyRouter::getPlanarNodeCost(ERModel& er_model, std::vector>& routing_segment_list) +{ + double congestion_unit = er_model.get_er_parameter().get_congestion_unit(); + GridMap& planar_node_map = er_model.get_planar_node_map(); + + double node_cost = 0; + for (Segment& coord_segment : routing_segment_list) { + PlanarCoord& first_coord = coord_segment.get_first(); + PlanarCoord& second_coord = coord_segment.get_second(); + + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + if (orientation == Orientation::kNone || orientation == Orientation::kOblique) { + RTLOG.error(Loc::current(), "The orientation is error!"); + } + Orientation opposite_orientation = RTUTIL.getOppositeOrientation(orientation); + + node_cost += planar_node_map[first_coord.get_x()][first_coord.get_y()].getCongestionCost(orientation); + node_cost += planar_node_map[second_coord.get_x()][second_coord.get_y()].getCongestionCost(opposite_orientation); + + if (RTUTIL.isHorizontal(first_coord, second_coord)) { + int32_t first_x = first_coord.get_x(); + int32_t second_x = second_coord.get_x(); + int32_t y = first_coord.get_y(); + RTUTIL.swapByASC(first_x, second_x); + for (int32_t x = (first_x + 1); x <= (second_x - 1); x++) { + node_cost += planar_node_map[x][y].getCongestionCost(orientation); + node_cost += planar_node_map[x][y].getCongestionCost(opposite_orientation); + } + } else if (RTUTIL.isVertical(first_coord, second_coord)) { + int32_t x = first_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t second_y = second_coord.get_y(); + RTUTIL.swapByASC(first_y, second_y); + for (int32_t y = (first_y + 1); y <= (second_y - 1); y++) { + node_cost += planar_node_map[x][y].getCongestionCost(orientation); + node_cost += planar_node_map[x][y].getCongestionCost(opposite_orientation); + } + } + } + node_cost *= congestion_unit; + return node_cost; +} + +MTree EarlyRouter::getPlanarCoordTree(ERNet* er_net, std::vector>& planar_routing_segment_list) +{ + std::vector> routing_segment_list; + for (Segment& planar_routing_segment : planar_routing_segment_list) { + routing_segment_list.emplace_back(LayerCoord(planar_routing_segment.get_first(), 0), + LayerCoord(planar_routing_segment.get_second(), 0)); + } + std::vector candidate_root_coord_list; + std::map, CmpLayerCoordByXASC> key_coord_pin_map; + std::vector& er_pin_list = er_net->get_er_pin_list(); + for (size_t i = 0; i < er_pin_list.size(); i++) { + LayerCoord coord(er_pin_list[i].get_access_point().get_grid_coord(), 0); + candidate_root_coord_list.push_back(coord); + key_coord_pin_map[coord].insert(static_cast(i)); + } + return RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map); +} + +void EarlyRouter::updatePlanarDemand(ERModel& er_model, MTree& coord_tree) +{ + std::vector> routing_segment_list; + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { + routing_segment_list.emplace_back(coord_segment.get_first()->value(), coord_segment.get_second()->value()); + } + std::map, CmpLayerCoordByXASC> usage_map; + for (Segment& coord_segment : routing_segment_list) { + LayerCoord& first_coord = coord_segment.get_first(); + LayerCoord& second_coord = coord_segment.get_second(); + + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + if (orientation == Orientation::kNone || orientation == Orientation::kOblique) { + RTLOG.error(Loc::current(), "The orientation is error!"); + } + Orientation opposite_orientation = RTUTIL.getOppositeOrientation(orientation); + + int32_t first_x = first_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_x = second_coord.get_x(); + int32_t second_y = second_coord.get_y(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + RTUTIL.swapByASC(first_x, second_x); + RTUTIL.swapByASC(first_y, second_y); + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + + for (int32_t x = first_x; x <= second_x; x++) { + for (int32_t y = first_y; y <= second_y; y++) { + for (int32_t layer_idx = first_layer_idx; layer_idx <= second_layer_idx; layer_idx++) { + LayerCoord coord(x, y, layer_idx); + if (coord != first_coord) { + usage_map[coord].insert(opposite_orientation); + } + if (coord != second_coord) { + usage_map[coord].insert(orientation); + } + } + } + } + } + GridMap& planar_node_map = er_model.get_planar_node_map(); + for (auto& [usage_coord, orientation_list] : usage_map) { + ERNode& er_node = planar_node_map[usage_coord.get_x()][usage_coord.get_y()]; + er_node.updateDemand(orientation_list, ChangeType::kAdd); + } +} + +void EarlyRouter::buildLayerNodeMap(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + + std::vector>& layer_node_map = er_model.get_layer_node_map(); + layer_node_map.resize(routing_layer_list.size()); +#pragma omp parallel for + for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { + GridMap& er_node_map = layer_node_map[layer_idx]; + er_node_map.init(gcell_map.get_x_size(), gcell_map.get_y_size()); + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + ERNode& er_node = er_node_map[x][y]; + er_node.set_coord(x, y); + er_node.set_layer_idx(layer_idx); + } + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::buildLayerNodeNeighbor(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + GridMap& gcell_map = RTDM.getDatabase().get_gcell_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; + + std::vector>& layer_node_map = er_model.get_layer_node_map(); + +#pragma omp parallel for + for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { + bool routing_h = routing_layer_list[layer_idx].isPreferH(); + bool routing_v = !routing_h; + if (layer_idx < bottom_routing_layer_idx || top_routing_layer_idx < layer_idx) { + routing_h = false; + routing_v = false; + } + GridMap& er_node_map = layer_node_map[layer_idx]; + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + std::map& neighbor_node_map = er_node_map[x][y].get_neighbor_node_map(); + if (routing_h) { + if (x != 0) { + neighbor_node_map[Orientation::kWest] = &er_node_map[x - 1][y]; + } + if (x != (er_node_map.get_x_size() - 1)) { + neighbor_node_map[Orientation::kEast] = &er_node_map[x + 1][y]; + } + } + if (routing_v) { + if (y != 0) { + neighbor_node_map[Orientation::kSouth] = &er_node_map[x][y - 1]; + } + if (y != (er_node_map.get_y_size() - 1)) { + neighbor_node_map[Orientation::kNorth] = &er_node_map[x][y + 1]; + } + } + if (layer_idx != 0) { + neighbor_node_map[Orientation::kBelow] = &layer_node_map[layer_idx - 1][x][y]; + } + if (layer_idx != static_cast(layer_node_map.size()) - 1) { + neighbor_node_map[Orientation::kAbove] = &layer_node_map[layer_idx + 1][x][y]; + } + } + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::buildLayerOrientSupply(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + + std::vector>& layer_node_map = er_model.get_layer_node_map(); + +#pragma omp parallel for collapse(2) + for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { + for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { + for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { + layer_node_map[layer_idx][x][y].set_orient_supply_map(gcell_map[x][y].get_routing_orient_supply_map()[layer_idx]); + } + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::generateGlobalTree(ERModel& er_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + std::vector& er_task_list = er_model.get_er_task_list(); + + int32_t batch_size = RTUTIL.getBatchSize(er_task_list.size()); + + Monitor stage_monitor; + for (size_t i = 0; i < er_task_list.size(); i++) { + routeLayerNet(er_model, er_task_list[i]); + if ((i + 1) % batch_size == 0 || (i + 1) == er_task_list.size()) { + RTLOG.info(Loc::current(), "Routed ", (i + 1), "/", er_task_list.size(), "(", RTUTIL.getPercentage(i + 1, er_task_list.size()), + ") nets", stage_monitor.getStatsInfo()); + } + } + + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + +void EarlyRouter::routeLayerNet(ERModel& er_model, ERNet* er_net) +{ + // 构建er_topo_list,并将通孔线段加入routing_segment_list + std::vector er_topo_list; + std::vector> routing_segment_list; + makeERTopoList(er_model, er_net, er_topo_list, routing_segment_list); + for (ERTopo& er_topo : er_topo_list) { + routeERTopo(er_model, &er_topo); + for (Segment& routing_segment : er_topo.get_routing_segment_list()) { + routing_segment_list.push_back(routing_segment); + } + } + MTree coord_tree = getLayerCoordTree(er_net, routing_segment_list); + updateLayerDemand(er_model, er_net, coord_tree); + uploadNetResult(er_net, coord_tree); +} + +void EarlyRouter::makeERTopoList(ERModel& er_model, ERNet* er_net, std::vector& er_topo_list, + std::vector>& routing_segment_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; + int32_t topo_spilt_length = er_model.get_er_parameter().get_topo_spilt_length(); + + if (er_net->get_topo_tree().get_root() == nullptr) { + ERTopo er_topo; + for (ERPin& er_pin : er_net->get_er_pin_list()) { + ERGroup er_group; + er_group.get_coord_list().push_back(er_pin.get_access_point().getGridLayerCoord()); + er_topo.get_er_group_list().push_back(er_group); + } + er_topo_list.push_back(er_topo); + { + std::set coord_set; + for (ERTopo& er_topo : er_topo_list) { + for (ERGroup& er_group : er_topo.get_er_group_list()) { + for (LayerCoord& coord : er_group.get_coord_list()) { + coord_set.insert(coord); + } + } + } + if (coord_set.size() > 1) { + RTLOG.error(Loc::current(), "The topo_tree should not be empty!"); + } + } + } else { + // planar_topo_list + std::vector> planar_topo_list; + { + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(er_net->get_topo_tree())) { + PlanarCoord& first_coord = coord_segment.get_first()->value(); + PlanarCoord& second_coord = coord_segment.get_second()->value(); + int32_t first_x = first_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t second_x = second_coord.get_x(); + int32_t second_y = second_coord.get_y(); + + if (first_x == second_x) { + int32_t y_diff = std::abs(second_y - first_y); + int32_t segment_num = std::max(1, static_cast(std::ceil(y_diff / topo_spilt_length))); + int32_t step = (second_y - first_y) / segment_num; + for (int32_t i = 0; i < segment_num; ++i) { + PlanarCoord start(first_x, first_y + i * step); + PlanarCoord end(first_x, first_y + (i + 1) * step); + planar_topo_list.emplace_back(start, end); + } + // Add the last segment to reach the exact second_coord + if (planar_topo_list.back().get_second().get_y() != second_y) { + planar_topo_list.emplace_back(planar_topo_list.back().get_second(), second_coord); + } + } else if (first_y == second_y) { + int32_t x_diff = std::abs(second_x - first_x); + int32_t segment_num = std::max(1, static_cast(std::ceil(x_diff / topo_spilt_length))); + int32_t step = (second_x - first_x) / segment_num; + for (int32_t i = 0; i < segment_num; ++i) { + PlanarCoord start(first_x + i * step, first_y); + PlanarCoord end(first_x + (i + 1) * step, first_y); + planar_topo_list.emplace_back(start, end); + } + if (planar_topo_list.back().get_second().get_x() != second_x) { + planar_topo_list.emplace_back(planar_topo_list.back().get_second(), second_coord); + } + } else { + RTLOG.error(Loc::current(), "The segment is not horizontal or vertical!"); + } + } + } + // planar_pin_group_map + std::map, CmpPlanarCoordByXASC> planar_pin_group_map; + { + for (ERPin& er_pin : er_net->get_er_pin_list()) { + LayerCoord grid_coord = er_pin.get_access_point().getGridLayerCoord(); + + ERGroup er_group; + er_group.get_coord_list().push_back(grid_coord); + planar_pin_group_map[grid_coord.get_planar_coord()].push_back(er_group); + } + } + // planar_steiner_group_map + std::map planar_steiner_group_map; + { + for (Segment& planar_topo : planar_topo_list) { + for (PlanarCoord coord : {planar_topo.get_first(), planar_topo.get_second()}) { + if (!RTUTIL.exist(planar_pin_group_map, coord) && !RTUTIL.exist(planar_steiner_group_map, coord)) { + // 补充steiner point的垂直线段 + routing_segment_list.emplace_back(LayerCoord(coord, bottom_routing_layer_idx), LayerCoord(coord, top_routing_layer_idx)); + for (int32_t layer_idx = bottom_routing_layer_idx; layer_idx <= top_routing_layer_idx; layer_idx++) { + planar_steiner_group_map[coord].get_coord_list().push_back(LayerCoord(coord, layer_idx)); + } + } + } + } + } + // 生成topo group + { + for (Segment& planar_topo : planar_topo_list) { + ERTopo er_topo; + for (PlanarCoord coord : {planar_topo.get_first(), planar_topo.get_second()}) { + if (RTUTIL.exist(planar_pin_group_map, coord)) { + for (ERGroup& er_group : planar_pin_group_map[coord]) { + er_topo.get_er_group_list().push_back(er_group); + } + } else if (RTUTIL.exist(planar_steiner_group_map, coord)) { + er_topo.get_er_group_list().push_back(planar_steiner_group_map[coord]); + } + } + er_topo_list.push_back(er_topo); + } + } + } + // 构建topo的其他内容 + { + for (ERTopo& er_topo : er_topo_list) { + er_topo.set_net_idx(er_net->get_net_idx()); + std::vector coord_list; + for (ERGroup& er_group : er_topo.get_er_group_list()) { + for (LayerCoord& coord : er_group.get_coord_list()) { + coord_list.push_back(coord); + } + } + er_topo.set_bounding_box(RTUTIL.getBoundingBox(coord_list)); + } + } +} + +void EarlyRouter::routeERTopo(ERModel& er_model, ERTopo* er_topo) +{ + initSingleTask(er_model, er_topo); + while (!isConnectedAllEnd(er_model)) { + routeSinglePath(er_model); + updatePathResult(er_model); + resetStartAndEnd(er_model); + resetSinglePath(er_model); + } + updateTaskResult(er_model); + resetSingleTask(er_model); +} + +void EarlyRouter::initSingleTask(ERModel& er_model, ERTopo* er_topo) +{ + std::vector>& layer_node_map = er_model.get_layer_node_map(); + + // single topo + er_model.set_curr_er_topo(er_topo); + { + std::vector> node_list_list; + std::vector& er_group_list = er_topo->get_er_group_list(); + for (ERGroup& er_group : er_group_list) { + std::vector node_list; + for (LayerCoord& coord : er_group.get_coord_list()) { + ERNode& er_node = layer_node_map[coord.get_layer_idx()][coord.get_x()][coord.get_y()]; + node_list.push_back(&er_node); + } + node_list_list.push_back(node_list); + } + for (size_t i = 0; i < node_list_list.size(); i++) { + if (i == 0) { + er_model.get_start_node_list_list().push_back(node_list_list[i]); + } else { + er_model.get_end_node_list_list().push_back(node_list_list[i]); + } + } + } + er_model.get_path_node_list().clear(); + er_model.get_single_topo_visited_node_list().clear(); + er_model.get_routing_segment_list().clear(); +} + +bool EarlyRouter::isConnectedAllEnd(ERModel& er_model) +{ + return er_model.get_end_node_list_list().empty(); +} + +void EarlyRouter::routeSinglePath(ERModel& er_model) +{ + initPathHead(er_model); + while (!searchEnded(er_model)) { + expandSearching(er_model); + resetPathHead(er_model); + } +} + +void EarlyRouter::initPathHead(ERModel& er_model) +{ + std::vector>& start_node_list_list = er_model.get_start_node_list_list(); + std::vector& path_node_list = er_model.get_path_node_list(); + + for (std::vector& start_node_list : start_node_list_list) { + for (ERNode* start_node : start_node_list) { + start_node->set_estimated_cost(getEstimateCostToEnd(er_model, start_node)); + pushToOpenList(er_model, start_node); + } + } + for (ERNode* path_node : path_node_list) { + path_node->set_estimated_cost(getEstimateCostToEnd(er_model, path_node)); + pushToOpenList(er_model, path_node); + } + resetPathHead(er_model); +} + +bool EarlyRouter::searchEnded(ERModel& er_model) +{ + std::vector>& end_node_list_list = er_model.get_end_node_list_list(); + ERNode* path_head_node = er_model.get_path_head_node(); + + if (path_head_node == nullptr) { + er_model.set_end_node_list_idx(-1); + return true; + } + for (size_t i = 0; i < end_node_list_list.size(); i++) { + for (ERNode* end_node : end_node_list_list[i]) { + if (path_head_node == end_node) { + er_model.set_end_node_list_idx(static_cast(i)); + return true; + } + } + } + return false; +} + +void EarlyRouter::expandSearching(ERModel& er_model) +{ + PriorityQueue, CmpERNodeCost>& open_queue = er_model.get_open_queue(); + ERNode* path_head_node = er_model.get_path_head_node(); + + for (auto& [orientation, neighbor_node] : path_head_node->get_neighbor_node_map()) { + if (neighbor_node == nullptr) { + continue; + } + if (!RTUTIL.isInside(er_model.get_curr_er_topo()->get_bounding_box(), *neighbor_node)) { + continue; + } + if (neighbor_node->isClose()) { + continue; + } + double know_cost = getKnowCost(er_model, path_head_node, neighbor_node); + if (neighbor_node->isOpen() && know_cost < neighbor_node->get_known_cost()) { + neighbor_node->set_known_cost(know_cost); + neighbor_node->set_parent_node(path_head_node); + // 对优先队列中的值修改了,需要重新建堆 + std::make_heap(open_queue.begin(), open_queue.end(), CmpERNodeCost()); + } else if (neighbor_node->isNone()) { + neighbor_node->set_known_cost(know_cost); + neighbor_node->set_parent_node(path_head_node); + neighbor_node->set_estimated_cost(getEstimateCostToEnd(er_model, neighbor_node)); + pushToOpenList(er_model, neighbor_node); + } + } +} + +void EarlyRouter::resetPathHead(ERModel& er_model) +{ + er_model.set_path_head_node(popFromOpenList(er_model)); +} + +void EarlyRouter::updatePathResult(ERModel& er_model) +{ + for (Segment& routing_segment : getRoutingSegmentListByNode(er_model.get_path_head_node())) { + er_model.get_routing_segment_list().push_back(routing_segment); + } +} + +std::vector> EarlyRouter::getRoutingSegmentListByNode(ERNode* node) +{ + std::vector> routing_segment_list; + + ERNode* curr_node = node; + ERNode* pre_node = curr_node->get_parent_node(); + + if (pre_node == nullptr) { + // 起点和终点重合 + return routing_segment_list; + } + Orientation curr_orientation = RTUTIL.getOrientation(*curr_node, *pre_node); + while (pre_node->get_parent_node() != nullptr) { + Orientation pre_orientation = RTUTIL.getOrientation(*pre_node, *pre_node->get_parent_node()); + if (curr_orientation != pre_orientation) { + routing_segment_list.emplace_back(*curr_node, *pre_node); + curr_orientation = pre_orientation; + curr_node = pre_node; + } + pre_node = pre_node->get_parent_node(); + } + routing_segment_list.emplace_back(*curr_node, *pre_node); + + return routing_segment_list; +} + +void EarlyRouter::resetStartAndEnd(ERModel& er_model) +{ + std::vector>& start_node_list_list = er_model.get_start_node_list_list(); + std::vector>& end_node_list_list = er_model.get_end_node_list_list(); + std::vector& path_node_list = er_model.get_path_node_list(); + ERNode* path_head_node = er_model.get_path_head_node(); + int32_t end_node_list_idx = er_model.get_end_node_list_idx(); + + // 对于抵达的终点pin,只保留到达的node + end_node_list_list[end_node_list_idx].clear(); + end_node_list_list[end_node_list_idx].push_back(path_head_node); + + ERNode* path_node = path_head_node->get_parent_node(); + if (path_node == nullptr) { + // 起点和终点重合 + path_node = path_head_node; + } else { + // 起点和终点不重合 + while (path_node->get_parent_node() != nullptr) { + path_node_list.push_back(path_node); + path_node = path_node->get_parent_node(); + } + } + if (start_node_list_list.size() == 1) { + // 初始化时,要把start_node_list_list的pin只留一个ap点 + // 后续只要将end_node_list_list的pin保留一个ap点 + start_node_list_list.front().clear(); + start_node_list_list.front().push_back(path_node); + } + start_node_list_list.push_back(end_node_list_list[end_node_list_idx]); + end_node_list_list.erase(end_node_list_list.begin() + end_node_list_idx); +} + +void EarlyRouter::resetSinglePath(ERModel& er_model) +{ + PriorityQueue, CmpERNodeCost> empty_queue; + er_model.set_open_queue(empty_queue); + + std::vector& single_path_visited_node_list = er_model.get_single_path_visited_node_list(); + for (ERNode* visited_node : single_path_visited_node_list) { + visited_node->set_state(ERNodeState::kNone); + visited_node->set_parent_node(nullptr); + visited_node->set_known_cost(0); + visited_node->set_estimated_cost(0); + } + single_path_visited_node_list.clear(); + + er_model.set_path_head_node(nullptr); + er_model.set_end_node_list_idx(-1); +} + +void EarlyRouter::updateTaskResult(ERModel& er_model) +{ + er_model.get_curr_er_topo()->set_routing_segment_list(getRoutingSegmentList(er_model)); +} + +std::vector> EarlyRouter::getRoutingSegmentList(ERModel& er_model) +{ + ERTopo* curr_er_topo = er_model.get_curr_er_topo(); + + std::vector candidate_root_coord_list; + std::map, CmpLayerCoordByXASC> key_coord_pin_map; + std::vector& er_group_list = curr_er_topo->get_er_group_list(); + for (size_t i = 0; i < er_group_list.size(); i++) { + for (LayerCoord& coord : er_group_list[i].get_coord_list()) { + candidate_root_coord_list.push_back(coord); + key_coord_pin_map[coord].insert(static_cast(i)); + } + } + MTree coord_tree + = RTUTIL.getTreeByFullFlow(candidate_root_coord_list, er_model.get_routing_segment_list(), key_coord_pin_map); + + std::vector> routing_segment_list; + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { + routing_segment_list.emplace_back(coord_segment.get_first()->value(), coord_segment.get_second()->value()); + } + return routing_segment_list; +} + +void EarlyRouter::resetSingleTask(ERModel& er_model) +{ + er_model.set_curr_er_topo(nullptr); + er_model.get_start_node_list_list().clear(); + er_model.get_end_node_list_list().clear(); + er_model.get_path_node_list().clear(); + er_model.get_single_topo_visited_node_list().clear(); + er_model.get_routing_segment_list().clear(); +} + +// manager open list + +void EarlyRouter::pushToOpenList(ERModel& er_model, ERNode* curr_node) +{ + PriorityQueue, CmpERNodeCost>& open_queue = er_model.get_open_queue(); + std::vector& single_topo_visited_node_list = er_model.get_single_topo_visited_node_list(); + std::vector& single_path_visited_node_list = er_model.get_single_path_visited_node_list(); + + open_queue.push(curr_node); + curr_node->set_state(ERNodeState::kOpen); + single_topo_visited_node_list.push_back(curr_node); + single_path_visited_node_list.push_back(curr_node); +} + +ERNode* EarlyRouter::popFromOpenList(ERModel& er_model) +{ + PriorityQueue, CmpERNodeCost>& open_queue = er_model.get_open_queue(); + + ERNode* node = nullptr; + if (!open_queue.empty()) { + node = open_queue.top(); + open_queue.pop(); + node->set_state(ERNodeState::kClose); + } + return node; +} + +// calculate known cost + +double EarlyRouter::getKnowCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + bool exist_neighbor = false; + for (auto& [orientation, neighbor_ptr] : start_node->get_neighbor_node_map()) { + if (neighbor_ptr == end_node) { + exist_neighbor = true; + break; + } + } + if (!exist_neighbor) { + RTLOG.error(Loc::current(), "The neighbor not exist!"); + } + + double cost = 0; + cost += start_node->get_known_cost(); + cost += getNodeCost(er_model, start_node, RTUTIL.getOrientation(*start_node, *end_node)); + cost += getNodeCost(er_model, end_node, RTUTIL.getOrientation(*end_node, *start_node)); + cost += getKnowWireCost(er_model, start_node, end_node); + cost += getKnowViaCost(er_model, start_node, end_node); + return cost; +} + +double EarlyRouter::getNodeCost(ERModel& er_model, ERNode* curr_node, Orientation orientation) +{ + double congestion_unit = er_model.get_er_parameter().get_congestion_unit(); + + double node_cost = 0; + node_cost += curr_node->getCongestionCost(orientation) * congestion_unit; + return node_cost; +} + +double EarlyRouter::getKnowWireCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + double prefer_wire_unit = er_model.get_er_parameter().get_prefer_wire_unit(); + + double wire_cost = 0; + if (start_node->get_layer_idx() == end_node->get_layer_idx()) { + wire_cost += RTUTIL.getManhattanDistance(start_node->get_planar_coord(), end_node->get_planar_coord()); + + RoutingLayer& routing_layer = routing_layer_list[start_node->get_layer_idx()]; + if (routing_layer.get_prefer_direction() == RTUTIL.getDirection(*start_node, *end_node)) { + wire_cost *= prefer_wire_unit; + } + } + return wire_cost; +} + +double EarlyRouter::getKnowViaCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + double via_unit = er_model.get_er_parameter().get_via_unit(); + double via_cost = (via_unit * std::abs(start_node->get_layer_idx() - end_node->get_layer_idx())); + return via_cost; +} + +// calculate estimate cost + +double EarlyRouter::getEstimateCostToEnd(ERModel& er_model, ERNode* curr_node) +{ + std::vector>& end_node_list_list = er_model.get_end_node_list_list(); + + double estimate_cost = DBL_MAX; + for (std::vector& end_node_list : end_node_list_list) { + for (ERNode* end_node : end_node_list) { + if (end_node->isClose()) { + continue; + } + estimate_cost = std::min(estimate_cost, getEstimateCost(er_model, curr_node, end_node)); + } + } + return estimate_cost; +} + +double EarlyRouter::getEstimateCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + double estimate_cost = 0; + estimate_cost += getEstimateWireCost(er_model, start_node, end_node); + estimate_cost += getEstimateViaCost(er_model, start_node, end_node); + return estimate_cost; +} + +double EarlyRouter::getEstimateWireCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + double prefer_wire_unit = er_model.get_er_parameter().get_prefer_wire_unit(); + + double wire_cost = 0; + wire_cost += RTUTIL.getManhattanDistance(start_node->get_planar_coord(), end_node->get_planar_coord()); + wire_cost *= prefer_wire_unit; + return wire_cost; +} + +double EarlyRouter::getEstimateViaCost(ERModel& er_model, ERNode* start_node, ERNode* end_node) +{ + double via_unit = er_model.get_er_parameter().get_via_unit(); + double via_cost = (via_unit * std::abs(start_node->get_layer_idx() - end_node->get_layer_idx())); + return via_cost; +} + +MTree EarlyRouter::getLayerCoordTree(ERNet* er_net, std::vector>& routing_segment_list) +{ + std::vector candidate_root_coord_list; + std::map, CmpLayerCoordByXASC> key_coord_pin_map; + std::vector& er_pin_list = er_net->get_er_pin_list(); + for (size_t i = 0; i < er_pin_list.size(); i++) { + LayerCoord coord = er_pin_list[i].get_access_point().getGridLayerCoord(); + candidate_root_coord_list.push_back(coord); + key_coord_pin_map[coord].insert(static_cast(i)); + } + return RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map); +} + +void EarlyRouter::updateLayerDemand(ERModel& er_model, ERNet* er_net, MTree& coord_tree) +{ + std::set key_coord_set; + for (ERPin& er_pin : er_net->get_er_pin_list()) { + key_coord_set.insert(er_pin.get_access_point().getGridLayerCoord()); + } + std::vector> routing_segment_list; + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { + routing_segment_list.emplace_back(coord_segment.get_first()->value(), coord_segment.get_second()->value()); + } + std::map, CmpLayerCoordByXASC> usage_map; + for (Segment& coord_segment : routing_segment_list) { + LayerCoord& first_coord = coord_segment.get_first(); + LayerCoord& second_coord = coord_segment.get_second(); + + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + if (orientation == Orientation::kNone || orientation == Orientation::kOblique) { + RTLOG.error(Loc::current(), "The orientation is error!"); + } + Orientation opposite_orientation = RTUTIL.getOppositeOrientation(orientation); + + int32_t first_x = first_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_x = second_coord.get_x(); + int32_t second_y = second_coord.get_y(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + RTUTIL.swapByASC(first_x, second_x); + RTUTIL.swapByASC(first_y, second_y); + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + + for (int32_t x = first_x; x <= second_x; x++) { + for (int32_t y = first_y; y <= second_y; y++) { + for (int32_t layer_idx = first_layer_idx; layer_idx <= second_layer_idx; layer_idx++) { + LayerCoord coord(x, y, layer_idx); + if (coord != first_coord) { + usage_map[coord].insert(opposite_orientation); + } + if (coord != second_coord) { + usage_map[coord].insert(orientation); + } + } + } + } + } + std::vector>& layer_node_map = er_model.get_layer_node_map(); + for (auto& [usage_coord, orientation_list] : usage_map) { + ERNode& er_node = layer_node_map[usage_coord.get_layer_idx()][usage_coord.get_x()][usage_coord.get_y()]; + er_node.updateDemand(orientation_list, ChangeType::kAdd); + } +} + +void EarlyRouter::uploadNetResult(ERNet* er_net, MTree& coord_tree) +{ + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { + Segment* segment = new Segment(coord_segment.get_first()->value(), coord_segment.get_second()->value()); + RTDM.updateGlobalNetResultToGCellMap(ChangeType::kAdd, er_net->get_net_idx(), segment); + } +} + +#if 1 // exhibit + +void EarlyRouter::updateSummary(ERModel& er_model) +{ + int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + Die& die = RTDM.getDatabase().get_die(); + GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); + std::vector>& layer_via_master_list = RTDM.getDatabase().get_layer_via_master_list(); + Summary& summary = RTDM.getDatabase().get_summary(); + int32_t enable_timing = RTDM.getConfig().enable_timing; + + std::map& routing_demand_map = summary.er_summary.routing_demand_map; + int32_t& total_demand = summary.er_summary.total_demand; + std::map& routing_overflow_map = summary.er_summary.routing_overflow_map; + int32_t& total_overflow = summary.er_summary.total_overflow; + std::map& routing_wire_length_map = summary.er_summary.routing_wire_length_map; + double& total_wire_length = summary.er_summary.total_wire_length; + std::map& cut_via_num_map = summary.er_summary.cut_via_num_map; + int32_t& total_via_num = summary.er_summary.total_via_num; + std::map>& clock_timing = summary.er_summary.clock_timing; + std::map& power_map = summary.er_summary.power_map; + + std::vector>& layer_node_map = er_model.get_layer_node_map(); + std::vector& er_net_list = er_model.get_er_net_list(); + + for (RoutingLayer& routing_layer : routing_layer_list) { + routing_demand_map[routing_layer.get_layer_idx()] = 0; + routing_overflow_map[routing_layer.get_layer_idx()] = 0; + routing_wire_length_map[routing_layer.get_layer_idx()] = 0; + } + total_demand = 0; + total_overflow = 0; + total_wire_length = 0; + for (CutLayer& cut_layer : cut_layer_list) { + cut_via_num_map[cut_layer.get_layer_idx()] = 0; + } + total_via_num = 0; + + for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { + GridMap& er_node_map = layer_node_map[layer_idx]; + for (int32_t x = 0; x < er_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < er_node_map.get_y_size(); y++) { + std::map& orient_supply_map = er_node_map[x][y].get_orient_supply_map(); + std::map& orient_demand_map = er_node_map[x][y].get_orient_demand_map(); + int32_t node_demand = 0; + int32_t node_overflow = 0; + if (routing_layer_list[layer_idx].isPreferH()) { + node_demand = (orient_demand_map[Orientation::kEast] + orient_demand_map[Orientation::kWest]); + node_overflow = std::max(0, orient_demand_map[Orientation::kEast] - orient_supply_map[Orientation::kEast]) + + std::max(0, orient_demand_map[Orientation::kWest] - orient_supply_map[Orientation::kWest]); + } else { + node_demand = (orient_demand_map[Orientation::kSouth] + orient_demand_map[Orientation::kNorth]); + node_overflow = std::max(0, orient_demand_map[Orientation::kSouth] - orient_supply_map[Orientation::kSouth]) + + std::max(0, orient_demand_map[Orientation::kNorth] - orient_supply_map[Orientation::kNorth]); + } + routing_demand_map[layer_idx] += node_demand; + total_demand += node_demand; + routing_overflow_map[layer_idx] += node_overflow; + total_overflow += node_overflow; + } + } + } + for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { + for (Segment* segment : segment_set) { + LayerCoord& first_coord = segment->get_first(); + int32_t first_layer_idx = first_coord.get_layer_idx(); + LayerCoord& second_coord = segment->get_second(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + + if (first_layer_idx == second_layer_idx) { + GCell& first_gcell = gcell_map[first_coord.get_x()][first_coord.get_y()]; + GCell& second_gcell = gcell_map[second_coord.get_x()][second_coord.get_y()]; + double wire_length = RTUTIL.getManhattanDistance(first_gcell.getMidPoint(), second_gcell.getMidPoint()) / 1.0 / micron_dbu; + routing_wire_length_map[first_layer_idx] += wire_length; + total_wire_length += wire_length; + } else { + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { + cut_via_num_map[layer_via_master_list[layer_idx].front().get_cut_layer_idx()]++; + total_via_num++; + } + } + } + } + if (enable_timing) { + std::vector>> real_pin_coord_map_list; + real_pin_coord_map_list.resize(er_net_list.size()); + std::vector>> routing_segment_list_list; + routing_segment_list_list.resize(er_net_list.size()); + for (ERNet& er_net : er_net_list) { + for (ERPin& er_pin : er_net.get_er_pin_list()) { + LayerCoord layer_coord = er_pin.get_access_point().getGridLayerCoord(); + real_pin_coord_map_list[er_net.get_net_idx()][er_pin.get_pin_name()].emplace_back( + RTUTIL.getRealRectByGCell(layer_coord, gcell_axis).getMidPoint(), layer_coord.get_layer_idx()); + } + } + for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { + for (Segment* segment : segment_set) { + LayerCoord first_layer_coord = segment->get_first(); + LayerCoord first_real_coord(RTUTIL.getRealRectByGCell(first_layer_coord, gcell_axis).getMidPoint(), + first_layer_coord.get_layer_idx()); + LayerCoord second_layer_coord = segment->get_second(); + LayerCoord second_real_coord(RTUTIL.getRealRectByGCell(second_layer_coord, gcell_axis).getMidPoint(), + second_layer_coord.get_layer_idx()); + + routing_segment_list_list[net_idx].emplace_back(first_real_coord, second_real_coord); + } + } + RTI.updateTimingAndPower(real_pin_coord_map_list, routing_segment_list_list, clock_timing, power_map); + } +} + +void EarlyRouter::printSummary(ERModel& er_model) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); + Summary& summary = RTDM.getDatabase().get_summary(); + int32_t enable_timing = RTDM.getConfig().enable_timing; + + std::map& routing_demand_map = summary.er_summary.routing_demand_map; + int32_t& total_demand = summary.er_summary.total_demand; + std::map& routing_overflow_map = summary.er_summary.routing_overflow_map; + int32_t& total_overflow = summary.er_summary.total_overflow; + std::map& routing_wire_length_map = summary.er_summary.routing_wire_length_map; + double& total_wire_length = summary.er_summary.total_wire_length; + std::map& cut_via_num_map = summary.er_summary.cut_via_num_map; + int32_t& total_via_num = summary.er_summary.total_via_num; + std::map>& clock_timing = summary.er_summary.clock_timing; + std::map& power_map = summary.er_summary.power_map; + + fort::char_table routing_demand_map_table; + { + routing_demand_map_table << fort::header << "routing_layer" + << "demand" + << "proportion" << fort::endr; + for (RoutingLayer& routing_layer : routing_layer_list) { + routing_demand_map_table << routing_layer.get_layer_name() << routing_demand_map[routing_layer.get_layer_idx()] + << RTUTIL.getPercentage(routing_demand_map[routing_layer.get_layer_idx()], total_demand) << fort::endr; + } + routing_demand_map_table << fort::header << "Total" << total_demand << RTUTIL.getPercentage(total_demand, total_demand) << fort::endr; + } + fort::char_table routing_overflow_map_table; + { + routing_overflow_map_table << fort::header << "routing_layer" + << "overflow" + << "proportion" << fort::endr; + for (RoutingLayer& routing_layer : routing_layer_list) { + routing_overflow_map_table << routing_layer.get_layer_name() << routing_overflow_map[routing_layer.get_layer_idx()] + << RTUTIL.getPercentage(routing_overflow_map[routing_layer.get_layer_idx()], total_overflow) << fort::endr; + } + routing_overflow_map_table << fort::header << "Total" << total_overflow << RTUTIL.getPercentage(total_overflow, total_overflow) + << fort::endr; + } + fort::char_table routing_wire_length_map_table; + { + routing_wire_length_map_table << fort::header << "routing_layer" + << "wire_length" + << "proportion" << fort::endr; + for (RoutingLayer& routing_layer : routing_layer_list) { + routing_wire_length_map_table << routing_layer.get_layer_name() << routing_wire_length_map[routing_layer.get_layer_idx()] + << RTUTIL.getPercentage(routing_wire_length_map[routing_layer.get_layer_idx()], total_wire_length) + << fort::endr; + } + routing_wire_length_map_table << fort::header << "Total" << total_wire_length + << RTUTIL.getPercentage(total_wire_length, total_wire_length) << fort::endr; + } + fort::char_table cut_via_num_map_table; + { + cut_via_num_map_table << fort::header << "cut_layer" + << "via_num" + << "proportion" << fort::endr; + for (CutLayer& cut_layer : cut_layer_list) { + cut_via_num_map_table << cut_layer.get_layer_name() << cut_via_num_map[cut_layer.get_layer_idx()] + << RTUTIL.getPercentage(cut_via_num_map[cut_layer.get_layer_idx()], total_via_num) << fort::endr; + } + cut_via_num_map_table << fort::header << "Total" << total_via_num << RTUTIL.getPercentage(total_via_num, total_via_num) << fort::endr; + } + fort::char_table timing_table; + fort::char_table power_table; + if (enable_timing) { + timing_table << fort::header << "clock_name" + << "tns" + << "wns" + << "freq" << fort::endr; + for (auto& [clock_name, timing_map] : clock_timing) { + timing_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; + } + power_table << fort::header << "power_type" << "power_value" << fort::endr; + for (auto& [type, power] : power_map) { + power_table << type << power << fort::endr; + } + } + RTUTIL.printTableList({routing_demand_map_table, routing_overflow_map_table, routing_wire_length_map_table, cut_via_num_map_table}); + RTUTIL.printTableList({timing_table, power_table}); +} + +void EarlyRouter::outputGuide(ERModel& er_model) +{ + int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + Die& die = RTDM.getDatabase().get_die(); + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::string& er_temp_directory_path = RTDM.getConfig().er_temp_directory_path; + int32_t output_inter_result = RTDM.getConfig().output_inter_result; + if (!output_inter_result) { + return; + } + std::vector& er_net_list = er_model.get_er_net_list(); + + std::ofstream* guide_file_stream = RTUTIL.getOutputFileStream(er_temp_directory_path + "route.guide"); + if (guide_file_stream == nullptr) { + return; + } + RTUTIL.pushStream(guide_file_stream, "guide net_name\n"); + RTUTIL.pushStream(guide_file_stream, "pin grid_x grid_y real_x real_y layer energy name\n"); + RTUTIL.pushStream(guide_file_stream, "wire grid1_x grid1_y grid2_x grid2_y real1_x real1_y real2_x real2_y layer\n"); + RTUTIL.pushStream(guide_file_stream, "via grid_x grid_y real_x real_y layer1 layer2\n"); + + for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { + ERNet& er_net = er_net_list[net_idx]; + RTUTIL.pushStream(guide_file_stream, "guide ", er_net.get_origin_net()->get_net_name(), "\n"); + + for (ERPin& er_pin : er_net.get_er_pin_list()) { + AccessPoint& access_point = er_pin.get_access_point(); + double grid_x = access_point.get_grid_x(); + double grid_y = access_point.get_grid_y(); + double real_x = access_point.get_real_x() / 1.0 / micron_dbu; + double real_y = access_point.get_real_y() / 1.0 / micron_dbu; + std::string layer = routing_layer_list[access_point.get_layer_idx()].get_layer_name(); + std::string connnect; + if (er_pin.get_is_driven()) { + connnect = "driven"; + } else { + connnect = "load"; + } + RTUTIL.pushStream(guide_file_stream, "pin ", grid_x, " ", grid_y, " ", real_x, " ", real_y, " ", layer, " ", connnect, " ", + er_pin.get_pin_name(), "\n"); + } + for (Segment* segment : segment_set) { + LayerCoord first_layer_coord = segment->get_first(); + double grid1_x = first_layer_coord.get_x(); + double grid1_y = first_layer_coord.get_y(); + int32_t first_layer_idx = first_layer_coord.get_layer_idx(); + + PlanarCoord first_mid_coord = RTUTIL.getRealRectByGCell(first_layer_coord, gcell_axis).getMidPoint(); + double real1_x = first_mid_coord.get_x() / 1.0 / micron_dbu; + double real1_y = first_mid_coord.get_y() / 1.0 / micron_dbu; + + LayerCoord second_layer_coord = segment->get_second(); + double grid2_x = second_layer_coord.get_x(); + double grid2_y = second_layer_coord.get_y(); + int32_t second_layer_idx = second_layer_coord.get_layer_idx(); + + PlanarCoord second_mid_coord = RTUTIL.getRealRectByGCell(second_layer_coord, gcell_axis).getMidPoint(); + double real2_x = second_mid_coord.get_x() / 1.0 / micron_dbu; + double real2_y = second_mid_coord.get_y() / 1.0 / micron_dbu; + + if (first_layer_idx != second_layer_idx) { + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + std::string layer1 = routing_layer_list[first_layer_idx].get_layer_name(); + std::string layer2 = routing_layer_list[second_layer_idx].get_layer_name(); + RTUTIL.pushStream(guide_file_stream, "via ", grid1_x, " ", grid1_y, " ", real1_x, " ", real1_y, " ", layer1, " ", layer2, "\n"); + } else { + std::string layer = routing_layer_list[first_layer_idx].get_layer_name(); + RTUTIL.pushStream(guide_file_stream, "wire ", grid1_x, " ", grid1_y, " ", grid2_x, " ", grid2_y, " ", real1_x, " ", real1_y, " ", + real2_x, " ", real2_y, " ", layer, "\n"); + } + } + } + RTUTIL.closeFileStream(guide_file_stream); +} + +void EarlyRouter::outputDemandCSV(ERModel& er_model) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::string& er_temp_directory_path = RTDM.getConfig().er_temp_directory_path; + int32_t output_inter_result = RTDM.getConfig().output_inter_result; + if (!output_inter_result) { + return; + } + std::vector>& layer_node_map = er_model.get_layer_node_map(); + for (RoutingLayer& routing_layer : routing_layer_list) { + std::ofstream* demand_csv_file + = RTUTIL.getOutputFileStream(RTUTIL.getString(er_temp_directory_path, "demand_map_", routing_layer.get_layer_name(), ".csv")); + + GridMap& er_node_map = layer_node_map[routing_layer.get_layer_idx()]; + for (int32_t y = er_node_map.get_y_size() - 1; y >= 0; y--) { + for (int32_t x = 0; x < er_node_map.get_x_size(); x++) { + std::map& orient_demand_map = er_node_map[x][y].get_orient_demand_map(); + int32_t total_demand = 0; + if (routing_layer.isPreferH()) { + total_demand = (orient_demand_map[Orientation::kEast] + orient_demand_map[Orientation::kWest]); + } else { + total_demand = (orient_demand_map[Orientation::kSouth] + orient_demand_map[Orientation::kNorth]); + } + RTUTIL.pushStream(demand_csv_file, total_demand, ","); + } + RTUTIL.pushStream(demand_csv_file, "\n"); + } + RTUTIL.closeFileStream(demand_csv_file); + } +} + +void EarlyRouter::outputOverflowCSV(ERModel& er_model) +{ + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::string& er_temp_directory_path = RTDM.getConfig().er_temp_directory_path; + int32_t output_inter_result = RTDM.getConfig().output_inter_result; + if (!output_inter_result) { + return; + } + std::vector>& layer_node_map = er_model.get_layer_node_map(); + for (RoutingLayer& routing_layer : routing_layer_list) { + std::ofstream* overflow_csv_file + = RTUTIL.getOutputFileStream(RTUTIL.getString(er_temp_directory_path, "overflow_map_", routing_layer.get_layer_name(), ".csv")); + + GridMap& er_node_map = layer_node_map[routing_layer.get_layer_idx()]; + for (int32_t y = er_node_map.get_y_size() - 1; y >= 0; y--) { + for (int32_t x = 0; x < er_node_map.get_x_size(); x++) { + std::map& orient_supply_map = er_node_map[x][y].get_orient_supply_map(); + std::map& orient_demand_map = er_node_map[x][y].get_orient_demand_map(); + int32_t total_overflow = 0; + if (routing_layer.isPreferH()) { + total_overflow = std::max(0, orient_demand_map[Orientation::kEast] - orient_supply_map[Orientation::kEast]) + + std::max(0, orient_demand_map[Orientation::kWest] - orient_supply_map[Orientation::kWest]); + } else { + total_overflow = std::max(0, orient_demand_map[Orientation::kSouth] - orient_supply_map[Orientation::kSouth]) + + std::max(0, orient_demand_map[Orientation::kNorth] - orient_supply_map[Orientation::kNorth]); + } + RTUTIL.pushStream(overflow_csv_file, total_overflow, ","); + } + RTUTIL.pushStream(overflow_csv_file, "\n"); + } + RTUTIL.closeFileStream(overflow_csv_file); + } +} + +#endif + +#if 1 // debug + +void EarlyRouter::debugCheckPlanarNodeMap(ERModel& er_model) +{ + GridMap& er_node_map = er_model.get_planar_node_map(); + for (int32_t x = 0; x < er_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < er_node_map.get_y_size(); y++) { + ERNode& er_node = er_node_map[x][y]; + for (auto& [orient, neighbor] : er_node.get_neighbor_node_map()) { + Orientation opposite_orient = RTUTIL.getOppositeOrientation(orient); + if (!RTUTIL.exist(neighbor->get_neighbor_node_map(), opposite_orient)) { + RTLOG.error(Loc::current(), "The er_node neighbor is not bidirectional!"); + } + if (neighbor->get_neighbor_node_map()[opposite_orient] != &er_node) { + RTLOG.error(Loc::current(), "The er_node neighbor is not bidirectional!"); + } + if (RTUTIL.getOrientation(PlanarCoord(er_node), PlanarCoord(*neighbor)) == orient) { + continue; + } + RTLOG.error(Loc::current(), "The neighbor orient is different with real region!"); + } + } + } +} + +void EarlyRouter::debugCheckLayerNodeMap(ERModel& er_model) +{ + std::vector>& layer_node_map = er_model.get_layer_node_map(); + for (GridMap& er_node_map : layer_node_map) { + for (int32_t x = 0; x < er_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < er_node_map.get_y_size(); y++) { + ERNode& er_node = er_node_map[x][y]; + for (auto& [orient, neighbor] : er_node.get_neighbor_node_map()) { + Orientation opposite_orient = RTUTIL.getOppositeOrientation(orient); + if (!RTUTIL.exist(neighbor->get_neighbor_node_map(), opposite_orient)) { + RTLOG.error(Loc::current(), "The er_node neighbor is not bidirectional!"); + } + if (neighbor->get_neighbor_node_map()[opposite_orient] != &er_node) { + RTLOG.error(Loc::current(), "The er_node neighbor is not bidirectional!"); + } + if (RTUTIL.getOrientation(LayerCoord(er_node), LayerCoord(*neighbor)) == orient) { + continue; + } + RTLOG.error(Loc::current(), "The neighbor orient is different with real region!"); + } + } + } + } +} + +#endif + +} // namespace irt diff --git a/src/operation/iRT/source/module/early_router/EarlyRouter.hpp b/src/operation/iRT/source/module/early_router/EarlyRouter.hpp new file mode 100644 index 000000000..86f77ceab --- /dev/null +++ b/src/operation/iRT/source/module/early_router/EarlyRouter.hpp @@ -0,0 +1,118 @@ +// *************************************************************************************** +// 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 "ChangeType.hpp" +#include "Config.hpp" +#include "DataManager.hpp" +#include "Database.hpp" +#include "ERModel.hpp" +#include "RTHeader.hpp" + +namespace irt { + +#define RTER (irt::EarlyRouter::getInst()) + +class EarlyRouter +{ + public: + static void initInst(); + static EarlyRouter& getInst(); + static void destroyInst(); + // function + void route(); + + private: + // self + static EarlyRouter* _er_instance; + + EarlyRouter() = default; + EarlyRouter(const EarlyRouter& other) = delete; + EarlyRouter(EarlyRouter&& other) = delete; + ~EarlyRouter() = default; + EarlyRouter& operator=(const EarlyRouter& other) = delete; + EarlyRouter& operator=(EarlyRouter&& other) = delete; + // function + ERModel initERModel(); + std::vector convertToERNetList(std::vector& net_list); + ERNet convertToERNet(Net& net); + void setERParameter(ERModel& er_model); + void generateAccessPoint(ERModel& er_model); + void initERTaskList(ERModel& er_model); + void buildPlanarNodeMap(ERModel& er_model); + void buildPlanarNodeNeighbor(ERModel& er_model); + void buildPlanarOrientSupply(ERModel& er_model); + void generateTopoTree(ERModel& er_model); + void routePlanarNet(ERModel& er_model, ERNet* er_net); + std::vector> getPlanarTopoList(ERModel& er_model, ERNet* er_net); + std::vector> getRoutingSegmentList(ERModel& er_model, Segment& planar_topo); + std::vector> getRoutingSegmentListByStraight(ERModel& er_model, Segment& planar_topo); + std::vector> getRoutingSegmentListByLPattern(ERModel& er_model, Segment& planar_topo); + double getPlanarNodeCost(ERModel& er_model, std::vector>& routing_segment_list); + MTree getPlanarCoordTree(ERNet* er_net, std::vector>& planar_routing_segment_list); + void updatePlanarDemand(ERModel& er_model, MTree& coord_tree); + void buildLayerNodeMap(ERModel& er_model); + void buildLayerNodeNeighbor(ERModel& er_model); + void buildLayerOrientSupply(ERModel& er_model); + void generateGlobalTree(ERModel& er_model); + void routeLayerNet(ERModel& er_model, ERNet* er_net); + void makeERTopoList(ERModel& er_model, ERNet* er_net, std::vector& er_topo_list, + std::vector>& routing_segment_list); + void routeERTopo(ERModel& er_model, ERTopo* er_topo); + void initSingleTask(ERModel& er_model, ERTopo* er_topo); + bool isConnectedAllEnd(ERModel& er_model); + void routeSinglePath(ERModel& er_model); + void initPathHead(ERModel& er_model); + bool searchEnded(ERModel& er_model); + void expandSearching(ERModel& er_model); + void resetPathHead(ERModel& er_model); + void updatePathResult(ERModel& er_model); + std::vector> getRoutingSegmentListByNode(ERNode* node); + void resetStartAndEnd(ERModel& er_model); + void resetSinglePath(ERModel& er_model); + void updateTaskResult(ERModel& er_model); + std::vector> getRoutingSegmentList(ERModel& er_model); + void resetSingleTask(ERModel& er_model); + void pushToOpenList(ERModel& er_model, ERNode* curr_node); + ERNode* popFromOpenList(ERModel& er_model); + double getKnowCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + double getNodeCost(ERModel& er_model, ERNode* curr_node, Orientation orientation); + double getKnowWireCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + double getKnowViaCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + double getEstimateCostToEnd(ERModel& er_model, ERNode* curr_node); + double getEstimateCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + double getEstimateWireCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + double getEstimateViaCost(ERModel& er_model, ERNode* start_node, ERNode* end_node); + MTree getLayerCoordTree(ERNet* er_net, std::vector>& routing_segment_list); + void updateLayerDemand(ERModel& er_model, ERNet* er_net, MTree& coord_tree); + void uploadNetResult(ERNet* er_net, MTree& coord_tree); + +#if 1 // exhibit + void updateSummary(ERModel& er_model); + void printSummary(ERModel& er_model); + void outputGuide(ERModel& er_model); + void outputDemandCSV(ERModel& er_model); + void outputOverflowCSV(ERModel& er_model); +#endif + +#if 1 // debug + void debugCheckPlanarNodeMap(ERModel& er_model); + void debugCheckLayerNodeMap(ERModel& er_model); +#endif +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRGroup.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERGroup.hpp similarity index 95% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRGroup.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERGroup.hpp index f5e20b770..496a51c2b 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRGroup.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERGroup.hpp @@ -20,11 +20,11 @@ namespace irt { -class IRGroup +class ERGroup { public: - IRGroup() = default; - ~IRGroup() = default; + ERGroup() = default; + ~ERGroup() = default; // getter std::vector& get_coord_list() { return _coord_list; } // setter diff --git a/src/operation/iRT/source/module/early_router/er_data_manager/ERModel.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERModel.hpp new file mode 100644 index 000000000..4a76e526e --- /dev/null +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERModel.hpp @@ -0,0 +1,104 @@ +// *************************************************************************************** +// 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 "ERNet.hpp" +#include "ERNode.hpp" +#include "ERParameter.hpp" +#include "ERTopo.hpp" +#include "PriorityQueue.hpp" + +namespace irt { + +class ERModel +{ + public: + ERModel() = default; + ~ERModel() = default; + // getter + std::vector& get_er_net_list() { return _er_net_list; } + ERParameter& get_er_parameter() { return _er_parameter; } + std::vector& get_er_task_list() { return _er_task_list; } + GridMap& get_planar_node_map() { return _planar_node_map; } + std::vector>& get_layer_node_map() { return _layer_node_map; } + // setter + void set_er_net_list(const std::vector& er_net_list) { _er_net_list = er_net_list; } + void set_er_parameter(const ERParameter& er_parameter) { _er_parameter = er_parameter; } + void set_er_task_list(const std::vector& er_task_list) { _er_task_list = er_task_list; } + void set_planar_node_map(const GridMap& planar_node_map) { _planar_node_map = planar_node_map; } + void set_layer_node_map(const std::vector>& layer_node_map) { _layer_node_map = layer_node_map; } + // function +#if 1 // astar + // single topo + ERTopo* get_curr_er_topo() { return _curr_er_topo; } + std::vector>& get_start_node_list_list() { return _start_node_list_list; } + std::vector>& get_end_node_list_list() { return _end_node_list_list; } + std::vector& get_path_node_list() { return _path_node_list; } + std::vector& get_single_topo_visited_node_list() { return _single_topo_visited_node_list; } + std::vector>& get_routing_segment_list() { return _routing_segment_list; } + void set_curr_er_topo(ERTopo* curr_er_topo) { _curr_er_topo = curr_er_topo; } + void set_start_node_list_list(const std::vector>& start_node_list_list) + { + _start_node_list_list = start_node_list_list; + } + void set_end_node_list_list(const std::vector>& end_node_list_list) { _end_node_list_list = end_node_list_list; } + void set_path_node_list(const std::vector& path_node_list) { _path_node_list = path_node_list; } + void set_single_topo_visited_node_list(const std::vector& single_topo_visited_node_list) + { + _single_topo_visited_node_list = single_topo_visited_node_list; + } + void set_routing_segment_list(const std::vector>& routing_segment_list) + { + _routing_segment_list = routing_segment_list; + } + // single path + PriorityQueue, CmpERNodeCost>& get_open_queue() { return _open_queue; } + std::vector& get_single_path_visited_node_list() { return _single_path_visited_node_list; } + ERNode* get_path_head_node() { return _path_head_node; } + int32_t get_end_node_list_idx() const { return _end_node_list_idx; } + void set_open_queue(const PriorityQueue, CmpERNodeCost>& open_queue) { _open_queue = open_queue; } + void set_single_path_visited_node_list(const std::vector& single_path_visited_node_list) + { + _single_path_visited_node_list = single_path_visited_node_list; + } + void set_path_head_node(ERNode* path_head_node) { _path_head_node = path_head_node; } + void set_end_node_list_idx(const int32_t end_node_list_idx) { _end_node_list_idx = end_node_list_idx; } +#endif + + private: + std::vector _er_net_list; + ERParameter _er_parameter; + std::vector _er_task_list; + GridMap _planar_node_map; + std::vector> _layer_node_map; +#if 1 // astar + // single topo + ERTopo* _curr_er_topo = nullptr; + std::vector> _start_node_list_list; + std::vector> _end_node_list_list; + std::vector _path_node_list; + std::vector _single_topo_visited_node_list; + std::vector> _routing_segment_list; + // single path + PriorityQueue, CmpERNodeCost> _open_queue; + std::vector _single_path_visited_node_list; + ERNode* _path_head_node = nullptr; + int32_t _end_node_list_idx = -1; +#endif +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRNet.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERNet.hpp similarity index 89% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRNet.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERNet.hpp index 903d98c18..4f3def82e 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRNet.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERNet.hpp @@ -16,32 +16,32 @@ // *************************************************************************************** #pragma once -#include "IRPin.hpp" +#include "ERPin.hpp" #include "Net.hpp" namespace irt { -class IRNet +class ERNet { public: - IRNet() = default; - ~IRNet() = default; + ERNet() = default; + ~ERNet() = default; // getter Net* get_origin_net() { return _origin_net; } int32_t get_net_idx() const { return _net_idx; } ConnectType& get_connect_type() { return _connect_type; } - std::vector& get_ir_pin_list() { return _ir_pin_list; } + std::vector& get_er_pin_list() { return _er_pin_list; } BoundingBox& get_bounding_box() { return _bounding_box; } MTree& get_topo_tree() { return _topo_tree; } // const getter const ConnectType& get_connect_type() const { return _connect_type; } - const std::vector& get_ir_pin_list() const { return _ir_pin_list; } + const std::vector& get_er_pin_list() const { return _er_pin_list; } const BoundingBox& get_bounding_box() const { return _bounding_box; } // setter void set_origin_net(Net* origin_net) { _origin_net = origin_net; } void set_net_idx(const int32_t net_idx) { _net_idx = net_idx; } void set_connect_type(const ConnectType& connect_type) { _connect_type = connect_type; } - void set_ir_pin_list(const std::vector& ir_pin_list) { _ir_pin_list = ir_pin_list; } + void set_er_pin_list(const std::vector& er_pin_list) { _er_pin_list = er_pin_list; } void set_bounding_box(const BoundingBox& bounding_box) { _bounding_box = bounding_box; } void set_topo_tree(const MTree& topo_tree) { _topo_tree = topo_tree; } // function @@ -50,14 +50,14 @@ class IRNet Net* _origin_net = nullptr; int32_t _net_idx = -1; ConnectType _connect_type = ConnectType::kNone; - std::vector _ir_pin_list; + std::vector _er_pin_list; BoundingBox _bounding_box; MTree _topo_tree; }; -struct CmpIRNet +struct CmpERNet { - bool operator()(const IRNet* a, const IRNet* b) const + bool operator()(const ERNet* a, const ERNet* b) const { SortStatus sort_status = SortStatus::kEqual; // 时钟线网优先 @@ -104,8 +104,8 @@ struct CmpIRNet } // PinNum 降序 if (sort_status == SortStatus::kEqual) { - int32_t a_pin_num = static_cast(a->get_ir_pin_list().size()); - int32_t b_pin_num = static_cast(b->get_ir_pin_list().size()); + int32_t a_pin_num = static_cast(a->get_er_pin_list().size()); + int32_t b_pin_num = static_cast(b->get_er_pin_list().size()); if (a_pin_num > b_pin_num) { sort_status = SortStatus::kTrue; } else if (a_pin_num == b_pin_num) { diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRNode.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERNode.hpp similarity index 82% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRNode.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERNode.hpp index 25d2cf30b..bbc3962c5 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRNode.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERNode.hpp @@ -25,7 +25,7 @@ namespace irt { #if 1 // astar -enum class IRNodeState +enum class ERNodeState { kNone = 0, kOpen = 1, @@ -33,23 +33,23 @@ enum class IRNodeState }; #endif -class IRNode : public LayerCoord +class ERNode : public LayerCoord { public: - IRNode() = default; - ~IRNode() = default; + ERNode() = default; + ~ERNode() = default; // getter - std::map& get_neighbor_node_map() { return _neighbor_node_map; } + std::map& get_neighbor_node_map() { return _neighbor_node_map; } std::map& get_orient_supply_map() { return _orient_supply_map; } std::map& get_orient_demand_map() { return _orient_demand_map; } // setter - void set_neighbor_node_map(const std::map& neighbor_node_map) { _neighbor_node_map = neighbor_node_map; } + void set_neighbor_node_map(const std::map& neighbor_node_map) { _neighbor_node_map = neighbor_node_map; } void set_orient_supply_map(const std::map& orient_supply_map) { _orient_supply_map = orient_supply_map; } void set_orient_demand_map(const std::map& orient_demand_map) { _orient_demand_map = orient_demand_map; } // function - IRNode* getNeighborNode(Orientation orientation) + ERNode* getNeighborNode(Orientation orientation) { - IRNode* neighbor_node = nullptr; + ERNode* neighbor_node = nullptr; if (RTUTIL.exist(_neighbor_node_map, orientation)) { neighbor_node = _neighbor_node_map[orientation]; } @@ -93,38 +93,38 @@ class IRNode : public LayerCoord } #if 1 // astar // single path - IRNodeState& get_state() { return _state; } - IRNode* get_parent_node() const { return _parent_node; } + ERNodeState& get_state() { return _state; } + ERNode* get_parent_node() const { return _parent_node; } double get_known_cost() const { return _known_cost; } double get_estimated_cost() const { return _estimated_cost; } - void set_state(IRNodeState state) { _state = state; } - void set_parent_node(IRNode* parent_node) { _parent_node = parent_node; } + void set_state(ERNodeState state) { _state = state; } + void set_parent_node(ERNode* parent_node) { _parent_node = parent_node; } void set_known_cost(const double known_cost) { _known_cost = known_cost; } void set_estimated_cost(const double estimated_cost) { _estimated_cost = estimated_cost; } // function - bool isNone() { return _state == IRNodeState::kNone; } - bool isOpen() { return _state == IRNodeState::kOpen; } - bool isClose() { return _state == IRNodeState::kClose; } + bool isNone() { return _state == ERNodeState::kNone; } + bool isOpen() { return _state == ERNodeState::kOpen; } + bool isClose() { return _state == ERNodeState::kClose; } double getTotalCost() { return (_known_cost + _estimated_cost); } #endif private: - std::map _neighbor_node_map; + std::map _neighbor_node_map; std::map _orient_supply_map; std::map _orient_demand_map; #if 1 // astar // single path - IRNodeState _state = IRNodeState::kNone; - IRNode* _parent_node = nullptr; + ERNodeState _state = ERNodeState::kNone; + ERNode* _parent_node = nullptr; double _known_cost = 0.0; // include curr double _estimated_cost = 0.0; #endif }; #if 1 // astar -struct CmpIRNodeCost +struct CmpERNodeCost { - bool operator()(IRNode* a, IRNode* b) + bool operator()(ERNode* a, ERNode* b) { if (RTUTIL.equalDoubleByError(a->getTotalCost(), b->getTotalCost(), RT_ERROR)) { if (RTUTIL.equalDoubleByError(a->get_estimated_cost(), b->get_estimated_cost(), RT_ERROR)) { diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRParameter.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERParameter.hpp similarity index 93% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRParameter.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERParameter.hpp index 9d8a9694c..4338e283d 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRParameter.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERParameter.hpp @@ -18,18 +18,18 @@ namespace irt { -class IRParameter +class ERParameter { public: - IRParameter() = default; - IRParameter(int32_t topo_spilt_length, double congestion_unit, double prefer_wire_unit, double via_unit) + ERParameter() = default; + ERParameter(int32_t topo_spilt_length, double congestion_unit, double prefer_wire_unit, double via_unit) { _topo_spilt_length = 10; _congestion_unit = 2; _prefer_wire_unit = 1; _via_unit = 1; } - ~IRParameter() = default; + ~ERParameter() = default; // getter int32_t get_topo_spilt_length() const { return _topo_spilt_length; } double get_congestion_unit() const { return _congestion_unit; } diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRPin.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERPin.hpp similarity index 90% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRPin.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERPin.hpp index 89c7a857e..bc0f368d4 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRPin.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERPin.hpp @@ -23,12 +23,12 @@ namespace irt { -class IRPin : public Pin +class ERPin : public Pin { public: - IRPin() = default; - explicit IRPin(const Pin& pin) : Pin(pin) {} - ~IRPin() = default; + ERPin() = default; + explicit ERPin(const Pin& pin) : Pin(pin) {} + ~ERPin() = default; // getter // setter diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRTopo.hpp b/src/operation/iRT/source/module/early_router/er_data_manager/ERTopo.hpp similarity index 82% rename from src/operation/iRT/source/module/initial_router/ir_data_manager/IRTopo.hpp rename to src/operation/iRT/source/module/early_router/er_data_manager/ERTopo.hpp index 37f4b20ec..a10da596d 100644 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRTopo.hpp +++ b/src/operation/iRT/source/module/early_router/er_data_manager/ERTopo.hpp @@ -16,26 +16,26 @@ // *************************************************************************************** #pragma once -#include "IRGroup.hpp" +#include "ERGroup.hpp" namespace irt { -class IRTopo +class ERTopo { public: - IRTopo() = default; - ~IRTopo() = default; + ERTopo() = default; + ~ERTopo() = default; // getter int32_t get_net_idx() { return _net_idx; } - std::vector& get_ir_group_list() { return _ir_group_list; } + std::vector& get_er_group_list() { return _er_group_list; } PlanarRect& get_bounding_box() { return _bounding_box; } std::vector>& get_routing_segment_list() { return _routing_segment_list; } // const getter - const std::vector& get_ir_group_list() const { return _ir_group_list; } + const std::vector& get_er_group_list() const { return _er_group_list; } const PlanarRect& get_bounding_box() const { return _bounding_box; } // setter void set_net_idx(const int32_t net_idx) { _net_idx = net_idx; } - void set_ir_group_list(const std::vector& ir_group_list) { _ir_group_list = ir_group_list; } + void set_er_group_list(const std::vector& er_group_list) { _er_group_list = er_group_list; } void set_bounding_box(const PlanarRect& bounding_box) { _bounding_box = bounding_box; } void set_routing_segment_list(const std::vector>& routing_segment_list) { @@ -45,7 +45,7 @@ class IRTopo private: int32_t _net_idx = -1; - std::vector _ir_group_list; + std::vector _er_group_list; PlanarRect _bounding_box; std::vector> _routing_segment_list; }; diff --git a/src/operation/iRT/source/module/early_router/framwork.txt b/src/operation/iRT/source/module/early_router/framwork.txt new file mode 100644 index 000000000..d3d3294ff --- /dev/null +++ b/src/operation/iRT/source/module/early_router/framwork.txt @@ -0,0 +1,12 @@ +initERModel:初始化ERModel +setERParameter:设置布线参数 +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:生成全局布线结果 \ No newline at end of file diff --git a/src/operation/iRT/source/module/gds_plotter/GDSPlotter.cpp b/src/operation/iRT/source/module/gds_plotter/GDSPlotter.cpp index 2acbda563..ea85890c9 100644 --- a/src/operation/iRT/source/module/gds_plotter/GDSPlotter.cpp +++ b/src/operation/iRT/source/module/gds_plotter/GDSPlotter.cpp @@ -51,6 +51,12 @@ void GDSPlotter::destroyInst() // function +void GDSPlotter::init() +{ + buildGDSLayerMap(); + buildGraphLypFile(); +} + void GDSPlotter::plot(GPGDS& gp_gds, std::string gds_file_path) { buildTopStruct(gp_gds); @@ -84,12 +90,6 @@ int32_t GDSPlotter::getGDSIdxByCut(int32_t cut_layer_idx) GDSPlotter* GDSPlotter::_gp_instance = nullptr; -void GDSPlotter::init() -{ - buildGDSLayerMap(); - buildGraphLypFile(); -} - void GDSPlotter::buildGDSLayerMap() { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); diff --git a/src/operation/iRT/source/module/gds_plotter/GDSPlotter.hpp b/src/operation/iRT/source/module/gds_plotter/GDSPlotter.hpp index 2e3344b82..32a709bc4 100644 --- a/src/operation/iRT/source/module/gds_plotter/GDSPlotter.hpp +++ b/src/operation/iRT/source/module/gds_plotter/GDSPlotter.hpp @@ -37,6 +37,7 @@ class GDSPlotter static GDSPlotter& getInst(); static void destroyInst(); // function + void init(); void plot(GPGDS& gp_gds, std::string gds_file_path); int32_t getGDSIdxByRouting(int32_t layer_idx); int32_t getGDSIdxByCut(int32_t below_layer_idx); @@ -49,14 +50,13 @@ class GDSPlotter std::map _gds_routing_layer_map; std::map _gds_cut_layer_map; - GDSPlotter() { init(); } + GDSPlotter() = default; GDSPlotter(const GDSPlotter& other) = delete; GDSPlotter(GDSPlotter&& other) = delete; ~GDSPlotter() = default; GDSPlotter& operator=(const GDSPlotter& other) = delete; GDSPlotter& operator=(GDSPlotter&& other) = delete; // function - void init(); void buildGDSLayerMap(); void buildGraphLypFile(); void writeLypFile(std::string lyp_file_path, std::vector& lyp_layer_list); diff --git a/src/operation/iRT/source/module/initial_router/CMakeLists.txt b/src/operation/iRT/source/module/initial_router/CMakeLists.txt deleted file mode 100644 index 35d325f94..000000000 --- a/src/operation/iRT/source/module/initial_router/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -if(DEBUG_IRT_INITIAL_ROUTER) - message(STATUS "RT: DEBUG_IRT_INITIAL_ROUTER") - set(CMAKE_BUILD_TYPE "Debug") -else() - message(STATUS "RT: RELEASE_IRT_INITIAL_ROUTER") - set(CMAKE_BUILD_TYPE "Release") -endif() - -add_library(irt_initial_router - ## module initial_router - ${IRT_MODULE}/initial_router/InitialRouter.cpp -) - -target_link_libraries(irt_initial_router - PUBLIC - irt_data_manager - irt_module - irt_toolkit -) - -target_include_directories(irt_initial_router - PUBLIC - ${IRT_MODULE}/initial_router/ir_data_manager - ${IRT_MODULE}/initial_router -) diff --git a/src/operation/iRT/source/module/initial_router/InitialRouter.hpp b/src/operation/iRT/source/module/initial_router/InitialRouter.hpp deleted file mode 100644 index cb8675fc9..000000000 --- a/src/operation/iRT/source/module/initial_router/InitialRouter.hpp +++ /dev/null @@ -1,105 +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 "ChangeType.hpp" -#include "Config.hpp" -#include "DataManager.hpp" -#include "Database.hpp" -#include "IRModel.hpp" -#include "RTHeader.hpp" - -namespace irt { - -#define RTIR (irt::InitialRouter::getInst()) - -class InitialRouter -{ - public: - static void initInst(); - static InitialRouter& getInst(); - static void destroyInst(); - // function - void route(); - - private: - // self - static InitialRouter* _ir_instance; - - InitialRouter() = default; - InitialRouter(const InitialRouter& other) = delete; - InitialRouter(InitialRouter&& other) = delete; - ~InitialRouter() = default; - InitialRouter& operator=(const InitialRouter& other) = delete; - InitialRouter& operator=(InitialRouter&& other) = delete; - // function - IRModel initIRModel(); - std::vector convertToIRNetList(std::vector& net_list); - IRNet convertToIRNet(Net& net); - void initIRTaskList(IRModel& ir_model); - void setIRParameter(IRModel& ir_model); - void buildLayerNodeMap(IRModel& ir_model); - void buildIRNodeNeighbor(IRModel& ir_model); - void buildOrientSupply(IRModel& ir_model); - void buildTopoTree(IRModel& ir_model); - void routeIRModel(IRModel& ir_model); - void routeIRNet(IRModel& ir_model, IRNet* ir_net); - void makeIRTopoList(IRModel& ir_model, IRNet* ir_net, std::vector& ir_topo_list, - std::vector>& routing_segment_list); - void routeIRTopo(IRModel& ir_model, IRTopo* ir_topo); - void initSingleTask(IRModel& ir_model, IRTopo* ir_topo); - bool isConnectedAllEnd(IRModel& ir_model); - void routeSinglePath(IRModel& ir_model); - void initPathHead(IRModel& ir_model); - bool searchEnded(IRModel& ir_model); - void expandSearching(IRModel& ir_model); - void resetPathHead(IRModel& ir_model); - void updatePathResult(IRModel& ir_model); - std::vector> getRoutingSegmentListByNode(IRNode* node); - void resetStartAndEnd(IRModel& ir_model); - void resetSinglePath(IRModel& ir_model); - void updateTaskResult(IRModel& ir_model); - std::vector> getRoutingSegmentList(IRModel& ir_model); - void resetSingleTask(IRModel& ir_model); - void pushToOpenList(IRModel& ir_model, IRNode* curr_node); - IRNode* popFromOpenList(IRModel& ir_model); - double getKnowCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - double getNodeCost(IRModel& ir_model, IRNode* curr_node, Orientation orientation); - double getKnowWireCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - double getKnowViaCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - double getEstimateCostToEnd(IRModel& ir_model, IRNode* curr_node); - double getEstimateCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - double getEstimateWireCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - double getEstimateViaCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node); - MTree getCoordTree(IRNet* ir_net, std::vector>& routing_segment_list); - void updateDemand(IRModel& ir_model, IRNet* ir_net, MTree& coord_tree); - void uploadNetResult(IRNet* ir_net, MTree& coord_tree); - -#if 1 // exhibit - void updateSummary(IRModel& ir_model); - void printSummary(IRModel& ir_model); - void outputDemandCSV(IRModel& ir_model); - void outputOverflowCSV(IRModel& ir_model); -#endif - -#if 1 // debug - void debugCheckIRModel(IRModel& ir_model); - void outputGuide(IRModel& ir_model); -#endif -}; - -} // namespace irt diff --git a/src/operation/iRT/source/module/initial_router/framwork.txt b/src/operation/iRT/source/module/initial_router/framwork.txt deleted file mode 100644 index d7166a8de..000000000 --- a/src/operation/iRT/source/module/initial_router/framwork.txt +++ /dev/null @@ -1,12 +0,0 @@ -initIRModel:初始化ir_net_list -setIRParameter:设置布线参数 -buildLayerNodeMap:初始化graph -buildIRNodeNeighbor:构建graph的邻居 -buildOrientSupply:从supply_analyzer获取supply的access -sortIRModel:对ir_net进行排序 -routeIRModel: - routeIRNet:一个接一个的ir_net进行布线 - makeIRTaskList:通过flute获取多个topo,并将每个topo构建成task,通过加入斯坦纳点的垂直线段 - routeIRTask:布线 - updateDemand:将布线结果添加到graph上 -updateIRModel:将结果更新到顶层 \ No newline at end of file diff --git a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRModel.hpp b/src/operation/iRT/source/module/initial_router/ir_data_manager/IRModel.hpp deleted file mode 100644 index 8fc977df8..000000000 --- a/src/operation/iRT/source/module/initial_router/ir_data_manager/IRModel.hpp +++ /dev/null @@ -1,101 +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 "IRNet.hpp" -#include "IRNode.hpp" -#include "IRParameter.hpp" -#include "IRTopo.hpp" -#include "PriorityQueue.hpp" - -namespace irt { - -class IRModel -{ - public: - IRModel() = default; - ~IRModel() = default; - // getter - std::vector& get_ir_net_list() { return _ir_net_list; } - IRParameter& get_ir_parameter() { return _ir_parameter; } - std::vector& get_ir_task_list() { return _ir_task_list; } - std::vector>& get_layer_node_map() { return _layer_node_map; } - // setter - void set_ir_net_list(const std::vector& ir_net_list) { _ir_net_list = ir_net_list; } - void set_ir_parameter(const IRParameter& ir_parameter) { _ir_parameter = ir_parameter; } - void set_ir_task_list(const std::vector& ir_task_list) { _ir_task_list = ir_task_list; } - void set_layer_node_map(const std::vector>& layer_node_map) { _layer_node_map = layer_node_map; } - // function -#if 1 // astar - // single topo - IRTopo* get_curr_ir_topo() { return _curr_ir_topo; } - std::vector>& get_start_node_list_list() { return _start_node_list_list; } - std::vector>& get_end_node_list_list() { return _end_node_list_list; } - std::vector& get_path_node_list() { return _path_node_list; } - std::vector& get_single_topo_visited_node_list() { return _single_topo_visited_node_list; } - std::vector>& get_routing_segment_list() { return _routing_segment_list; } - void set_curr_ir_topo(IRTopo* curr_ir_topo) { _curr_ir_topo = curr_ir_topo; } - void set_start_node_list_list(const std::vector>& start_node_list_list) - { - _start_node_list_list = start_node_list_list; - } - void set_end_node_list_list(const std::vector>& end_node_list_list) { _end_node_list_list = end_node_list_list; } - void set_path_node_list(const std::vector& path_node_list) { _path_node_list = path_node_list; } - void set_single_topo_visited_node_list(const std::vector& single_topo_visited_node_list) - { - _single_topo_visited_node_list = single_topo_visited_node_list; - } - void set_routing_segment_list(const std::vector>& routing_segment_list) - { - _routing_segment_list = routing_segment_list; - } - // single path - PriorityQueue, CmpIRNodeCost>& get_open_queue() { return _open_queue; } - std::vector& get_single_path_visited_node_list() { return _single_path_visited_node_list; } - IRNode* get_path_head_node() { return _path_head_node; } - int32_t get_end_node_list_idx() const { return _end_node_list_idx; } - void set_open_queue(const PriorityQueue, CmpIRNodeCost>& open_queue) { _open_queue = open_queue; } - void set_single_path_visited_node_list(const std::vector& single_path_visited_node_list) - { - _single_path_visited_node_list = single_path_visited_node_list; - } - void set_path_head_node(IRNode* path_head_node) { _path_head_node = path_head_node; } - void set_end_node_list_idx(const int32_t end_node_list_idx) { _end_node_list_idx = end_node_list_idx; } -#endif - - private: - std::vector _ir_net_list; - IRParameter _ir_parameter; - std::vector _ir_task_list; - std::vector> _layer_node_map; -#if 1 // astar - // single topo - IRTopo* _curr_ir_topo = nullptr; - std::vector> _start_node_list_list; - std::vector> _end_node_list_list; - std::vector _path_node_list; - std::vector _single_topo_visited_node_list; - std::vector> _routing_segment_list; - // single path - PriorityQueue, CmpIRNodeCost> _open_queue; - std::vector _single_path_visited_node_list; - IRNode* _path_head_node = nullptr; - int32_t _end_node_list_idx = -1; -#endif -}; - -} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/CMakeLists.txt b/src/operation/iRT/source/module/layer_assigner/CMakeLists.txt new file mode 100644 index 000000000..1a5c5fd0a --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/CMakeLists.txt @@ -0,0 +1,25 @@ +if(DEBUG_IRT_LAYER_ASSIGNER) + message(STATUS "RT: DEBUG_IRT_LAYER_ASSIGNER") + set(CMAKE_BUILD_TYPE "Debug") +else() + message(STATUS "RT: RELEASE_IRT_LAYER_ASSIGNER") + set(CMAKE_BUILD_TYPE "Release") +endif() + +add_library(irt_layer_assigner + ## module layer_assigner + ${IRT_MODULE}/layer_assigner/LayerAssigner.cpp +) + +target_link_libraries(irt_layer_assigner + PUBLIC + irt_data_manager + irt_module + irt_toolkit +) + +target_include_directories(irt_layer_assigner + PUBLIC + ${IRT_MODULE}/layer_assigner/la_data_manager + ${IRT_MODULE}/layer_assigner +) diff --git a/src/operation/iRT/source/module/initial_router/InitialRouter.cpp b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp similarity index 61% rename from src/operation/iRT/source/module/initial_router/InitialRouter.cpp rename to src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp index d94e65340..e3052ca89 100644 --- a/src/operation/iRT/source/module/initial_router/InitialRouter.cpp +++ b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp @@ -14,7 +14,7 @@ // // See the Mulan PSL v2 for more details. // *************************************************************************************** -#include "InitialRouter.hpp" +#include "LayerAssigner.hpp" #include "GDSPlotter.hpp" #include "Monitor.hpp" @@ -25,113 +25,119 @@ namespace irt { // public -void InitialRouter::initInst() +void LayerAssigner::initInst() { - if (_ir_instance == nullptr) { - _ir_instance = new InitialRouter(); + if (_la_instance == nullptr) { + _la_instance = new LayerAssigner(); } } -InitialRouter& InitialRouter::getInst() +LayerAssigner& LayerAssigner::getInst() { - if (_ir_instance == nullptr) { + if (_la_instance == nullptr) { RTLOG.error(Loc::current(), "The instance not initialized!"); } - return *_ir_instance; + return *_la_instance; } -void InitialRouter::destroyInst() +void LayerAssigner::destroyInst() { - if (_ir_instance != nullptr) { - delete _ir_instance; - _ir_instance = nullptr; + if (_la_instance != nullptr) { + delete _la_instance; + _la_instance = nullptr; } } // function -void InitialRouter::route() +void LayerAssigner::route() { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); - IRModel ir_model = initIRModel(); - setIRParameter(ir_model); - initIRTaskList(ir_model); - buildLayerNodeMap(ir_model); - buildIRNodeNeighbor(ir_model); - buildOrientSupply(ir_model); - // debugCheckIRModel(ir_model); - buildTopoTree(ir_model); - routeIRModel(ir_model); - updateSummary(ir_model); - printSummary(ir_model); - outputGuide(ir_model); - outputDemandCSV(ir_model); - outputOverflowCSV(ir_model); + LAModel la_model = initLAModel(); + setLAParameter(la_model); + initLATaskList(la_model); + buildLayerNodeMap(la_model); + buildLANodeNeighbor(la_model); + buildOrientSupply(la_model); + // debugCheckLAModel(la_model); + buildTopoTree(la_model); + routeLAModel(la_model); + updateSummary(la_model); + printSummary(la_model); + outputGuide(la_model); + outputDemandCSV(la_model); + outputOverflowCSV(la_model); RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } // private -InitialRouter* InitialRouter::_ir_instance = nullptr; +LayerAssigner* LayerAssigner::_la_instance = nullptr; -IRModel InitialRouter::initIRModel() +LAModel LayerAssigner::initLAModel() { std::vector& net_list = RTDM.getDatabase().get_net_list(); - IRModel ir_model; - ir_model.set_ir_net_list(convertToIRNetList(net_list)); - return ir_model; + LAModel la_model; + la_model.set_la_net_list(convertToLANetList(net_list)); + return la_model; } -std::vector InitialRouter::convertToIRNetList(std::vector& net_list) +std::vector LayerAssigner::convertToLANetList(std::vector& net_list) { - std::vector ir_net_list; - ir_net_list.reserve(net_list.size()); + std::vector la_net_list; + la_net_list.reserve(net_list.size()); for (size_t i = 0; i < net_list.size(); i++) { - ir_net_list.emplace_back(convertToIRNet(net_list[i])); + la_net_list.emplace_back(convertToLANet(net_list[i])); } - return ir_net_list; + return la_net_list; } -IRNet InitialRouter::convertToIRNet(Net& net) +LANet LayerAssigner::convertToLANet(Net& net) { - IRNet ir_net; - ir_net.set_origin_net(&net); - ir_net.set_net_idx(net.get_net_idx()); - ir_net.set_connect_type(net.get_connect_type()); + LANet la_net; + la_net.set_origin_net(&net); + la_net.set_net_idx(net.get_net_idx()); + la_net.set_connect_type(net.get_connect_type()); for (Pin& pin : net.get_pin_list()) { - ir_net.get_ir_pin_list().push_back(IRPin(pin)); + la_net.get_la_pin_list().push_back(LAPin(pin)); } - ir_net.set_bounding_box(net.get_bounding_box()); - return ir_net; + la_net.set_bounding_box(net.get_bounding_box()); + return la_net; } -void InitialRouter::setIRParameter(IRModel& ir_model) +void LayerAssigner::setLAParameter(LAModel& la_model) { + int32_t topo_spilt_length = 10; + double congestion_unit = 2; + double prefer_wire_unit = 1; + double via_unit = 1; /** * topo_spilt_length, congestion_unit, prefer_wire_unit, via_unit */ - IRParameter ir_parameter(10, 2, 1, 1); - RTLOG.info(Loc::current(), "topo_spilt_length: ", ir_parameter.get_topo_spilt_length()); - RTLOG.info(Loc::current(), "congestion_unit: ", ir_parameter.get_congestion_unit()); - RTLOG.info(Loc::current(), "prefer_wire_unit: ", ir_parameter.get_prefer_wire_unit()); - RTLOG.info(Loc::current(), "via_unit: ", ir_parameter.get_via_unit()); - ir_model.set_ir_parameter(ir_parameter); + // clang-format off + LAParameter la_parameter(topo_spilt_length, congestion_unit, prefer_wire_unit, via_unit); + // clang-format on + RTLOG.info(Loc::current(), "topo_spilt_length: ", la_parameter.get_topo_spilt_length()); + RTLOG.info(Loc::current(), "congestion_unit: ", la_parameter.get_congestion_unit()); + RTLOG.info(Loc::current(), "prefer_wire_unit: ", la_parameter.get_prefer_wire_unit()); + RTLOG.info(Loc::current(), "via_unit: ", la_parameter.get_via_unit()); + la_model.set_la_parameter(la_parameter); } -void InitialRouter::initIRTaskList(IRModel& ir_model) +void LayerAssigner::initLATaskList(LAModel& la_model) { - std::vector& ir_net_list = ir_model.get_ir_net_list(); - std::vector& ir_task_list = ir_model.get_ir_task_list(); - ir_task_list.reserve(ir_net_list.size()); - for (IRNet& ir_net : ir_net_list) { - ir_task_list.push_back(&ir_net); + std::vector& la_net_list = la_model.get_la_net_list(); + std::vector& la_task_list = la_model.get_la_task_list(); + la_task_list.reserve(la_net_list.size()); + for (LANet& la_net : la_net_list) { + la_task_list.push_back(&la_net); } - std::sort(ir_task_list.begin(), ir_task_list.end(), CmpIRNet()); + std::sort(la_task_list.begin(), la_task_list.end(), CmpLANet()); } -void InitialRouter::buildLayerNodeMap(IRModel& ir_model) +void LayerAssigner::buildLayerNodeMap(LAModel& la_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); @@ -139,17 +145,17 @@ void InitialRouter::buildLayerNodeMap(IRModel& ir_model) GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::vector>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); layer_node_map.resize(routing_layer_list.size()); #pragma omp parallel for for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { - GridMap& ir_node_map = layer_node_map[layer_idx]; - ir_node_map.init(gcell_map.get_x_size(), gcell_map.get_y_size()); + GridMap& la_node_map = layer_node_map[layer_idx]; + la_node_map.init(gcell_map.get_x_size(), gcell_map.get_y_size()); for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { - IRNode& ir_node = ir_node_map[x][y]; - ir_node.set_coord(x, y); - ir_node.set_layer_idx(layer_idx); + LANode& la_node = la_node_map[x][y]; + la_node.set_coord(x, y); + la_node.set_layer_idx(layer_idx); } } } @@ -157,7 +163,7 @@ void InitialRouter::buildLayerNodeMap(IRModel& ir_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void InitialRouter::buildIRNodeNeighbor(IRModel& ir_model) +void LayerAssigner::buildLANodeNeighbor(LAModel& la_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); @@ -167,7 +173,7 @@ void InitialRouter::buildIRNodeNeighbor(IRModel& ir_model) 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>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); #pragma omp parallel for for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { @@ -177,24 +183,24 @@ void InitialRouter::buildIRNodeNeighbor(IRModel& ir_model) routing_h = false; routing_v = false; } - GridMap& ir_node_map = layer_node_map[layer_idx]; + GridMap& la_node_map = layer_node_map[layer_idx]; for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { for (int32_t y = 0; y < gcell_map.get_y_size(); y++) { - std::map& neighbor_node_map = ir_node_map[x][y].get_neighbor_node_map(); + std::map& neighbor_node_map = la_node_map[x][y].get_neighbor_node_map(); if (routing_h) { if (x != 0) { - neighbor_node_map[Orientation::kWest] = &ir_node_map[x - 1][y]; + neighbor_node_map[Orientation::kWest] = &la_node_map[x - 1][y]; } - if (x != (ir_node_map.get_x_size() - 1)) { - neighbor_node_map[Orientation::kEast] = &ir_node_map[x + 1][y]; + if (x != (la_node_map.get_x_size() - 1)) { + neighbor_node_map[Orientation::kEast] = &la_node_map[x + 1][y]; } } if (routing_v) { if (y != 0) { - neighbor_node_map[Orientation::kSouth] = &ir_node_map[x][y - 1]; + neighbor_node_map[Orientation::kSouth] = &la_node_map[x][y - 1]; } - if (y != (ir_node_map.get_y_size() - 1)) { - neighbor_node_map[Orientation::kNorth] = &ir_node_map[x][y + 1]; + if (y != (la_node_map.get_y_size() - 1)) { + neighbor_node_map[Orientation::kNorth] = &la_node_map[x][y + 1]; } } if (layer_idx != 0) { @@ -210,14 +216,14 @@ void InitialRouter::buildIRNodeNeighbor(IRModel& ir_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void InitialRouter::buildOrientSupply(IRModel& ir_model) +void LayerAssigner::buildOrientSupply(LAModel& la_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); - std::vector>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); #pragma omp parallel for collapse(2) for (int32_t x = 0; x < gcell_map.get_x_size(); x++) { @@ -231,17 +237,17 @@ void InitialRouter::buildOrientSupply(IRModel& ir_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void InitialRouter::buildTopoTree(IRModel& ir_model) +void LayerAssigner::buildTopoTree(LAModel& la_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); Die& die = RTDM.getDatabase().get_die(); - std::vector& ir_net_list = ir_model.get_ir_net_list(); + std::vector& la_net_list = la_model.get_la_net_list(); for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { - IRNet& ir_net = ir_net_list[net_idx]; + LANet& la_net = la_net_list[net_idx]; std::vector> routing_segment_list; for (Segment* segment : segment_set) { @@ -249,13 +255,13 @@ void InitialRouter::buildTopoTree(IRModel& ir_model) } std::vector candidate_root_coord_list; std::map, CmpLayerCoordByXASC> key_coord_pin_map; - std::vector& ir_pin_list = ir_net.get_ir_pin_list(); - for (size_t i = 0; i < ir_pin_list.size(); i++) { - LayerCoord coord(ir_pin_list[i].get_access_point().get_grid_coord(), 0); + std::vector& la_pin_list = la_net.get_la_pin_list(); + for (size_t i = 0; i < la_pin_list.size(); i++) { + LayerCoord coord(la_pin_list[i].get_access_point().get_grid_coord(), 0); candidate_root_coord_list.push_back(coord); key_coord_pin_map[coord].insert(static_cast(i)); } - ir_net.set_topo_tree(RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map)); + la_net.set_topo_tree(RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map)); } for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { for (Segment* segment : segment_set) { @@ -265,20 +271,20 @@ void InitialRouter::buildTopoTree(IRModel& ir_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void InitialRouter::routeIRModel(IRModel& ir_model) +void LayerAssigner::routeLAModel(LAModel& la_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); - std::vector& ir_task_list = ir_model.get_ir_task_list(); + std::vector& la_task_list = la_model.get_la_task_list(); - int32_t batch_size = RTUTIL.getBatchSize(ir_task_list.size()); + int32_t batch_size = RTUTIL.getBatchSize(la_task_list.size()); Monitor stage_monitor; - for (size_t i = 0; i < ir_task_list.size(); i++) { - routeIRNet(ir_model, ir_task_list[i]); - if ((i + 1) % batch_size == 0 || (i + 1) == ir_task_list.size()) { - RTLOG.info(Loc::current(), "Routed ", (i + 1), "/", ir_task_list.size(), "(", RTUTIL.getPercentage(i + 1, ir_task_list.size()), + for (size_t i = 0; i < la_task_list.size(); i++) { + routeLANet(la_model, la_task_list[i]); + if ((i + 1) % batch_size == 0 || (i + 1) == la_task_list.size()) { + RTLOG.info(Loc::current(), "Routed ", (i + 1), "/", la_task_list.size(), "(", RTUTIL.getPercentage(i + 1, la_task_list.size()), ") nets", stage_monitor.getStatsInfo()); } } @@ -286,43 +292,56 @@ void InitialRouter::routeIRModel(IRModel& ir_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void InitialRouter::routeIRNet(IRModel& ir_model, IRNet* ir_net) +void LayerAssigner::routeLANet(LAModel& la_model, LANet* la_net) { - // 构建ir_topo_list,并将通孔线段加入routing_segment_list - std::vector ir_topo_list; + // 构建la_topo_list,并将通孔线段加入routing_segment_list + std::vector la_topo_list; std::vector> routing_segment_list; - makeIRTopoList(ir_model, ir_net, ir_topo_list, routing_segment_list); - for (IRTopo& ir_topo : ir_topo_list) { - routeIRTopo(ir_model, &ir_topo); - for (Segment& routing_segment : ir_topo.get_routing_segment_list()) { + makeLATopoList(la_model, la_net, la_topo_list, routing_segment_list); + for (LATopo& la_topo : la_topo_list) { + routeLATopo(la_model, &la_topo); + for (Segment& routing_segment : la_topo.get_routing_segment_list()) { routing_segment_list.push_back(routing_segment); } } - MTree coord_tree = getCoordTree(ir_net, routing_segment_list); - updateDemand(ir_model, ir_net, coord_tree); - uploadNetResult(ir_net, coord_tree); + MTree coord_tree = getCoordTree(la_net, routing_segment_list); + updateDemand(la_model, la_net, coord_tree); + uploadNetResult(la_net, coord_tree); } -void InitialRouter::makeIRTopoList(IRModel& ir_model, IRNet* ir_net, std::vector& ir_topo_list, +void LayerAssigner::makeLATopoList(LAModel& la_model, LANet* la_net, std::vector& la_topo_list, std::vector>& routing_segment_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; - int32_t topo_spilt_length = ir_model.get_ir_parameter().get_topo_spilt_length(); + int32_t topo_spilt_length = la_model.get_la_parameter().get_topo_spilt_length(); - if (ir_net->get_topo_tree().get_root() == nullptr) { - IRTopo ir_topo; - for (IRPin& ir_pin : ir_net->get_ir_pin_list()) { - IRGroup ir_group; - ir_group.get_coord_list().push_back(ir_pin.get_access_point().getGridLayerCoord()); - ir_topo.get_ir_group_list().push_back(ir_group); + if (la_net->get_topo_tree().get_root() == nullptr) { + LATopo la_topo; + for (LAPin& la_pin : la_net->get_la_pin_list()) { + LAGroup la_group; + la_group.get_coord_list().push_back(la_pin.get_access_point().getGridLayerCoord()); + la_topo.get_la_group_list().push_back(la_group); + } + la_topo_list.push_back(la_topo); + { + std::set coord_set; + for (LATopo& la_topo : la_topo_list) { + for (LAGroup& la_group : la_topo.get_la_group_list()) { + for (LayerCoord& coord : la_group.get_coord_list()) { + coord_set.insert(coord); + } + } + } + if (coord_set.size() > 1) { + RTLOG.error(Loc::current(), "The topo_tree should not be empty!"); + } } - ir_topo_list.push_back(ir_topo); } else { // planar_topo_list std::vector> planar_topo_list; { - for (Segment*>& coord_segment : RTUTIL.getSegListByTree(ir_net->get_topo_tree())) { + for (Segment*>& coord_segment : RTUTIL.getSegListByTree(la_net->get_topo_tree())) { PlanarCoord& first_coord = coord_segment.get_first()->value(); PlanarCoord& second_coord = coord_segment.get_second()->value(); int32_t first_x = first_coord.get_x(); @@ -361,18 +380,18 @@ void InitialRouter::makeIRTopoList(IRModel& ir_model, IRNet* ir_net, std::vector } } // planar_pin_group_map - std::map, CmpPlanarCoordByXASC> planar_pin_group_map; + std::map, CmpPlanarCoordByXASC> planar_pin_group_map; { - for (IRPin& ir_pin : ir_net->get_ir_pin_list()) { - LayerCoord grid_coord = ir_pin.get_access_point().getGridLayerCoord(); + for (LAPin& la_pin : la_net->get_la_pin_list()) { + LayerCoord grid_coord = la_pin.get_access_point().getGridLayerCoord(); - IRGroup ir_group; - ir_group.get_coord_list().push_back(grid_coord); - planar_pin_group_map[grid_coord.get_planar_coord()].push_back(ir_group); + LAGroup la_group; + la_group.get_coord_list().push_back(grid_coord); + planar_pin_group_map[grid_coord.get_planar_coord()].push_back(la_group); } } // planar_steiner_group_map - std::map planar_steiner_group_map; + std::map planar_steiner_group_map; { for (Segment& planar_topo : planar_topo_list) { for (PlanarCoord coord : {planar_topo.get_first(), planar_topo.get_second()}) { @@ -389,123 +408,123 @@ void InitialRouter::makeIRTopoList(IRModel& ir_model, IRNet* ir_net, std::vector // 生成topo group { for (Segment& planar_topo : planar_topo_list) { - IRTopo ir_topo; + LATopo la_topo; for (PlanarCoord coord : {planar_topo.get_first(), planar_topo.get_second()}) { if (RTUTIL.exist(planar_pin_group_map, coord)) { - for (IRGroup& ir_group : planar_pin_group_map[coord]) { - ir_topo.get_ir_group_list().push_back(ir_group); + for (LAGroup& la_group : planar_pin_group_map[coord]) { + la_topo.get_la_group_list().push_back(la_group); } } else if (RTUTIL.exist(planar_steiner_group_map, coord)) { - ir_topo.get_ir_group_list().push_back(planar_steiner_group_map[coord]); + la_topo.get_la_group_list().push_back(planar_steiner_group_map[coord]); } } - ir_topo_list.push_back(ir_topo); + la_topo_list.push_back(la_topo); } } } // 构建topo的其他内容 { - for (IRTopo& ir_topo : ir_topo_list) { - ir_topo.set_net_idx(ir_net->get_net_idx()); + for (LATopo& la_topo : la_topo_list) { + la_topo.set_net_idx(la_net->get_net_idx()); std::vector coord_list; - for (IRGroup& ir_group : ir_topo.get_ir_group_list()) { - for (LayerCoord& coord : ir_group.get_coord_list()) { + for (LAGroup& la_group : la_topo.get_la_group_list()) { + for (LayerCoord& coord : la_group.get_coord_list()) { coord_list.push_back(coord); } } - ir_topo.set_bounding_box(RTUTIL.getBoundingBox(coord_list)); + la_topo.set_bounding_box(RTUTIL.getBoundingBox(coord_list)); } } } -void InitialRouter::routeIRTopo(IRModel& ir_model, IRTopo* ir_topo) +void LayerAssigner::routeLATopo(LAModel& la_model, LATopo* la_topo) { - initSingleTask(ir_model, ir_topo); - while (!isConnectedAllEnd(ir_model)) { - routeSinglePath(ir_model); - updatePathResult(ir_model); - resetStartAndEnd(ir_model); - resetSinglePath(ir_model); + initSingleTask(la_model, la_topo); + while (!isConnectedAllEnd(la_model)) { + routeSinglePath(la_model); + updatePathResult(la_model); + resetStartAndEnd(la_model); + resetSinglePath(la_model); } - updateTaskResult(ir_model); - resetSingleTask(ir_model); + updateTaskResult(la_model); + resetSingleTask(la_model); } -void InitialRouter::initSingleTask(IRModel& ir_model, IRTopo* ir_topo) +void LayerAssigner::initSingleTask(LAModel& la_model, LATopo* la_topo) { - std::vector>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); // single topo - ir_model.set_curr_ir_topo(ir_topo); + la_model.set_curr_la_topo(la_topo); { - std::vector> node_list_list; - std::vector& ir_group_list = ir_topo->get_ir_group_list(); - for (IRGroup& ir_group : ir_group_list) { - std::vector node_list; - for (LayerCoord& coord : ir_group.get_coord_list()) { - IRNode& ir_node = layer_node_map[coord.get_layer_idx()][coord.get_x()][coord.get_y()]; - node_list.push_back(&ir_node); + std::vector> node_list_list; + std::vector& la_group_list = la_topo->get_la_group_list(); + for (LAGroup& la_group : la_group_list) { + std::vector node_list; + for (LayerCoord& coord : la_group.get_coord_list()) { + LANode& la_node = layer_node_map[coord.get_layer_idx()][coord.get_x()][coord.get_y()]; + node_list.push_back(&la_node); } node_list_list.push_back(node_list); } for (size_t i = 0; i < node_list_list.size(); i++) { if (i == 0) { - ir_model.get_start_node_list_list().push_back(node_list_list[i]); + la_model.get_start_node_list_list().push_back(node_list_list[i]); } else { - ir_model.get_end_node_list_list().push_back(node_list_list[i]); + la_model.get_end_node_list_list().push_back(node_list_list[i]); } } } - ir_model.get_path_node_list().clear(); - ir_model.get_single_topo_visited_node_list().clear(); - ir_model.get_routing_segment_list().clear(); + la_model.get_path_node_list().clear(); + la_model.get_single_topo_visited_node_list().clear(); + la_model.get_routing_segment_list().clear(); } -bool InitialRouter::isConnectedAllEnd(IRModel& ir_model) +bool LayerAssigner::isConnectedAllEnd(LAModel& la_model) { - return ir_model.get_end_node_list_list().empty(); + return la_model.get_end_node_list_list().empty(); } -void InitialRouter::routeSinglePath(IRModel& ir_model) +void LayerAssigner::routeSinglePath(LAModel& la_model) { - initPathHead(ir_model); - while (!searchEnded(ir_model)) { - expandSearching(ir_model); - resetPathHead(ir_model); + initPathHead(la_model); + while (!searchEnded(la_model)) { + expandSearching(la_model); + resetPathHead(la_model); } } -void InitialRouter::initPathHead(IRModel& ir_model) +void LayerAssigner::initPathHead(LAModel& la_model) { - std::vector>& start_node_list_list = ir_model.get_start_node_list_list(); - std::vector& path_node_list = ir_model.get_path_node_list(); + std::vector>& start_node_list_list = la_model.get_start_node_list_list(); + std::vector& path_node_list = la_model.get_path_node_list(); - for (std::vector& start_node_list : start_node_list_list) { - for (IRNode* start_node : start_node_list) { - start_node->set_estimated_cost(getEstimateCostToEnd(ir_model, start_node)); - pushToOpenList(ir_model, start_node); + for (std::vector& start_node_list : start_node_list_list) { + for (LANode* start_node : start_node_list) { + start_node->set_estimated_cost(getEstimateCostToEnd(la_model, start_node)); + pushToOpenList(la_model, start_node); } } - for (IRNode* path_node : path_node_list) { - path_node->set_estimated_cost(getEstimateCostToEnd(ir_model, path_node)); - pushToOpenList(ir_model, path_node); + for (LANode* path_node : path_node_list) { + path_node->set_estimated_cost(getEstimateCostToEnd(la_model, path_node)); + pushToOpenList(la_model, path_node); } - resetPathHead(ir_model); + resetPathHead(la_model); } -bool InitialRouter::searchEnded(IRModel& ir_model) +bool LayerAssigner::searchEnded(LAModel& la_model) { - std::vector>& end_node_list_list = ir_model.get_end_node_list_list(); - IRNode* path_head_node = ir_model.get_path_head_node(); + std::vector>& end_node_list_list = la_model.get_end_node_list_list(); + LANode* path_head_node = la_model.get_path_head_node(); if (path_head_node == nullptr) { - ir_model.set_end_node_list_idx(-1); + la_model.set_end_node_list_idx(-1); return true; } for (size_t i = 0; i < end_node_list_list.size(); i++) { - for (IRNode* end_node : end_node_list_list[i]) { + for (LANode* end_node : end_node_list_list[i]) { if (path_head_node == end_node) { - ir_model.set_end_node_list_idx(static_cast(i)); + la_model.set_end_node_list_idx(static_cast(i)); return true; } } @@ -513,54 +532,54 @@ bool InitialRouter::searchEnded(IRModel& ir_model) return false; } -void InitialRouter::expandSearching(IRModel& ir_model) +void LayerAssigner::expandSearching(LAModel& la_model) { - PriorityQueue, CmpIRNodeCost>& open_queue = ir_model.get_open_queue(); - IRNode* path_head_node = ir_model.get_path_head_node(); + PriorityQueue, CmpLANodeCost>& open_queue = la_model.get_open_queue(); + LANode* path_head_node = la_model.get_path_head_node(); for (auto& [orientation, neighbor_node] : path_head_node->get_neighbor_node_map()) { if (neighbor_node == nullptr) { continue; } - if (!RTUTIL.isInside(ir_model.get_curr_ir_topo()->get_bounding_box(), *neighbor_node)) { + if (!RTUTIL.isInside(la_model.get_curr_la_topo()->get_bounding_box(), *neighbor_node)) { continue; } if (neighbor_node->isClose()) { continue; } - double know_cost = getKnowCost(ir_model, path_head_node, neighbor_node); + double know_cost = getKnowCost(la_model, path_head_node, neighbor_node); if (neighbor_node->isOpen() && know_cost < neighbor_node->get_known_cost()) { neighbor_node->set_known_cost(know_cost); neighbor_node->set_parent_node(path_head_node); - // 对优先队列中的值修改了,需要重新建堆 - std::make_heap(open_queue.begin(), open_queue.end(), CmpIRNodeCost()); + // 对优先队列中的值修改了,需要重新建堆 + std::make_heap(open_queue.begin(), open_queue.end(), CmpLANodeCost()); } else if (neighbor_node->isNone()) { neighbor_node->set_known_cost(know_cost); neighbor_node->set_parent_node(path_head_node); - neighbor_node->set_estimated_cost(getEstimateCostToEnd(ir_model, neighbor_node)); - pushToOpenList(ir_model, neighbor_node); + neighbor_node->set_estimated_cost(getEstimateCostToEnd(la_model, neighbor_node)); + pushToOpenList(la_model, neighbor_node); } } } -void InitialRouter::resetPathHead(IRModel& ir_model) +void LayerAssigner::resetPathHead(LAModel& la_model) { - ir_model.set_path_head_node(popFromOpenList(ir_model)); + la_model.set_path_head_node(popFromOpenList(la_model)); } -void InitialRouter::updatePathResult(IRModel& ir_model) +void LayerAssigner::updatePathResult(LAModel& la_model) { - for (Segment& routing_segment : getRoutingSegmentListByNode(ir_model.get_path_head_node())) { - ir_model.get_routing_segment_list().push_back(routing_segment); + for (Segment& routing_segment : getRoutingSegmentListByNode(la_model.get_path_head_node())) { + la_model.get_routing_segment_list().push_back(routing_segment); } } -std::vector> InitialRouter::getRoutingSegmentListByNode(IRNode* node) +std::vector> LayerAssigner::getRoutingSegmentListByNode(LANode* node) { std::vector> routing_segment_list; - IRNode* curr_node = node; - IRNode* pre_node = curr_node->get_parent_node(); + LANode* curr_node = node; + LANode* pre_node = curr_node->get_parent_node(); if (pre_node == nullptr) { // 起点和终点重合 @@ -581,19 +600,19 @@ std::vector> InitialRouter::getRoutingSegmentListByNode(IRNo return routing_segment_list; } -void InitialRouter::resetStartAndEnd(IRModel& ir_model) +void LayerAssigner::resetStartAndEnd(LAModel& la_model) { - std::vector>& start_node_list_list = ir_model.get_start_node_list_list(); - std::vector>& end_node_list_list = ir_model.get_end_node_list_list(); - std::vector& path_node_list = ir_model.get_path_node_list(); - IRNode* path_head_node = ir_model.get_path_head_node(); - int32_t end_node_list_idx = ir_model.get_end_node_list_idx(); + std::vector>& start_node_list_list = la_model.get_start_node_list_list(); + std::vector>& end_node_list_list = la_model.get_end_node_list_list(); + std::vector& path_node_list = la_model.get_path_node_list(); + LANode* path_head_node = la_model.get_path_head_node(); + int32_t end_node_list_idx = la_model.get_end_node_list_idx(); - // 对于抵达的终点pin,只保留到达的node + // 对于抵达的终点pin,只保留到达的node end_node_list_list[end_node_list_idx].clear(); end_node_list_list[end_node_list_idx].push_back(path_head_node); - IRNode* path_node = path_head_node->get_parent_node(); + LANode* path_node = path_head_node->get_parent_node(); if (path_node == nullptr) { // 起点和终点重合 path_node = path_head_node; @@ -605,7 +624,7 @@ void InitialRouter::resetStartAndEnd(IRModel& ir_model) } } if (start_node_list_list.size() == 1) { - // 初始化时,要把start_node_list_list的pin只留一个ap点 + // 初始化时,要把start_node_list_list的pin只留一个ap点 // 后续只要将end_node_list_list的pin保留一个ap点 start_node_list_list.front().clear(); start_node_list_list.front().push_back(path_node); @@ -614,44 +633,44 @@ void InitialRouter::resetStartAndEnd(IRModel& ir_model) end_node_list_list.erase(end_node_list_list.begin() + end_node_list_idx); } -void InitialRouter::resetSinglePath(IRModel& ir_model) +void LayerAssigner::resetSinglePath(LAModel& la_model) { - PriorityQueue, CmpIRNodeCost> empty_queue; - ir_model.set_open_queue(empty_queue); + PriorityQueue, CmpLANodeCost> empty_queue; + la_model.set_open_queue(empty_queue); - std::vector& single_path_visited_node_list = ir_model.get_single_path_visited_node_list(); - for (IRNode* visited_node : single_path_visited_node_list) { - visited_node->set_state(IRNodeState::kNone); + std::vector& single_path_visited_node_list = la_model.get_single_path_visited_node_list(); + for (LANode* visited_node : single_path_visited_node_list) { + visited_node->set_state(LANodeState::kNone); visited_node->set_parent_node(nullptr); visited_node->set_known_cost(0); visited_node->set_estimated_cost(0); } single_path_visited_node_list.clear(); - ir_model.set_path_head_node(nullptr); - ir_model.set_end_node_list_idx(-1); + la_model.set_path_head_node(nullptr); + la_model.set_end_node_list_idx(-1); } -void InitialRouter::updateTaskResult(IRModel& ir_model) +void LayerAssigner::updateTaskResult(LAModel& la_model) { - ir_model.get_curr_ir_topo()->set_routing_segment_list(getRoutingSegmentList(ir_model)); + la_model.get_curr_la_topo()->set_routing_segment_list(getRoutingSegmentList(la_model)); } -std::vector> InitialRouter::getRoutingSegmentList(IRModel& ir_model) +std::vector> LayerAssigner::getRoutingSegmentList(LAModel& la_model) { - IRTopo* curr_ir_topo = ir_model.get_curr_ir_topo(); + LATopo* curr_la_topo = la_model.get_curr_la_topo(); std::vector candidate_root_coord_list; std::map, CmpLayerCoordByXASC> key_coord_pin_map; - std::vector& ir_group_list = curr_ir_topo->get_ir_group_list(); - for (size_t i = 0; i < ir_group_list.size(); i++) { - for (LayerCoord& coord : ir_group_list[i].get_coord_list()) { + std::vector& la_group_list = curr_la_topo->get_la_group_list(); + for (size_t i = 0; i < la_group_list.size(); i++) { + for (LayerCoord& coord : la_group_list[i].get_coord_list()) { candidate_root_coord_list.push_back(coord); key_coord_pin_map[coord].insert(static_cast(i)); } } MTree coord_tree - = RTUTIL.getTreeByFullFlow(candidate_root_coord_list, ir_model.get_routing_segment_list(), key_coord_pin_map); + = RTUTIL.getTreeByFullFlow(candidate_root_coord_list, la_model.get_routing_segment_list(), key_coord_pin_map); std::vector> routing_segment_list; for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { @@ -660,46 +679,46 @@ std::vector> InitialRouter::getRoutingSegmentList(IRModel& i return routing_segment_list; } -void InitialRouter::resetSingleTask(IRModel& ir_model) +void LayerAssigner::resetSingleTask(LAModel& la_model) { - ir_model.set_curr_ir_topo(nullptr); - ir_model.get_start_node_list_list().clear(); - ir_model.get_end_node_list_list().clear(); - ir_model.get_path_node_list().clear(); - ir_model.get_single_topo_visited_node_list().clear(); - ir_model.get_routing_segment_list().clear(); + la_model.set_curr_la_topo(nullptr); + la_model.get_start_node_list_list().clear(); + la_model.get_end_node_list_list().clear(); + la_model.get_path_node_list().clear(); + la_model.get_single_topo_visited_node_list().clear(); + la_model.get_routing_segment_list().clear(); } // manager open list -void InitialRouter::pushToOpenList(IRModel& ir_model, IRNode* curr_node) +void LayerAssigner::pushToOpenList(LAModel& la_model, LANode* curr_node) { - PriorityQueue, CmpIRNodeCost>& open_queue = ir_model.get_open_queue(); - std::vector& single_topo_visited_node_list = ir_model.get_single_topo_visited_node_list(); - std::vector& single_path_visited_node_list = ir_model.get_single_path_visited_node_list(); + PriorityQueue, CmpLANodeCost>& open_queue = la_model.get_open_queue(); + std::vector& single_topo_visited_node_list = la_model.get_single_topo_visited_node_list(); + std::vector& single_path_visited_node_list = la_model.get_single_path_visited_node_list(); open_queue.push(curr_node); - curr_node->set_state(IRNodeState::kOpen); + curr_node->set_state(LANodeState::kOpen); single_topo_visited_node_list.push_back(curr_node); single_path_visited_node_list.push_back(curr_node); } -IRNode* InitialRouter::popFromOpenList(IRModel& ir_model) +LANode* LayerAssigner::popFromOpenList(LAModel& la_model) { - PriorityQueue, CmpIRNodeCost>& open_queue = ir_model.get_open_queue(); + PriorityQueue, CmpLANodeCost>& open_queue = la_model.get_open_queue(); - IRNode* node = nullptr; + LANode* node = nullptr; if (!open_queue.empty()) { node = open_queue.top(); open_queue.pop(); - node->set_state(IRNodeState::kClose); + node->set_state(LANodeState::kClose); } return node; } // calculate known cost -double InitialRouter::getKnowCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getKnowCost(LAModel& la_model, LANode* start_node, LANode* end_node) { bool exist_neighbor = false; for (auto& [orientation, neighbor_ptr] : start_node->get_neighbor_node_map()) { @@ -714,26 +733,26 @@ double InitialRouter::getKnowCost(IRModel& ir_model, IRNode* start_node, IRNode* double cost = 0; cost += start_node->get_known_cost(); - cost += getNodeCost(ir_model, start_node, RTUTIL.getOrientation(*start_node, *end_node)); - cost += getNodeCost(ir_model, end_node, RTUTIL.getOrientation(*end_node, *start_node)); - cost += getKnowWireCost(ir_model, start_node, end_node); - cost += getKnowViaCost(ir_model, start_node, end_node); + cost += getNodeCost(la_model, start_node, RTUTIL.getOrientation(*start_node, *end_node)); + cost += getNodeCost(la_model, end_node, RTUTIL.getOrientation(*end_node, *start_node)); + cost += getKnowWireCost(la_model, start_node, end_node); + cost += getKnowViaCost(la_model, start_node, end_node); return cost; } -double InitialRouter::getNodeCost(IRModel& ir_model, IRNode* curr_node, Orientation orientation) +double LayerAssigner::getNodeCost(LAModel& la_model, LANode* curr_node, Orientation orientation) { - double congestion_unit = ir_model.get_ir_parameter().get_congestion_unit(); + double congestion_unit = la_model.get_la_parameter().get_congestion_unit(); double node_cost = 0; node_cost += curr_node->getCongestionCost(orientation) * congestion_unit; return node_cost; } -double InitialRouter::getKnowWireCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getKnowWireCost(LAModel& la_model, LANode* start_node, LANode* end_node) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - double prefer_wire_unit = ir_model.get_ir_parameter().get_prefer_wire_unit(); + double prefer_wire_unit = la_model.get_la_parameter().get_prefer_wire_unit(); double wire_cost = 0; if (start_node->get_layer_idx() == end_node->get_layer_idx()) { @@ -747,42 +766,42 @@ double InitialRouter::getKnowWireCost(IRModel& ir_model, IRNode* start_node, IRN return wire_cost; } -double InitialRouter::getKnowViaCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getKnowViaCost(LAModel& la_model, LANode* start_node, LANode* end_node) { - double via_unit = ir_model.get_ir_parameter().get_via_unit(); + double via_unit = la_model.get_la_parameter().get_via_unit(); double via_cost = (via_unit * std::abs(start_node->get_layer_idx() - end_node->get_layer_idx())); return via_cost; } // calculate estimate cost -double InitialRouter::getEstimateCostToEnd(IRModel& ir_model, IRNode* curr_node) +double LayerAssigner::getEstimateCostToEnd(LAModel& la_model, LANode* curr_node) { - std::vector>& end_node_list_list = ir_model.get_end_node_list_list(); + std::vector>& end_node_list_list = la_model.get_end_node_list_list(); double estimate_cost = DBL_MAX; - for (std::vector& end_node_list : end_node_list_list) { - for (IRNode* end_node : end_node_list) { + for (std::vector& end_node_list : end_node_list_list) { + for (LANode* end_node : end_node_list) { if (end_node->isClose()) { continue; } - estimate_cost = std::min(estimate_cost, getEstimateCost(ir_model, curr_node, end_node)); + estimate_cost = std::min(estimate_cost, getEstimateCost(la_model, curr_node, end_node)); } } return estimate_cost; } -double InitialRouter::getEstimateCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getEstimateCost(LAModel& la_model, LANode* start_node, LANode* end_node) { double estimate_cost = 0; - estimate_cost += getEstimateWireCost(ir_model, start_node, end_node); - estimate_cost += getEstimateViaCost(ir_model, start_node, end_node); + estimate_cost += getEstimateWireCost(la_model, start_node, end_node); + estimate_cost += getEstimateViaCost(la_model, start_node, end_node); return estimate_cost; } -double InitialRouter::getEstimateWireCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getEstimateWireCost(LAModel& la_model, LANode* start_node, LANode* end_node) { - double prefer_wire_unit = ir_model.get_ir_parameter().get_prefer_wire_unit(); + double prefer_wire_unit = la_model.get_la_parameter().get_prefer_wire_unit(); double wire_cost = 0; wire_cost += RTUTIL.getManhattanDistance(start_node->get_planar_coord(), end_node->get_planar_coord()); @@ -790,31 +809,31 @@ double InitialRouter::getEstimateWireCost(IRModel& ir_model, IRNode* start_node, return wire_cost; } -double InitialRouter::getEstimateViaCost(IRModel& ir_model, IRNode* start_node, IRNode* end_node) +double LayerAssigner::getEstimateViaCost(LAModel& la_model, LANode* start_node, LANode* end_node) { - double via_unit = ir_model.get_ir_parameter().get_via_unit(); + double via_unit = la_model.get_la_parameter().get_via_unit(); double via_cost = (via_unit * std::abs(start_node->get_layer_idx() - end_node->get_layer_idx())); return via_cost; } -MTree InitialRouter::getCoordTree(IRNet* ir_net, std::vector>& routing_segment_list) +MTree LayerAssigner::getCoordTree(LANet* la_net, std::vector>& routing_segment_list) { std::vector candidate_root_coord_list; std::map, CmpLayerCoordByXASC> key_coord_pin_map; - std::vector& ir_pin_list = ir_net->get_ir_pin_list(); - for (size_t i = 0; i < ir_pin_list.size(); i++) { - LayerCoord coord = ir_pin_list[i].get_access_point().getGridLayerCoord(); + std::vector& la_pin_list = la_net->get_la_pin_list(); + for (size_t i = 0; i < la_pin_list.size(); i++) { + LayerCoord coord = la_pin_list[i].get_access_point().getGridLayerCoord(); candidate_root_coord_list.push_back(coord); key_coord_pin_map[coord].insert(static_cast(i)); } return RTUTIL.getTreeByFullFlow(candidate_root_coord_list, routing_segment_list, key_coord_pin_map); } -void InitialRouter::updateDemand(IRModel& ir_model, IRNet* ir_net, MTree& coord_tree) +void LayerAssigner::updateDemand(LAModel& la_model, LANet* la_net, MTree& coord_tree) { std::set key_coord_set; - for (IRPin& ir_pin : ir_net->get_ir_pin_list()) { - key_coord_set.insert(ir_pin.get_access_point().getGridLayerCoord()); + for (LAPin& la_pin : la_net->get_la_pin_list()) { + key_coord_set.insert(la_pin.get_access_point().getGridLayerCoord()); } std::vector> routing_segment_list; for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { @@ -855,24 +874,24 @@ void InitialRouter::updateDemand(IRModel& ir_model, IRNet* ir_net, MTree>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); for (auto& [usage_coord, orientation_list] : usage_map) { - IRNode& ir_node = layer_node_map[usage_coord.get_layer_idx()][usage_coord.get_x()][usage_coord.get_y()]; - ir_node.updateDemand(orientation_list, ChangeType::kAdd); + LANode& la_node = layer_node_map[usage_coord.get_layer_idx()][usage_coord.get_x()][usage_coord.get_y()]; + la_node.updateDemand(orientation_list, ChangeType::kAdd); } } -void InitialRouter::uploadNetResult(IRNet* ir_net, MTree& coord_tree) +void LayerAssigner::uploadNetResult(LANet* la_net, MTree& coord_tree) { for (Segment*>& coord_segment : RTUTIL.getSegListByTree(coord_tree)) { Segment* segment = new Segment(coord_segment.get_first()->value(), coord_segment.get_second()->value()); - RTDM.updateGlobalNetResultToGCellMap(ChangeType::kAdd, ir_net->get_net_idx(), segment); + RTDM.updateGlobalNetResultToGCellMap(ChangeType::kAdd, la_net->get_net_idx(), segment); } } #if 1 // exhibit -void InitialRouter::updateSummary(IRModel& ir_model) +void LayerAssigner::updateSummary(LAModel& la_model) { int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); @@ -881,20 +900,22 @@ void InitialRouter::updateSummary(IRModel& ir_model) std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); std::vector>& layer_via_master_list = RTDM.getDatabase().get_layer_via_master_list(); + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - std::map& routing_demand_map = RTDM.getSummary().ir_summary.routing_demand_map; - int32_t& total_demand = RTDM.getSummary().ir_summary.total_demand; - std::map& routing_overflow_map = RTDM.getSummary().ir_summary.routing_overflow_map; - int32_t& total_overflow = RTDM.getSummary().ir_summary.total_overflow; - std::map& routing_wire_length_map = RTDM.getSummary().ir_summary.routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().ir_summary.total_wire_length; - std::map& cut_via_num_map = RTDM.getSummary().ir_summary.cut_via_num_map; - int32_t& total_via_num = RTDM.getSummary().ir_summary.total_via_num; - std::map>& clock_timing = RTDM.getSummary().ir_summary.clock_timing; - std::map& power_map = RTDM.getSummary().ir_summary.power_map; - std::vector>& layer_node_map = ir_model.get_layer_node_map(); - std::vector& ir_net_list = ir_model.get_ir_net_list(); + std::map& routing_demand_map = summary.la_summary.routing_demand_map; + int32_t& total_demand = summary.la_summary.total_demand; + std::map& routing_overflow_map = summary.la_summary.routing_overflow_map; + int32_t& total_overflow = summary.la_summary.total_overflow; + std::map& routing_wire_length_map = summary.la_summary.routing_wire_length_map; + double& total_wire_length = summary.la_summary.total_wire_length; + std::map& cut_via_num_map = summary.la_summary.cut_via_num_map; + int32_t& total_via_num = summary.la_summary.total_via_num; + std::map>& clock_timing = summary.la_summary.clock_timing; + std::map& power_map = summary.la_summary.power_map; + + std::vector>& layer_node_map = la_model.get_layer_node_map(); + std::vector& la_net_list = la_model.get_la_net_list(); for (RoutingLayer& routing_layer : routing_layer_list) { routing_demand_map[routing_layer.get_layer_idx()] = 0; @@ -910,11 +931,11 @@ void InitialRouter::updateSummary(IRModel& ir_model) total_via_num = 0; for (int32_t layer_idx = 0; layer_idx < static_cast(layer_node_map.size()); layer_idx++) { - GridMap& ir_node_map = layer_node_map[layer_idx]; - for (int32_t x = 0; x < ir_node_map.get_x_size(); x++) { - for (int32_t y = 0; y < ir_node_map.get_y_size(); y++) { - std::map& orient_supply_map = ir_node_map[x][y].get_orient_supply_map(); - std::map& orient_demand_map = ir_node_map[x][y].get_orient_demand_map(); + GridMap& la_node_map = layer_node_map[layer_idx]; + for (int32_t x = 0; x < la_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < la_node_map.get_y_size(); y++) { + std::map& orient_supply_map = la_node_map[x][y].get_orient_supply_map(); + std::map& orient_demand_map = la_node_map[x][y].get_orient_demand_map(); int32_t node_demand = 0; int32_t node_overflow = 0; if (routing_layer_list[layer_idx].isPreferH()) { @@ -957,13 +978,13 @@ void InitialRouter::updateSummary(IRModel& ir_model) } if (enable_timing) { std::vector>> real_pin_coord_map_list; - real_pin_coord_map_list.resize(ir_net_list.size()); + real_pin_coord_map_list.resize(la_net_list.size()); std::vector>> routing_segment_list_list; - routing_segment_list_list.resize(ir_net_list.size()); - for (IRNet& ir_net : ir_net_list) { - for (IRPin& ir_pin : ir_net.get_ir_pin_list()) { - LayerCoord layer_coord = ir_pin.get_access_point().getGridLayerCoord(); - real_pin_coord_map_list[ir_net.get_net_idx()][ir_pin.get_pin_name()].emplace_back( + routing_segment_list_list.resize(la_net_list.size()); + for (LANet& la_net : la_net_list) { + for (LAPin& la_pin : la_net.get_la_pin_list()) { + LayerCoord layer_coord = la_pin.get_access_point().getGridLayerCoord(); + real_pin_coord_map_list[la_net.get_net_idx()][la_pin.get_pin_name()].emplace_back( RTUTIL.getRealRectByGCell(layer_coord, gcell_axis).getMidPoint(), layer_coord.get_layer_idx()); } } @@ -983,21 +1004,23 @@ void InitialRouter::updateSummary(IRModel& ir_model) } } -void InitialRouter::printSummary(IRModel& ir_model) +void LayerAssigner::printSummary(LAModel& la_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - std::map& routing_demand_map = RTDM.getSummary().ir_summary.routing_demand_map; - int32_t& total_demand = RTDM.getSummary().ir_summary.total_demand; - std::map& routing_overflow_map = RTDM.getSummary().ir_summary.routing_overflow_map; - int32_t& total_overflow = RTDM.getSummary().ir_summary.total_overflow; - std::map& routing_wire_length_map = RTDM.getSummary().ir_summary.routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().ir_summary.total_wire_length; - std::map& cut_via_num_map = RTDM.getSummary().ir_summary.cut_via_num_map; - int32_t& total_via_num = RTDM.getSummary().ir_summary.total_via_num; - std::map>& clock_timing = RTDM.getSummary().ir_summary.clock_timing; - std::map& power_map = RTDM.getSummary().ir_summary.power_map; + + std::map& routing_demand_map = summary.la_summary.routing_demand_map; + int32_t& total_demand = summary.la_summary.total_demand; + std::map& routing_overflow_map = summary.la_summary.routing_overflow_map; + int32_t& total_overflow = summary.la_summary.total_overflow; + std::map& routing_wire_length_map = summary.la_summary.routing_wire_length_map; + double& total_wire_length = summary.la_summary.total_wire_length; + std::map& cut_via_num_map = summary.la_summary.cut_via_num_map; + int32_t& total_via_num = summary.la_summary.total_via_num; + std::map>& clock_timing = summary.la_summary.clock_timing; + std::map& power_map = summary.la_summary.power_map; fort::char_table routing_demand_map_table; { @@ -1046,43 +1069,39 @@ void InitialRouter::printSummary(IRModel& ir_model) } cut_via_num_map_table << fort::header << "Total" << total_via_num << RTUTIL.getPercentage(total_via_num, total_via_num) << fort::endr; } - fort::char_table timing_and_power_table; + fort::char_table timing_table; + fort::char_table power_table; if (enable_timing) { - timing_and_power_table << fort::header << "Clock" - << "TNS" - << "WNS" - << "Freq(MHz)" << fort::endr; + timing_table << fort::header << "clock_name" + << "tns" + << "wns" + << "freq" << fort::endr; for (auto& [clock_name, timing_map] : clock_timing) { - timing_and_power_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; + timing_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; } + power_table << fort::header << "power_type" << "power_value" << fort::endr; for (auto& [type, power] : power_map) { - timing_and_power_table << fort::header << "type" << type << fort::endr; - timing_and_power_table << fort::header << "power" << power << fort::endr; + power_table << type << power << fort::endr; } } - std::vector table_list; - table_list.push_back(routing_demand_map_table); - table_list.push_back(routing_overflow_map_table); - table_list.push_back(routing_wire_length_map_table); - table_list.push_back(cut_via_num_map_table); - table_list.push_back(timing_and_power_table); - RTUTIL.printTableList(table_list); + RTUTIL.printTableList({routing_demand_map_table, routing_overflow_map_table, routing_wire_length_map_table, cut_via_num_map_table}); + RTUTIL.printTableList({timing_table, power_table}); } -void InitialRouter::outputGuide(IRModel& ir_model) +void LayerAssigner::outputGuide(LAModel& la_model) { int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); Die& die = RTDM.getDatabase().get_die(); std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::string& ir_temp_directory_path = RTDM.getConfig().ir_temp_directory_path; + std::string& la_temp_directory_path = RTDM.getConfig().la_temp_directory_path; int32_t output_inter_result = RTDM.getConfig().output_inter_result; if (!output_inter_result) { return; } - std::vector& ir_net_list = ir_model.get_ir_net_list(); + std::vector& la_net_list = la_model.get_la_net_list(); - std::ofstream* guide_file_stream = RTUTIL.getOutputFileStream(ir_temp_directory_path + "route.guide"); + std::ofstream* guide_file_stream = RTUTIL.getOutputFileStream(la_temp_directory_path + "route.guide"); if (guide_file_stream == nullptr) { return; } @@ -1092,24 +1111,24 @@ void InitialRouter::outputGuide(IRModel& ir_model) RTUTIL.pushStream(guide_file_stream, "via grid_x grid_y real_x real_y layer1 layer2\n"); for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { - IRNet& ir_net = ir_net_list[net_idx]; - RTUTIL.pushStream(guide_file_stream, "guide ", ir_net.get_origin_net()->get_net_name(), "\n"); + LANet& la_net = la_net_list[net_idx]; + RTUTIL.pushStream(guide_file_stream, "guide ", la_net.get_origin_net()->get_net_name(), "\n"); - for (IRPin& ir_pin : ir_net.get_ir_pin_list()) { - AccessPoint& access_point = ir_pin.get_access_point(); + for (LAPin& la_pin : la_net.get_la_pin_list()) { + AccessPoint& access_point = la_pin.get_access_point(); double grid_x = access_point.get_grid_x(); double grid_y = access_point.get_grid_y(); double real_x = access_point.get_real_x() / 1.0 / micron_dbu; double real_y = access_point.get_real_y() / 1.0 / micron_dbu; std::string layer = routing_layer_list[access_point.get_layer_idx()].get_layer_name(); std::string connnect; - if (ir_pin.get_is_driven()) { + if (la_pin.get_is_driven()) { connnect = "driven"; } else { connnect = "load"; } RTUTIL.pushStream(guide_file_stream, "pin ", grid_x, " ", grid_y, " ", real_x, " ", real_y, " ", layer, " ", connnect, " ", - ir_pin.get_pin_name(), "\n"); + la_pin.get_pin_name(), "\n"); } for (Segment* segment : segment_set) { LayerCoord first_layer_coord = segment->get_first(); @@ -1145,23 +1164,23 @@ void InitialRouter::outputGuide(IRModel& ir_model) RTUTIL.closeFileStream(guide_file_stream); } -void InitialRouter::outputDemandCSV(IRModel& ir_model) +void LayerAssigner::outputDemandCSV(LAModel& la_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::string& ir_temp_directory_path = RTDM.getConfig().ir_temp_directory_path; + std::string& la_temp_directory_path = RTDM.getConfig().la_temp_directory_path; int32_t output_inter_result = RTDM.getConfig().output_inter_result; if (!output_inter_result) { return; } - std::vector>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); for (RoutingLayer& routing_layer : routing_layer_list) { std::ofstream* demand_csv_file - = RTUTIL.getOutputFileStream(RTUTIL.getString(ir_temp_directory_path, "demand_map_", routing_layer.get_layer_name(), ".csv")); + = RTUTIL.getOutputFileStream(RTUTIL.getString(la_temp_directory_path, "demand_map_", routing_layer.get_layer_name(), ".csv")); - GridMap& ir_node_map = layer_node_map[routing_layer.get_layer_idx()]; - for (int32_t y = ir_node_map.get_y_size() - 1; y >= 0; y--) { - for (int32_t x = 0; x < ir_node_map.get_x_size(); x++) { - std::map& orient_demand_map = ir_node_map[x][y].get_orient_demand_map(); + GridMap& la_node_map = layer_node_map[routing_layer.get_layer_idx()]; + for (int32_t y = la_node_map.get_y_size() - 1; y >= 0; y--) { + for (int32_t x = 0; x < la_node_map.get_x_size(); x++) { + std::map& orient_demand_map = la_node_map[x][y].get_orient_demand_map(); int32_t total_demand = 0; if (routing_layer.isPreferH()) { total_demand = (orient_demand_map[Orientation::kEast] + orient_demand_map[Orientation::kWest]); @@ -1176,24 +1195,24 @@ void InitialRouter::outputDemandCSV(IRModel& ir_model) } } -void InitialRouter::outputOverflowCSV(IRModel& ir_model) +void LayerAssigner::outputOverflowCSV(LAModel& la_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::string& ir_temp_directory_path = RTDM.getConfig().ir_temp_directory_path; + std::string& la_temp_directory_path = RTDM.getConfig().la_temp_directory_path; int32_t output_inter_result = RTDM.getConfig().output_inter_result; if (!output_inter_result) { return; } - std::vector>& layer_node_map = ir_model.get_layer_node_map(); + std::vector>& layer_node_map = la_model.get_layer_node_map(); for (RoutingLayer& routing_layer : routing_layer_list) { std::ofstream* overflow_csv_file - = RTUTIL.getOutputFileStream(RTUTIL.getString(ir_temp_directory_path, "overflow_map_", routing_layer.get_layer_name(), ".csv")); + = RTUTIL.getOutputFileStream(RTUTIL.getString(la_temp_directory_path, "overflow_map_", routing_layer.get_layer_name(), ".csv")); - GridMap& ir_node_map = layer_node_map[routing_layer.get_layer_idx()]; - for (int32_t y = ir_node_map.get_y_size() - 1; y >= 0; y--) { - for (int32_t x = 0; x < ir_node_map.get_x_size(); x++) { - std::map& orient_supply_map = ir_node_map[x][y].get_orient_supply_map(); - std::map& orient_demand_map = ir_node_map[x][y].get_orient_demand_map(); + GridMap& la_node_map = layer_node_map[routing_layer.get_layer_idx()]; + for (int32_t y = la_node_map.get_y_size() - 1; y >= 0; y--) { + for (int32_t x = 0; x < la_node_map.get_x_size(); x++) { + std::map& orient_supply_map = la_node_map[x][y].get_orient_supply_map(); + std::map& orient_demand_map = la_node_map[x][y].get_orient_demand_map(); int32_t total_overflow = 0; if (routing_layer.isPreferH()) { total_overflow = std::max(0, orient_demand_map[Orientation::kEast] - orient_supply_map[Orientation::kEast]) @@ -1214,22 +1233,22 @@ void InitialRouter::outputOverflowCSV(IRModel& ir_model) #if 1 // debug -void InitialRouter::debugCheckIRModel(IRModel& ir_model) +void LayerAssigner::debugCheckLAModel(LAModel& la_model) { - std::vector>& layer_node_map = ir_model.get_layer_node_map(); - for (GridMap& ir_node_map : layer_node_map) { - for (int32_t x = 0; x < ir_node_map.get_x_size(); x++) { - for (int32_t y = 0; y < ir_node_map.get_y_size(); y++) { - IRNode& ir_node = ir_node_map[x][y]; - for (auto& [orient, neighbor] : ir_node.get_neighbor_node_map()) { + std::vector>& layer_node_map = la_model.get_layer_node_map(); + for (GridMap& la_node_map : layer_node_map) { + for (int32_t x = 0; x < la_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < la_node_map.get_y_size(); y++) { + LANode& la_node = la_node_map[x][y]; + for (auto& [orient, neighbor] : la_node.get_neighbor_node_map()) { Orientation opposite_orient = RTUTIL.getOppositeOrientation(orient); if (!RTUTIL.exist(neighbor->get_neighbor_node_map(), opposite_orient)) { - RTLOG.error(Loc::current(), "The ir_node neighbor is not bidirectional!"); + RTLOG.error(Loc::current(), "The la_node neighbor is not bidirectional!"); } - if (neighbor->get_neighbor_node_map()[opposite_orient] != &ir_node) { - RTLOG.error(Loc::current(), "The ir_node neighbor is not bidirectional!"); + if (neighbor->get_neighbor_node_map()[opposite_orient] != &la_node) { + RTLOG.error(Loc::current(), "The la_node neighbor is not bidirectional!"); } - if (RTUTIL.getOrientation(LayerCoord(ir_node), LayerCoord(*neighbor)) == orient) { + if (RTUTIL.getOrientation(LayerCoord(la_node), LayerCoord(*neighbor)) == orient) { continue; } RTLOG.error(Loc::current(), "The neighbor orient is different with real region!"); diff --git a/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp new file mode 100644 index 000000000..afd74db87 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp @@ -0,0 +1,105 @@ +// *************************************************************************************** +// 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 "ChangeType.hpp" +#include "Config.hpp" +#include "DataManager.hpp" +#include "Database.hpp" +#include "LAModel.hpp" +#include "RTHeader.hpp" + +namespace irt { + +#define RTLA (irt::LayerAssigner::getInst()) + +class LayerAssigner +{ + public: + static void initInst(); + static LayerAssigner& getInst(); + static void destroyInst(); + // function + void route(); + + private: + // self + static LayerAssigner* _la_instance; + + LayerAssigner() = default; + LayerAssigner(const LayerAssigner& other) = delete; + LayerAssigner(LayerAssigner&& other) = delete; + ~LayerAssigner() = default; + LayerAssigner& operator=(const LayerAssigner& other) = delete; + LayerAssigner& operator=(LayerAssigner&& other) = delete; + // function + LAModel initLAModel(); + std::vector convertToLANetList(std::vector& net_list); + LANet convertToLANet(Net& net); + void initLATaskList(LAModel& la_model); + void setLAParameter(LAModel& la_model); + void buildLayerNodeMap(LAModel& la_model); + void buildLANodeNeighbor(LAModel& la_model); + void buildOrientSupply(LAModel& la_model); + void buildTopoTree(LAModel& la_model); + void routeLAModel(LAModel& la_model); + void routeLANet(LAModel& la_model, LANet* la_net); + void makeLATopoList(LAModel& la_model, LANet* la_net, std::vector& la_topo_list, + std::vector>& routing_segment_list); + void routeLATopo(LAModel& la_model, LATopo* la_topo); + void initSingleTask(LAModel& la_model, LATopo* la_topo); + bool isConnectedAllEnd(LAModel& la_model); + void routeSinglePath(LAModel& la_model); + void initPathHead(LAModel& la_model); + bool searchEnded(LAModel& la_model); + void expandSearching(LAModel& la_model); + void resetPathHead(LAModel& la_model); + void updatePathResult(LAModel& la_model); + std::vector> getRoutingSegmentListByNode(LANode* node); + void resetStartAndEnd(LAModel& la_model); + void resetSinglePath(LAModel& la_model); + void updateTaskResult(LAModel& la_model); + std::vector> getRoutingSegmentList(LAModel& la_model); + void resetSingleTask(LAModel& la_model); + void pushToOpenList(LAModel& la_model, LANode* curr_node); + LANode* popFromOpenList(LAModel& la_model); + double getKnowCost(LAModel& la_model, LANode* start_node, LANode* end_node); + double getNodeCost(LAModel& la_model, LANode* curr_node, Orientation orientation); + double getKnowWireCost(LAModel& la_model, LANode* start_node, LANode* end_node); + double getKnowViaCost(LAModel& la_model, LANode* start_node, LANode* end_node); + double getEstimateCostToEnd(LAModel& la_model, LANode* curr_node); + double getEstimateCost(LAModel& la_model, LANode* start_node, LANode* end_node); + double getEstimateWireCost(LAModel& la_model, LANode* start_node, LANode* end_node); + double getEstimateViaCost(LAModel& la_model, LANode* start_node, LANode* end_node); + MTree getCoordTree(LANet* la_net, std::vector>& routing_segment_list); + void updateDemand(LAModel& la_model, LANet* la_net, MTree& coord_tree); + void uploadNetResult(LANet* la_net, MTree& coord_tree); + +#if 1 // exhibit + void updateSummary(LAModel& la_model); + void printSummary(LAModel& la_model); + void outputGuide(LAModel& la_model); + void outputDemandCSV(LAModel& la_model); + void outputOverflowCSV(LAModel& la_model); +#endif + +#if 1 // debug + void debugCheckLAModel(LAModel& la_model); +#endif +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/framwork.txt b/src/operation/iRT/source/module/layer_assigner/framwork.txt new file mode 100644 index 000000000..8c485ae9f --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/framwork.txt @@ -0,0 +1,10 @@ +initLAModel:初始化la_net_list +setLAParameter:设置布线参数 +initLATaskList:构建task,有序 +buildLayerNodeMap:初始化graph +buildLANodeNeighbor:构建graph的邻居 +buildOrientSupply:从supply_analyzer获取supply的access +buildTopoTree:从顶层拿取topo树 +routeLAModel: + routeLANet:一个接一个的la_net进行布线 +updateLAModel:将结果更新到顶层 \ No newline at end of file diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAGroup.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAGroup.hpp new file mode 100644 index 000000000..099e3c944 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAGroup.hpp @@ -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. +// *************************************************************************************** +#pragma once + +#include "LayerCoord.hpp" + +namespace irt { + +class LAGroup +{ + public: + LAGroup() = default; + ~LAGroup() = default; + // getter + std::vector& get_coord_list() { return _coord_list; } + // setter + void set_coord_list(const std::vector& coord_list) { _coord_list = coord_list; } + // function + + private: + std::vector _coord_list; +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAModel.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAModel.hpp new file mode 100644 index 000000000..ccd7d6bf8 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAModel.hpp @@ -0,0 +1,101 @@ +// *************************************************************************************** +// 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 "LANet.hpp" +#include "LANode.hpp" +#include "LAParameter.hpp" +#include "LATopo.hpp" +#include "PriorityQueue.hpp" + +namespace irt { + +class LAModel +{ + public: + LAModel() = default; + ~LAModel() = default; + // getter + std::vector& get_la_net_list() { return _la_net_list; } + LAParameter& get_la_parameter() { return _la_parameter; } + std::vector& get_la_task_list() { return _la_task_list; } + std::vector>& get_layer_node_map() { return _layer_node_map; } + // setter + void set_la_net_list(const std::vector& la_net_list) { _la_net_list = la_net_list; } + void set_la_parameter(const LAParameter& la_parameter) { _la_parameter = la_parameter; } + void set_la_task_list(const std::vector& la_task_list) { _la_task_list = la_task_list; } + void set_layer_node_map(const std::vector>& layer_node_map) { _layer_node_map = layer_node_map; } + // function +#if 1 // astar + // single topo + LATopo* get_curr_la_topo() { return _curr_la_topo; } + std::vector>& get_start_node_list_list() { return _start_node_list_list; } + std::vector>& get_end_node_list_list() { return _end_node_list_list; } + std::vector& get_path_node_list() { return _path_node_list; } + std::vector& get_single_topo_visited_node_list() { return _single_topo_visited_node_list; } + std::vector>& get_routing_segment_list() { return _routing_segment_list; } + void set_curr_la_topo(LATopo* curr_la_topo) { _curr_la_topo = curr_la_topo; } + void set_start_node_list_list(const std::vector>& start_node_list_list) + { + _start_node_list_list = start_node_list_list; + } + void set_end_node_list_list(const std::vector>& end_node_list_list) { _end_node_list_list = end_node_list_list; } + void set_path_node_list(const std::vector& path_node_list) { _path_node_list = path_node_list; } + void set_single_topo_visited_node_list(const std::vector& single_topo_visited_node_list) + { + _single_topo_visited_node_list = single_topo_visited_node_list; + } + void set_routing_segment_list(const std::vector>& routing_segment_list) + { + _routing_segment_list = routing_segment_list; + } + // single path + PriorityQueue, CmpLANodeCost>& get_open_queue() { return _open_queue; } + std::vector& get_single_path_visited_node_list() { return _single_path_visited_node_list; } + LANode* get_path_head_node() { return _path_head_node; } + int32_t get_end_node_list_idx() const { return _end_node_list_idx; } + void set_open_queue(const PriorityQueue, CmpLANodeCost>& open_queue) { _open_queue = open_queue; } + void set_single_path_visited_node_list(const std::vector& single_path_visited_node_list) + { + _single_path_visited_node_list = single_path_visited_node_list; + } + void set_path_head_node(LANode* path_head_node) { _path_head_node = path_head_node; } + void set_end_node_list_idx(const int32_t end_node_list_idx) { _end_node_list_idx = end_node_list_idx; } +#endif + + private: + std::vector _la_net_list; + LAParameter _la_parameter; + std::vector _la_task_list; + std::vector> _layer_node_map; +#if 1 // astar + // single topo + LATopo* _curr_la_topo = nullptr; + std::vector> _start_node_list_list; + std::vector> _end_node_list_list; + std::vector _path_node_list; + std::vector _single_topo_visited_node_list; + std::vector> _routing_segment_list; + // single path + PriorityQueue, CmpLANodeCost> _open_queue; + std::vector _single_path_visited_node_list; + LANode* _path_head_node = nullptr; + int32_t _end_node_list_idx = -1; +#endif +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANet.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANet.hpp new file mode 100644 index 000000000..6a5cabc35 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANet.hpp @@ -0,0 +1,126 @@ +// *************************************************************************************** +// 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 "LAPin.hpp" +#include "Net.hpp" + +namespace irt { + +class LANet +{ + public: + LANet() = default; + ~LANet() = default; + // getter + Net* get_origin_net() { return _origin_net; } + int32_t get_net_idx() const { return _net_idx; } + ConnectType& get_connect_type() { return _connect_type; } + std::vector& get_la_pin_list() { return _la_pin_list; } + BoundingBox& get_bounding_box() { return _bounding_box; } + MTree& get_topo_tree() { return _topo_tree; } + // const getter + const ConnectType& get_connect_type() const { return _connect_type; } + const std::vector& get_la_pin_list() const { return _la_pin_list; } + const BoundingBox& get_bounding_box() const { return _bounding_box; } + // setter + void set_origin_net(Net* origin_net) { _origin_net = origin_net; } + void set_net_idx(const int32_t net_idx) { _net_idx = net_idx; } + void set_connect_type(const ConnectType& connect_type) { _connect_type = connect_type; } + void set_la_pin_list(const std::vector& la_pin_list) { _la_pin_list = la_pin_list; } + void set_bounding_box(const BoundingBox& bounding_box) { _bounding_box = bounding_box; } + void set_topo_tree(const MTree& topo_tree) { _topo_tree = topo_tree; } + // function + + private: + Net* _origin_net = nullptr; + int32_t _net_idx = -1; + ConnectType _connect_type = ConnectType::kNone; + std::vector _la_pin_list; + BoundingBox _bounding_box; + MTree _topo_tree; +}; + +struct CmpLANet +{ + bool operator()(const LANet* a, const LANet* b) const + { + SortStatus sort_status = SortStatus::kEqual; + // 时钟线网优先 + if (sort_status == SortStatus::kEqual) { + ConnectType a_connect_type = a->get_connect_type(); + ConnectType b_connect_type = b->get_connect_type(); + if (a_connect_type == ConnectType::kClock && b_connect_type != ConnectType::kClock) { + sort_status = SortStatus::kTrue; + } else if (a_connect_type != ConnectType::kClock && b_connect_type == ConnectType::kClock) { + sort_status = SortStatus::kFalse; + } else { + sort_status = SortStatus::kEqual; + } + } + // BoundingBox 大小升序 + if (sort_status == SortStatus::kEqual) { + double a_total_size = a->get_bounding_box().getTotalSize(); + double b_total_size = b->get_bounding_box().getTotalSize(); + if (a_total_size < b_total_size) { + sort_status = SortStatus::kTrue; + } else if (a_total_size == b_total_size) { + sort_status = SortStatus::kEqual; + } else { + sort_status = SortStatus::kFalse; + } + } + // 长宽比 降序 + if (sort_status == SortStatus::kEqual) { + double a_length_width_ratio = a->get_bounding_box().getXSize() / 1.0 / a->get_bounding_box().getYSize(); + if (a_length_width_ratio < 1) { + a_length_width_ratio = 1 / a_length_width_ratio; + } + double b_length_width_ratio = b->get_bounding_box().getXSize() / 1.0 / b->get_bounding_box().getYSize(); + if (b_length_width_ratio < 1) { + b_length_width_ratio = 1 / b_length_width_ratio; + } + if (a_length_width_ratio > b_length_width_ratio) { + sort_status = SortStatus::kTrue; + } else if (a_length_width_ratio == b_length_width_ratio) { + sort_status = SortStatus::kEqual; + } else { + sort_status = SortStatus::kFalse; + } + } + // PinNum 降序 + if (sort_status == SortStatus::kEqual) { + int32_t a_pin_num = static_cast(a->get_la_pin_list().size()); + int32_t b_pin_num = static_cast(b->get_la_pin_list().size()); + if (a_pin_num > b_pin_num) { + sort_status = SortStatus::kTrue; + } else if (a_pin_num == b_pin_num) { + sort_status = SortStatus::kEqual; + } else { + sort_status = SortStatus::kFalse; + } + } + if (sort_status == SortStatus::kTrue) { + return true; + } else if (sort_status == SortStatus::kFalse) { + return false; + } + return false; + } +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp new file mode 100644 index 000000000..3ca62c8a3 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp @@ -0,0 +1,142 @@ +// *************************************************************************************** +// 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 "Direction.hpp" +#include "LayerCoord.hpp" +#include "Orientation.hpp" +#include "RTHeader.hpp" +#include "Utility.hpp" + +namespace irt { + +#if 1 // astar +enum class LANodeState +{ + kNone = 0, + kOpen = 1, + kClose = 2 +}; +#endif + +class LANode : public LayerCoord +{ + public: + LANode() = default; + ~LANode() = default; + // getter + std::map& get_neighbor_node_map() { return _neighbor_node_map; } + std::map& get_orient_supply_map() { return _orient_supply_map; } + std::map& get_orient_demand_map() { return _orient_demand_map; } + // setter + void set_neighbor_node_map(const std::map& neighbor_node_map) { _neighbor_node_map = neighbor_node_map; } + void set_orient_supply_map(const std::map& orient_supply_map) { _orient_supply_map = orient_supply_map; } + void set_orient_demand_map(const std::map& orient_demand_map) { _orient_demand_map = orient_demand_map; } + // function + LANode* getNeighborNode(Orientation orientation) + { + LANode* neighbor_node = nullptr; + if (RTUTIL.exist(_neighbor_node_map, orientation)) { + neighbor_node = _neighbor_node_map[orientation]; + } + return neighbor_node; + } + double getCongestionCost(Orientation orientation) + { + double cost = 0; + if (orientation != Orientation::kAbove && orientation != Orientation::kBelow) { + int32_t node_demand = 0; + if (RTUTIL.exist(_orient_demand_map, orientation)) { + node_demand = _orient_demand_map[orientation]; + } + int32_t node_supply = 0; + if (RTUTIL.exist(_orient_supply_map, orientation)) { + node_supply = _orient_supply_map[orientation]; + } + cost += calcCost(node_demand + 1, node_supply); + } + return cost; + } + double calcCost(double demand, double supply) + { + double cost = 0; + if (demand == supply) { + cost = 1; + } else if (demand > supply) { + cost = std::pow(demand - supply + 1, 2); + } else if (demand < supply) { + cost = std::pow(demand / supply, 2); + } + return cost; + } + void updateDemand(std::set orient_set, ChangeType change_type) + { + for (const Orientation& orient : orient_set) { + if (orient == Orientation::kEast || orient == Orientation::kWest || orient == Orientation::kSouth || orient == Orientation::kNorth) { + _orient_demand_map[orient] += (change_type == ChangeType::kAdd ? 1 : -1); + } + } + } +#if 1 // astar + // single path + LANodeState& get_state() { return _state; } + LANode* get_parent_node() const { return _parent_node; } + double get_known_cost() const { return _known_cost; } + double get_estimated_cost() const { return _estimated_cost; } + void set_state(LANodeState state) { _state = state; } + void set_parent_node(LANode* parent_node) { _parent_node = parent_node; } + void set_known_cost(const double known_cost) { _known_cost = known_cost; } + void set_estimated_cost(const double estimated_cost) { _estimated_cost = estimated_cost; } + // function + bool isNone() { return _state == LANodeState::kNone; } + bool isOpen() { return _state == LANodeState::kOpen; } + bool isClose() { return _state == LANodeState::kClose; } + double getTotalCost() { return (_known_cost + _estimated_cost); } +#endif + + private: + std::map _neighbor_node_map; + std::map _orient_supply_map; + std::map _orient_demand_map; +#if 1 // astar + // single path + LANodeState _state = LANodeState::kNone; + LANode* _parent_node = nullptr; + double _known_cost = 0.0; // include curr + double _estimated_cost = 0.0; +#endif +}; + +#if 1 // astar +struct CmpLANodeCost +{ + bool operator()(LANode* a, LANode* b) + { + if (RTUTIL.equalDoubleByError(a->getTotalCost(), b->getTotalCost(), RT_ERROR)) { + if (RTUTIL.equalDoubleByError(a->get_estimated_cost(), b->get_estimated_cost(), RT_ERROR)) { + return a->get_neighbor_node_map().size() < b->get_neighbor_node_map().size(); + } else { + return a->get_estimated_cost() > b->get_estimated_cost(); + } + } else { + return a->getTotalCost() > b->getTotalCost(); + } + } +}; +#endif + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAParameter.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAParameter.hpp new file mode 100644 index 000000000..3573cfa83 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAParameter.hpp @@ -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. +// *************************************************************************************** +#pragma once + +namespace irt { + +class LAParameter +{ + public: + LAParameter() = default; + LAParameter(int32_t topo_spilt_length, double congestion_unit, double prefer_wire_unit, double via_unit) + { + _topo_spilt_length = 10; + _congestion_unit = 2; + _prefer_wire_unit = 1; + _via_unit = 1; + } + ~LAParameter() = default; + // getter + int32_t get_topo_spilt_length() const { return _topo_spilt_length; } + double get_congestion_unit() const { return _congestion_unit; } + double get_prefer_wire_unit() const { return _prefer_wire_unit; } + double get_via_unit() const { return _via_unit; } + // setter + void set_topo_spilt_length(const int32_t topo_spilt_length) { _topo_spilt_length = topo_spilt_length; } + void set_congestion_unit(const double congestion_unit) { _congestion_unit = congestion_unit; } + void set_prefer_wire_unit(const double prefer_wire_unit) { _prefer_wire_unit = prefer_wire_unit; } + void set_via_unit(const double via_unit) { _via_unit = via_unit; } + + private: + int32_t _topo_spilt_length = 0; + double _congestion_unit = 0; + double _prefer_wire_unit = 0; + double _via_unit = 0; +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAPin.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAPin.hpp new file mode 100644 index 000000000..6272262a8 --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAPin.hpp @@ -0,0 +1,41 @@ +// *************************************************************************************** +// 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 "AccessPoint.hpp" +#include "EXTLayerRect.hpp" +#include "PlanarCoord.hpp" +#include "RTHeader.hpp" + +namespace irt { + +class LAPin : public Pin +{ + public: + LAPin() = default; + explicit LAPin(const Pin& pin) : Pin(pin) {} + ~LAPin() = default; + // getter + + // setter + + // function + + private: +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LATopo.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LATopo.hpp new file mode 100644 index 000000000..82ceb2dda --- /dev/null +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LATopo.hpp @@ -0,0 +1,53 @@ +// *************************************************************************************** +// 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 "LAGroup.hpp" + +namespace irt { + +class LATopo +{ + public: + LATopo() = default; + ~LATopo() = default; + // getter + int32_t get_net_idx() { return _net_idx; } + std::vector& get_la_group_list() { return _la_group_list; } + PlanarRect& get_bounding_box() { return _bounding_box; } + std::vector>& get_routing_segment_list() { return _routing_segment_list; } + // const getter + const std::vector& get_la_group_list() const { return _la_group_list; } + const PlanarRect& get_bounding_box() const { return _bounding_box; } + // setter + void set_net_idx(const int32_t net_idx) { _net_idx = net_idx; } + void set_la_group_list(const std::vector& la_group_list) { _la_group_list = la_group_list; } + void set_bounding_box(const PlanarRect& bounding_box) { _bounding_box = bounding_box; } + void set_routing_segment_list(const std::vector>& routing_segment_list) + { + _routing_segment_list = routing_segment_list; + } + // function + + private: + int32_t _net_idx = -1; + std::vector _la_group_list; + PlanarRect _bounding_box; + std::vector> _routing_segment_list; +}; + +} // namespace irt diff --git a/src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp b/src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp index 406b0fb58..5018018e1 100644 --- a/src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp +++ b/src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp @@ -61,15 +61,16 @@ void PinAccessor::access() Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); PAModel pa_model = initPAModel(); - initAccessPointList(pa_model); - uploadAccessPointList(pa_model); - buildNonConflictPoint(pa_model); // debugPlotPAModel(pa_model, "before"); setPAParameter(pa_model); + initAccessPointList(pa_model); + uploadAccessPointList(pa_model); + // debugPlotPAModel(pa_model, "middle"); initPABoxMap(pa_model); buildBoxSchedule(pa_model); routePABoxMap(pa_model); - updatePAModel(pa_model); + uploadAccessPoint(pa_model); + ignoreViolation(pa_model); // debugPlotPAModel(pa_model, "after"); updateSummary(pa_model); printSummary(pa_model); @@ -114,6 +115,35 @@ PANet PinAccessor::convertToPANet(Net& net) return pa_net; } +void PinAccessor::setPAParameter(PAModel& pa_model) +{ + int32_t cost_unit = RTDM.getOnlyPitch(); + double prefer_wire_unit = 1; + double non_prefer_wire_unit = 2.5; + double via_unit = cost_unit; + double fixed_rect_unit = 4 * non_prefer_wire_unit * cost_unit; + double routed_rect_unit = 2 * via_unit; + double violation_unit = 4 * non_prefer_wire_unit * cost_unit; + /** + * prefer_wire_unit, non_prefer_wire_unit, via_unit, size, offset, fixed_rect_unit, routed_rect_unit, violation_unit, max_routed_times, + * max_candidate_point_num + */ + // clang-format off + PAParameter pa_parameter(prefer_wire_unit, non_prefer_wire_unit, via_unit, 1, 0, fixed_rect_unit, routed_rect_unit, violation_unit, 10, 10); + // clang-format on + RTLOG.info(Loc::current(), "prefer_wire_unit: ", pa_parameter.get_prefer_wire_unit()); + RTLOG.info(Loc::current(), "non_prefer_wire_unit: ", pa_parameter.get_non_prefer_wire_unit()); + RTLOG.info(Loc::current(), "via_unit: ", pa_parameter.get_via_unit()); + RTLOG.info(Loc::current(), "size: ", pa_parameter.get_size()); + RTLOG.info(Loc::current(), "offset: ", pa_parameter.get_offset()); + RTLOG.info(Loc::current(), "fixed_rect_unit: ", pa_parameter.get_fixed_rect_unit()); + RTLOG.info(Loc::current(), "routed_rect_unit: ", pa_parameter.get_routed_rect_unit()); + RTLOG.info(Loc::current(), "violation_unit: ", pa_parameter.get_violation_unit()); + RTLOG.info(Loc::current(), "max_routed_times: ", pa_parameter.get_max_routed_times()); + RTLOG.info(Loc::current(), "max_candidate_point_num: ", pa_parameter.get_max_candidate_point_num()); + pa_model.set_pa_parameter(pa_parameter); +} + void PinAccessor::initAccessPointList(PAModel& pa_model) { Monitor monitor; @@ -139,7 +169,7 @@ void PinAccessor::initAccessPointList(PAModel& pa_model) PAPin* pin = net_pin_pair.second; std::vector& access_point_list = net_pin_pair.second->get_access_point_list(); std::vector legal_shape_list = getLegalShapeList(pa_model, net_pin_pair.first, pin); - for (AccessPoint& access_point : getAccessPointList(pin->get_pin_idx(), legal_shape_list)) { + for (AccessPoint& access_point : getAccessPointList(pa_model, pin->get_pin_idx(), legal_shape_list)) { if (!RTUTIL.isInside(die_valid_rect, access_point.get_real_coord())) { continue; } @@ -147,7 +177,6 @@ void PinAccessor::initAccessPointList(PAModel& pa_model) } // 对于分散在多个gcell内的ap,取最多的留下 { - std::vector max_access_point_list; std::map, CmpPlanarCoordByXASC> grid_access_point_idx_map; for (size_t i = 0; i < access_point_list.size(); i++) { PlanarCoord grid_coord = RTUTIL.getGCellGridCoordByBBox(access_point_list[i].get_real_coord(), gcell_axis, die); @@ -162,6 +191,7 @@ void PinAccessor::initAccessPointList(PAModel& pa_model) max_access_point_idx_set = access_point_idx_set; } } + std::vector max_access_point_list; for (size_t access_point_idx : max_access_point_idx_set) { max_access_point_list.push_back(access_point_list[access_point_idx]); } @@ -273,13 +303,29 @@ std::vector PinAccessor::getPlanarLegalRectList(PAModel& pa_model, i continue; } for (EXTLayerRect* fixed_rect : fixed_rect_set) { - int32_t min_spacing = routing_layer.getMinSpacing(fixed_rect->get_real_rect()); - int32_t enlarged_x_size = min_spacing + enclosure_half_x_span; - int32_t enlarged_y_size = min_spacing + enclosure_half_y_span; - PlanarRect enlarged_rect - = RTUTIL.getEnlargedRect(fixed_rect->get_real_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); - if (RTUTIL.isOpenOverlap(shrinked_rect.get_real_rect(), enlarged_rect)) { - routing_obs_shape_list.push_back(enlarged_rect); + // x_spacing y_spacing + std::vector> spacing_pair_list; + { + // prl + int32_t prl_spacing = routing_layer.getPRLSpacing(fixed_rect->get_real_rect()); + spacing_pair_list.emplace_back(prl_spacing, prl_spacing); + if (layer_idx != curr_layer_idx) { + // eol + if (routing_layer.isPreferH()) { + spacing_pair_list.emplace_back(routing_layer.get_eol_spacing(), routing_layer.get_eol_within()); + } else { + spacing_pair_list.emplace_back(routing_layer.get_eol_within(), routing_layer.get_eol_spacing()); + } + } + } + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = x_spacing + enclosure_half_x_span; + int32_t enlarged_y_size = y_spacing + enclosure_half_y_span; + PlanarRect enlarged_rect = RTUTIL.getEnlargedRect(fixed_rect->get_real_rect(), enlarged_x_size, enlarged_y_size, + enlarged_x_size, enlarged_y_size); + if (RTUTIL.isOpenOverlap(shrinked_rect.get_real_rect(), enlarged_rect)) { + routing_obs_shape_list.push_back(enlarged_rect); + } } } } @@ -305,8 +351,10 @@ std::vector PinAccessor::getPlanarLegalRectList(PAModel& pa_model, i return legal_rect_list; } -std::vector PinAccessor::getAccessPointList(int32_t pin_idx, std::vector& legal_shape_list) +std::vector PinAccessor::getAccessPointList(PAModel& pa_model, int32_t pin_idx, std::vector& legal_shape_list) { + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::vector layer_coord_list; for (LayerRect& legal_shape : legal_shape_list) { int32_t ll_x = legal_shape.get_ll_x(); @@ -316,6 +364,27 @@ std::vector PinAccessor::getAccessPointList(int32_t pin_idx, std::v int32_t curr_layer_idx = legal_shape.get_layer_idx(); int32_t mid_x = (ll_x + ur_x) / 2; int32_t mid_y = (ll_y + ur_y) / 2; + RoutingLayer curr_routing_layer = routing_layer_list[curr_layer_idx]; + // track grid + for (int32_t x : RTUTIL.getScaleList(ll_x, ur_x, curr_routing_layer.getXTrackGridList())) { + for (int32_t y : RTUTIL.getScaleList(ll_y, ur_y, curr_routing_layer.getYTrackGridList())) { + layer_coord_list.emplace_back(x, y, curr_layer_idx); + } + } + // on track + { + for (int32_t x : {ll_x, mid_x, ur_x}) { + for (int32_t y : RTUTIL.getScaleList(ll_y, ur_y, curr_routing_layer.getYTrackGridList())) { + layer_coord_list.emplace_back(x, y, curr_layer_idx); + } + } + for (int32_t x : RTUTIL.getScaleList(ll_x, ur_x, curr_routing_layer.getXTrackGridList())) { + for (int32_t y : {ll_y, mid_y, ur_y}) { + layer_coord_list.emplace_back(x, y, curr_layer_idx); + } + } + } + // on shape for (int32_t x : {ll_x, mid_x, ur_x}) { for (int32_t y : {ll_y, mid_y, ur_y}) { layer_coord_list.emplace_back(x, y, curr_layer_idx); @@ -324,14 +393,40 @@ std::vector PinAccessor::getAccessPointList(int32_t pin_idx, std::v } 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(pa_model, layer_coord_list); std::vector access_point_list; for (LayerCoord& layer_coord : layer_coord_list) { - access_point_list.emplace_back(pin_idx, layer_coord, AccessPointType::kOnShape); + access_point_list.emplace_back(pin_idx, layer_coord, AccessPointType::kNoAccess); } return access_point_list; } +void PinAccessor::uniformSampleCoordList(PAModel& pa_model, std::vector& layer_coord_list) +{ + int32_t max_candidate_point_num = pa_model.get_pa_parameter().get_max_candidate_point_num(); + + PlanarRect bounding_box = RTUTIL.getBoundingBox(layer_coord_list); + int32_t grid_num = static_cast(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 visited_set; + std::vector new_layer_coord_list; + for (LayerCoord& layer_coord : layer_coord_list) { + PlanarCoord grid_coord(static_cast((layer_coord.get_x() - bounding_box.get_ll_x()) / grid_x_span), + static_cast((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(new_layer_coord_list.size()) >= max_candidate_point_num) { + break; + } + } + } + layer_coord_list = new_layer_coord_list; +} + void PinAccessor::uploadAccessPointList(PAModel& pa_model) { Monitor monitor; @@ -365,197 +460,6 @@ void PinAccessor::uploadAccessPointList(PAModel& pa_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } -void PinAccessor::buildNonConflictPoint(PAModel& pa_model) -{ - Monitor monitor; - RTLOG.info(Loc::current(), "Starting..."); - - std::vector> pin_segment_list = getPinSegmentList(pa_model); - for (std::vector& pin_group : getPinGroupList(pin_segment_list)) { - for (auto& [pa_pin, best_coord] : getPinBestCoordMap(pin_group)) { - pa_pin->set_best_coord(best_coord); - } - } - // 将没有conflict的pin设置best_coord - for (PANet& pa_net : pa_model.get_pa_net_list()) { - for (PAPin& pa_pin : pa_net.get_pa_pin_list()) { - if (pa_pin.get_best_coord().get_x() < 0 && pa_pin.get_best_coord().get_y() < 0) { - pa_pin.set_best_coord(pa_pin.get_access_point_list().front().get_real_coord()); - } - } - } - RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); -} - -std::vector> PinAccessor::getPinSegmentList(PAModel& pa_model) -{ - Die& die = RTDM.getDatabase().get_die(); - GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); - - std::vector>> pin_pin_set_pair_list; - for (PANet& pa_net : pa_model.get_pa_net_list()) { - for (PAPin& pa_pin : pa_net.get_pa_pin_list()) { - pin_pin_set_pair_list.emplace_back(&pa_pin, std::set{}); - } - } -#pragma omp parallel for - for (std::pair>& pin_pin_set_pair : pin_pin_set_pair_list) { - PAPin* curr_pin = pin_pin_set_pair.first; - std::vector& curr_access_point_list = curr_pin->get_access_point_list(); - // 构建周围pin与周围access_point - { - std::map> gcell_pin_access_map; - for (AccessPoint& curr_access_point : curr_access_point_list) { - PlanarCoord& grid_coord = curr_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) { - PAPin* gcell_pin = &pa_model.get_pa_net_list()[net_idx].get_pa_pin_list()[gcell_access_point->get_pin_idx()]; - if (curr_pin == gcell_pin) { - continue; - } - gcell_pin_access_map[gcell_pin].push_back(gcell_access_point); - } - } - } - } - } - // 查找具有冲突的gcell_pin - PlanarRect curr_searched_rect; - { - std::vector curr_coord_list; - for (AccessPoint& curr_access_point : curr_access_point_list) { - curr_coord_list.push_back(curr_access_point.get_real_coord()); - } - curr_searched_rect = RTUTIL.getEnlargedRect(RTUTIL.getBoundingBox(curr_coord_list), 2 * RTDM.getOnlyPitch()); - } - for (auto& [gcell_pin, gcell_access_point_list] : gcell_pin_access_map) { - std::vector gcell_coord_list; - for (AccessPoint* gcell_access_point : gcell_access_point_list) { - gcell_coord_list.push_back(gcell_access_point->get_real_coord()); - } - PlanarRect gcell_bounding_box = RTUTIL.getBoundingBox(gcell_coord_list); - if (RTUTIL.isOverlap(curr_searched_rect, gcell_bounding_box)) { - pin_pin_set_pair.second.insert(gcell_pin); - } - } - } - } - std::vector> pin_segment_list; - for (std::pair>& pin_pin_set_pair : pin_pin_set_pair_list) { - PAPin* curr_pin = pin_pin_set_pair.first; - for (PAPin* gcell_pin : pin_pin_set_pair.second) { - pin_segment_list.emplace_back(curr_pin, gcell_pin); - } - } - return pin_segment_list; -} - -std::vector> PinAccessor::getPinGroupList(std::vector>& pin_segment_list) -{ - std::map> pin_conflict_map; - std::set visited_pin_set; - - for (Segment& pin_segment : pin_segment_list) { - pin_conflict_map[pin_segment.get_first()].push_back(pin_segment.get_second()); - pin_conflict_map[pin_segment.get_second()].push_back(pin_segment.get_first()); - } - auto dfs = [&](PAPin* pa_pin, std::vector& pin_group) { - std::stack stack; - stack.push(pa_pin); - while (!stack.empty()) { - PAPin* curr_pin = stack.top(); - stack.pop(); - if (visited_pin_set.count(curr_pin) == 0) { - visited_pin_set.insert(curr_pin); - pin_group.push_back(curr_pin); - for (PAPin* conflict_pin : pin_conflict_map[curr_pin]) { - if (visited_pin_set.count(conflict_pin) == 0) { - stack.push(conflict_pin); - } - } - } - } - }; - std::vector> pin_group_list; - for (auto& [curr_pin, conflict_pin_set] : pin_conflict_map) { - if (visited_pin_set.count(curr_pin) == 0) { - std::vector pin_group; - dfs(curr_pin, pin_group); - pin_group_list.push_back(pin_group); - } - } - return pin_group_list; -} - -std::map PinAccessor::getPinBestCoordMap(std::vector& pin_group) -{ - std::vector> candidate_coord_list_list; - for (PAPin* pa_pin : pin_group) { - std::vector candidate_coord_list; - for (AccessPoint& access_point : pa_pin->get_access_point_list()) { - candidate_coord_list.push_back(access_point.get_real_coord()); - } - candidate_coord_list_list.push_back(candidate_coord_list); - } - std::vector best_coord_list; - for (const auto& coord_list : candidate_coord_list_list) { - best_coord_list.push_back(coord_list.front()); - } - bool improved = true; - while (improved) { - improved = false; - for (int32_t i = 0; i < static_cast(candidate_coord_list_list.size()); ++i) { - int32_t max_min_distance = INT32_MIN; - PlanarCoord best_coord = best_coord_list[i]; - for (const PlanarCoord& candidate_coord : candidate_coord_list_list[i]) { - int32_t min_distance = INT32_MAX; - for (int32_t j = 0; j < static_cast(best_coord_list.size()); ++j) { - if (i != j) { - min_distance = std::min(min_distance, RTUTIL.getManhattanDistance(candidate_coord, best_coord_list[j])); - } - } - if (max_min_distance < min_distance) { - max_min_distance = min_distance; - best_coord = candidate_coord; - } - } - if (best_coord.get_x() != best_coord_list[i].get_x() || best_coord.get_y() != best_coord_list[i].get_y()) { - best_coord_list[i] = best_coord; - improved = true; - } - } - } - std::map pin_coord_map; - for (size_t i = 0; i < pin_group.size(); ++i) { - pin_coord_map[pin_group[i]] = best_coord_list[i]; - } - return pin_coord_map; -} - -void PinAccessor::setPAParameter(PAModel& pa_model) -{ - int32_t cost_unit = 8; - /** - * prefer_wire_unit, non_prefer_wire_unit, via_unit, size, offset, fixed_rect_unit, routed_rect_unit, violation_unit, max_routed_times - */ - PAParameter pa_parameter(1, 2.5, RTDM.getOnlyPitch(), 1, 0, 128 * cost_unit, 32 * cost_unit, 32 * cost_unit, 4); - RTLOG.info(Loc::current(), "prefer_wire_unit: ", pa_parameter.get_prefer_wire_unit()); - RTLOG.info(Loc::current(), "non_prefer_wire_unit: ", pa_parameter.get_non_prefer_wire_unit()); - RTLOG.info(Loc::current(), "via_unit: ", pa_parameter.get_via_unit()); - RTLOG.info(Loc::current(), "size: ", pa_parameter.get_size()); - RTLOG.info(Loc::current(), "offset: ", pa_parameter.get_offset()); - RTLOG.info(Loc::current(), "fixed_rect_unit: ", pa_parameter.get_fixed_rect_unit()); - RTLOG.info(Loc::current(), "routed_rect_unit: ", pa_parameter.get_routed_rect_unit()); - RTLOG.info(Loc::current(), "violation_unit: ", pa_parameter.get_violation_unit()); - RTLOG.info(Loc::current(), "max_routed_times: ", pa_parameter.get_max_routed_times()); - pa_model.set_pa_parameter(pa_parameter); -} - void PinAccessor::initPABoxMap(PAModel& pa_model) { ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); @@ -608,7 +512,7 @@ void PinAccessor::buildBoxSchedule(PAModel& pa_model) { GridMap& pa_box_map = pa_model.get_pa_box_map(); - int32_t range = 2; + int32_t range = 3; std::vector> pa_box_id_list_list; for (int32_t start_x = 0; start_x < range; start_x++) { @@ -652,13 +556,14 @@ void PinAccessor::routePABoxMap(PAModel& pa_model) buildLayerNodeMap(pa_box); buildPANodeNeighbor(pa_box); buildOrientNetMap(pa_box); + exemptPinShape(pa_box); // debugCheckPABox(pa_box); // debugPlotPABox(pa_box, -1, "before"); routePABox(pa_box); // debugPlotPABox(pa_box, -1, "after"); uploadAccessResult(pa_box); - uploadViolation(pa_box); } + uploadViolation(pa_box); freePABox(pa_box); } routed_box_num += pa_box_id_list.size(); @@ -763,28 +668,15 @@ void PinAccessor::initPATaskList(PAModel& pa_model, PABox& pa_box) } pa_group_list.back().set_is_target(true); for (const LayerCoord& coord : coord_set) { - pa_group_list.back().get_coord_list().push_back(coord); - } - // 选取优先区域内的点作为布线点 - { - PlanarCoord& best_coord = pa_pin.get_best_coord(); - if (best_coord.get_x() == -1 || best_coord.get_y() == -1) { - RTLOG.error(Loc::current(), "The best_coord is not initialized!"); + bool in_shape = false; + for (EXTLayerRect& routing_shape : pa_pin.get_routing_shape_list()) { + if (routing_shape.get_layer_idx() == coord.get_layer_idx() && RTUTIL.isInside(routing_shape.get_real_rect(), coord)) { + in_shape = true; + break; + } } - PlanarRect priority_area = RTUTIL.getEnlargedRect(best_coord, RTDM.getOnlyPitch()); - for (PAGroup& pa_group : pa_group_list) { - std::vector& coord_list = pa_group.get_coord_list(); - std::vector temp_coord_list; - for (LayerCoord& coord : coord_list) { - if (RTUTIL.isInside(priority_area, coord)) { - temp_coord_list.push_back(coord); - } - } - if (temp_coord_list.empty()) { - RTLOG.error(Loc::current(), "The coord_list in priority_area is empty!"); - } else { - coord_list = temp_coord_list; - } + if (!in_shape) { + pa_group_list.back().get_coord_list().push_back(coord); } } } @@ -940,20 +832,37 @@ void PinAccessor::buildOrientNetMap(PABox& pa_box) } } for (Violation& violation : pa_box.get_violation_list()) { - updateViolationToGraph(pa_box, ChangeType::kAdd, violation); + addViolationToGraph(pa_box, violation); + } +} + +void PinAccessor::exemptPinShape(PABox& pa_box) +{ + std::vector>& layer_node_map = pa_box.get_layer_node_map(); + for (GridMap& pa_node_map : layer_node_map) { + for (int32_t x = 0; x < pa_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < pa_node_map.get_y_size(); y++) { + PANode& pa_node = pa_node_map[x][y]; + for (auto& [orient, net_set] : pa_node.get_orient_fixed_rect_map()) { + if (RTUTIL.exist(net_set, -1) && net_set.size() >= 2) { + net_set.erase(-1); + } + } + } + } } } void PinAccessor::routePABox(PABox& pa_box) { - std::vector pa_task_list = initTaskSchedule(pa_box); - while (!pa_task_list.empty()) { - for (PATask* pa_task : pa_task_list) { - routePATask(pa_box, pa_task); - pa_task->addRoutedTimes(); + std::vector routing_task_list = initTaskSchedule(pa_box); + while (!routing_task_list.empty()) { + for (PATask* routing_task : routing_task_list) { + routePATask(pa_box, routing_task); + routing_task->addRoutedTimes(); } updateViolationList(pa_box); - pa_task_list = getTaskScheduleByViolation(pa_box); + updateTaskSchedule(pa_box, routing_task_list); } } @@ -976,8 +885,6 @@ void PinAccessor::routePATask(PABox& pa_box, PATask* pa_task) resetSinglePath(pa_box); } updateTaskResult(pa_box); - patchSingleTask(pa_box); - updateTaskPatch(pa_box); resetSingleTask(pa_box); } @@ -1084,7 +991,7 @@ void PinAccessor::expandSearching(PABox& pa_box) if (neighbor_node->isOpen() && know_cost < neighbor_node->get_known_cost()) { neighbor_node->set_known_cost(know_cost); neighbor_node->set_parent_node(path_head_node); - // 对优先队列中的值修改了,需要重新建堆 + // 对优先队列中的值修改了,需要重新建堆 std::make_heap(open_queue.begin(), open_queue.end(), CmpPANodeCost()); } else if (neighbor_node->isNone()) { neighbor_node->set_known_cost(know_cost); @@ -1141,7 +1048,7 @@ void PinAccessor::resetStartAndEnd(PABox& pa_box) PANode* path_head_node = pa_box.get_path_head_node(); int32_t end_node_list_idx = pa_box.get_end_node_list_idx(); - // 对于抵达的终点pin,只保留到达的node + // 对于抵达的终点pin,只保留到达的node end_node_list_list[end_node_list_idx].clear(); end_node_list_list[end_node_list_idx].push_back(path_head_node); @@ -1157,7 +1064,7 @@ void PinAccessor::resetStartAndEnd(PABox& pa_box) } } if (start_node_list_list.size() == 1) { - // 初始化时,要把start_node_list_list的pin只留一个ap点 + // 初始化时,要把start_node_list_list的pin只留一个ap点 // 后续只要将end_node_list_list的pin保留一个ap点 start_node_list_list.front().clear(); start_node_list_list.front().push_back(path_node); @@ -1225,106 +1132,6 @@ std::vector> PinAccessor::getRoutingSegmentList(PABox& pa_bo return routing_segment_list; } -void PinAccessor::patchSingleTask(PABox& pa_box) -{ - ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); - - for (auto getRealPatchList : {std::bind(&PinAccessor::getMinimumAreaPatchList, this, std::placeholders::_1), - std::bind(&PinAccessor::getMinStepPatchList, this, std::placeholders::_1)}) { - for (LayerRect real_patch : getRealPatchList(pa_box)) { - EXTLayerRect routing_patch; - routing_patch.set_real_rect(real_patch); - routing_patch.set_layer_idx(real_patch.get_layer_idx()); - routing_patch.set_grid_rect(RTUTIL.getClosedGCellGridRect(routing_patch.get_real_rect(), gcell_axis)); - pa_box.get_routing_patch_list().push_back(routing_patch); - } - } -} - -std::vector PinAccessor::getMinimumAreaPatchList(PABox& pa_box) -{ - return {}; - std::vector real_patch_list; - for (Violation patch_violation : getPatchViolationList(pa_box)) { - if (patch_violation.get_violation_type() != ViolationType::kMinimumArea) { - continue; - } - EXTLayerRect& violation_shape = patch_violation.get_violation_shape(); - real_patch_list.push_back(violation_shape.get_real_rect()); - } - return real_patch_list; -} - -std::vector PinAccessor::getMinStepPatchList(PABox& pa_box) -{ - std::vector real_patch_list; - for (Violation patch_violation : getPatchViolationList(pa_box)) { - if (patch_violation.get_violation_type() != ViolationType::kMinStep) { - continue; - } - real_patch_list.push_back(patch_violation.get_violation_shape().get_real_rect()); - } - return real_patch_list; -} - -std::vector PinAccessor::getPatchViolationList(PABox& pa_box) -{ - int32_t curr_net_idx = pa_box.get_curr_pa_task()->get_net_idx(); - int32_t curr_task_idx = pa_box.get_curr_pa_task()->get_task_idx(); - - std::string top_name - = RTUTIL.getString("pa_box_", pa_box.get_pa_box_id().get_x(), "_", pa_box.get_pa_box_id().get_y(), "_", curr_task_idx); - PlanarRect check_region = pa_box.get_box_rect().get_real_rect(); - - std::map>> net_pin_shape_map; - for (auto& [is_routing, layer_net_fixed_rect_map] : pa_box.get_type_layer_net_fixed_rect_map()) { - for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { - for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { - if (net_idx == curr_net_idx) { - for (auto& fixed_rect : fixed_rect_set) { - net_pin_shape_map[net_idx].emplace_back(fixed_rect, is_routing); - } - } - } - } - } - std::map>> net_check_result_map; - for (Segment& segment : pa_box.get_net_task_result_map()[curr_net_idx][curr_task_idx]) { - net_check_result_map[curr_net_idx].emplace_back(segment); - } - DETask de_task; - de_task.set_process_type_set({DEProcessType::kRoutingPatch}); - de_task.set_top_name(top_name); - de_task.set_check_region(check_region); - de_task.set_net_pin_shape_map(net_pin_shape_map); - de_task.set_net_check_result_map(net_check_result_map); - return RTDE.getViolationList(de_task); -} - -void PinAccessor::updateTaskPatch(PABox& pa_box) -{ - std::vector new_routing_patch_list = getRoutingPatchList(pa_box); - - int32_t curr_net_idx = pa_box.get_curr_pa_task()->get_net_idx(); - int32_t curr_task_idx = pa_box.get_curr_pa_task()->get_task_idx(); - std::vector& routing_patch_list = pa_box.get_net_task_patch_map()[curr_net_idx][curr_task_idx]; - - // 原结果从graph删除,由于task有对应net_idx,所以不需要在布线前进行删除也不会影响结果 - for (EXTLayerRect& routing_patch : routing_patch_list) { - updateNetResultToGraph(pa_box, ChangeType::kDel, curr_net_idx, routing_patch); - } - routing_patch_list = new_routing_patch_list; - // 新结果添加到graph - for (EXTLayerRect& routing_patch : routing_patch_list) { - updateNetResultToGraph(pa_box, ChangeType::kAdd, curr_net_idx, routing_patch); - } -} - -std::vector PinAccessor::getRoutingPatchList(PABox& pa_box) -{ - return pa_box.get_routing_patch_list(); -} - void PinAccessor::resetSingleTask(PABox& pa_box) { pa_box.set_curr_pa_task(nullptr); @@ -1333,7 +1140,6 @@ void PinAccessor::resetSingleTask(PABox& pa_box) pa_box.get_path_node_list().clear(); pa_box.get_single_task_visited_node_list().clear(); pa_box.get_routing_segment_list().clear(); - pa_box.get_routing_patch_list().clear(); } // manager open list @@ -1475,17 +1281,13 @@ double PinAccessor::getEstimateViaCost(PABox& pa_box, PANode* start_node, PANode void PinAccessor::updateViolationList(PABox& pa_box) { - std::vector new_violation_list = getCostViolationList(pa_box); - - std::vector& violation_list = pa_box.get_violation_list(); - // 原结果从graph删除 - for (Violation& violation : violation_list) { - updateViolationToGraph(pa_box, ChangeType::kDel, violation); + pa_box.get_violation_list().clear(); + for (Violation new_violation : getCostViolationList(pa_box)) { + pa_box.get_violation_list().push_back(new_violation); } - violation_list = new_violation_list; // 新结果添加到graph - for (Violation& violation : violation_list) { - updateViolationToGraph(pa_box, ChangeType::kAdd, violation); + for (Violation& violation : pa_box.get_violation_list()) { + addViolationToGraph(pa_box, violation); } } @@ -1510,68 +1312,79 @@ std::vector PinAccessor::getCostViolationList(PABox& pa_box) } } } - std::map*>> net_env_result_map; + std::map*>> net_result_map; for (auto& [net_idx, segment_set] : pa_box.get_net_access_result_map()) { for (Segment* segment : segment_set) { - net_env_result_map[net_idx].push_back(segment); + net_result_map[net_idx].push_back(segment); } } - std::map> net_env_patch_map; - for (auto& [net_idx, patch_set] : pa_box.get_net_access_patch_map()) { - for (EXTLayerRect* patch : patch_set) { - net_env_patch_map[net_idx].push_back(patch); - } - } - std::map>> net_check_result_map; for (auto& [net_idx, task_result_map] : pa_box.get_net_task_result_map()) { for (auto& [task_idx, segment_list] : task_result_map) { for (Segment& segment : segment_list) { - net_check_result_map[net_idx].emplace_back(segment); + net_result_map[net_idx].emplace_back(&segment); } } } - std::map> net_check_patch_map; + std::map> net_patch_map; + for (auto& [net_idx, patch_set] : pa_box.get_net_access_patch_map()) { + for (EXTLayerRect* patch : patch_set) { + net_patch_map[net_idx].push_back(patch); + } + } for (auto& [net_idx, task_patch_map] : pa_box.get_net_task_patch_map()) { for (auto& [task_idx, patch_list] : task_patch_map) { for (EXTLayerRect& patch : patch_list) { - net_check_patch_map[net_idx].emplace_back(patch); + net_patch_map[net_idx].emplace_back(&patch); } } } + std::set need_checked_net_set; + for (PATask* pa_task : pa_box.get_pa_task_list()) { + need_checked_net_set.insert(pa_task->get_net_idx()); + } + DETask de_task; - de_task.set_process_type_set({DEProcessType::kRoutingCost, DEProcessType::kCutCost}); + de_task.set_process_type(DEProcessType::kMultiNet); de_task.set_top_name(top_name); de_task.set_check_region(check_region); de_task.set_env_shape_list(env_shape_list); de_task.set_net_pin_shape_map(net_pin_shape_map); - de_task.set_net_env_result_map(net_env_result_map); - de_task.set_net_env_patch_map(net_env_patch_map); - de_task.set_net_check_result_map(net_check_result_map); - de_task.set_net_check_patch_map(net_check_patch_map); + de_task.set_net_result_map(net_result_map); + de_task.set_net_patch_map(net_patch_map); + de_task.set_need_checked_net_set(need_checked_net_set); return RTDE.getViolationList(de_task); } -std::vector PinAccessor::getTaskScheduleByViolation(PABox& pa_box) +void PinAccessor::updateTaskSchedule(PABox& pa_box, std::vector& routing_task_list) { int32_t max_routed_times = pa_box.get_pa_parameter()->get_max_routed_times(); - std::set violation_net_set; + std::set visited_routing_task_set; + std::vector new_routing_task_list; for (Violation& violation : pa_box.get_violation_list()) { - for (int32_t violation_net : violation.get_violation_net_set()) { - violation_net_set.insert(violation_net); + for (PATask* pa_task : pa_box.get_pa_task_list()) { + if (!RTUTIL.exist(violation.get_violation_net_set(), pa_task->get_net_idx())) { + continue; + } + if (pa_task->get_routed_times() < max_routed_times && !RTUTIL.exist(visited_routing_task_set, pa_task)) { + visited_routing_task_set.insert(pa_task); + new_routing_task_list.push_back(pa_task); + } + break; } } - std::vector pa_task_list; + routing_task_list = new_routing_task_list; + + std::vector new_pa_task_list; for (PATask* pa_task : pa_box.get_pa_task_list()) { - if (!RTUTIL.exist(violation_net_set, pa_task->get_net_idx())) { - continue; + if (!RTUTIL.exist(visited_routing_task_set, pa_task)) { + new_pa_task_list.push_back(pa_task); } - if (pa_task->get_routed_times() >= max_routed_times) { - continue; - } - pa_task_list.push_back(pa_task); } - return pa_task_list; + for (PATask* routing_task : routing_task_list) { + new_pa_task_list.push_back(routing_task); + } + pa_box.set_pa_task_list(new_pa_task_list); } void PinAccessor::uploadAccessResult(PABox& pa_box) @@ -1664,7 +1477,7 @@ int32_t PinAccessor::getViolationNum() return static_cast(RTDM.getViolationSet(die).size()); } -void PinAccessor::updatePAModel(PAModel& pa_model) +void PinAccessor::uploadAccessPoint(PAModel& pa_model) { Monitor monitor; RTLOG.info(Loc::current(), "Starting..."); @@ -1704,12 +1517,26 @@ void PinAccessor::updatePAModel(PAModel& pa_model) RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); } +void PinAccessor::ignoreViolation(PAModel& pa_model) +{ + Monitor monitor; + RTLOG.info(Loc::current(), "Starting..."); + + Die& die = RTDM.getDatabase().get_die(); + + for (Violation* violation : RTDM.getViolationSet(die)) { + RTDM.updateViolationToGCellMap(ChangeType::kDel, violation); + } + RTDE.updateIgnoreViolationSet(); + RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); +} + #if 1 // update env void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect* fixed_rect, bool is_routing) { NetShape net_shape(net_idx, fixed_rect->getRealLayerRect(), is_routing); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { + for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { pa_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1723,7 +1550,7 @@ void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, Segment& segment) { for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, segment)) { - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { + for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { pa_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1738,7 +1565,7 @@ void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch) { NetShape net_shape(net_idx, patch.getRealLayerRect(), true); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { + for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { pa_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1752,7 +1579,7 @@ void PinAccessor::updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, void PinAccessor::updateNetResultToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, Segment& segment) { for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, segment)) { - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { + for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { pa_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1767,7 +1594,7 @@ void PinAccessor::updateNetResultToGraph(PABox& pa_box, ChangeType change_type, void PinAccessor::updateNetResultToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch) { NetShape net_shape(net_idx, patch.getRealLayerRect(), true); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { + for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { pa_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1778,32 +1605,114 @@ void PinAccessor::updateNetResultToGraph(PABox& pa_box, ChangeType change_type, } } -void PinAccessor::updateViolationToGraph(PABox& pa_box, ChangeType change_type, Violation& violation) +void PinAccessor::addViolationToGraph(PABox& pa_box, Violation& violation) { - NetShape net_shape(-1, violation.get_violation_shape().getRealLayerRect(), violation.get_is_routing()); - for (auto& [pa_node, orientation_set] : getNodeOrientationMap(pa_box, net_shape)) { - for (Orientation orientation : orientation_set) { - if (change_type == ChangeType::kAdd) { - pa_node->get_orient_violation_number_map()[orientation]++; - } else if (change_type == ChangeType::kDel) { - pa_node->get_orient_violation_number_map()[orientation]--; + LayerRect searched_rect; + { + EXTLayerRect& violation_shape = violation.get_violation_shape(); + searched_rect.set_rect(RTUTIL.getEnlargedRect(violation_shape.get_real_rect(), RTDM.getOnlyPitch())); + if (violation.get_is_routing()) { + searched_rect.set_layer_idx(violation_shape.get_layer_idx()); + } else { + RTLOG.error(Loc::current(), "The violation layer is cut!"); + } + } + std::vector> overlap_segment_list; + for (auto& [net_idx, task_result_map] : pa_box.get_net_task_result_map()) { + for (auto& [task_idx, segment_list] : task_result_map) { + if (!RTUTIL.exist(violation.get_violation_net_set(), net_idx)) { + continue; + } + for (Segment& segment : segment_list) { + if (!RTUTIL.isOverlap(searched_rect, segment)) { + continue; + } + overlap_segment_list.push_back(segment); + } + } + } + addViolationToGraph(pa_box, searched_rect, overlap_segment_list); +} + +void PinAccessor::addViolationToGraph(PABox& pa_box, LayerRect& searched_rect, std::vector>& overlap_segment_list) +{ + ScaleAxis& box_track_axis = pa_box.get_box_track_axis(); + std::vector>& layer_node_map = pa_box.get_layer_node_map(); + + for (Segment& overlap_segment : overlap_segment_list) { + LayerCoord& first_coord = overlap_segment.get_first(); + LayerCoord& second_coord = overlap_segment.get_second(); + if (first_coord == second_coord) { + continue; + } + PlanarRect real_rect = RTUTIL.getEnlargedRect(first_coord, second_coord, 0); + if (!RTUTIL.existTrackGrid(real_rect, box_track_axis)) { + continue; + } + PlanarRect grid_rect = RTUTIL.getTrackGrid(real_rect, box_track_axis); + std::map> distance_node_map; + { + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + for (int32_t layer_idx = first_layer_idx; layer_idx <= second_layer_idx; layer_idx++) { + for (int32_t x = grid_rect.get_ll_x(); x <= grid_rect.get_ur_x(); x++) { + for (int32_t y = grid_rect.get_ll_y(); y <= grid_rect.get_ur_y(); y++) { + PANode* pa_node = &layer_node_map[layer_idx][x][y]; + if (searched_rect.get_layer_idx() != pa_node->get_layer_idx()) { + continue; + } + int32_t distance = 0; + if (!RTUTIL.isInside(searched_rect.get_rect(), pa_node->get_planar_coord())) { + distance = RTUTIL.getManhattanDistance(searched_rect.getMidPoint(), pa_node->get_planar_coord()); + } + distance_node_map[distance].insert(pa_node); + } + } + } + } + std::set valid_node_set; + if (!distance_node_map[0].empty()) { + valid_node_set = distance_node_map[0]; + } else { + for (auto& [distance, node_set] : distance_node_map) { + valid_node_set.insert(node_set.begin(), node_set.end()); + if (valid_node_set.size() >= 2) { + break; + } + } + } + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + Orientation oppo_orientation = RTUTIL.getOppositeOrientation(orientation); + for (PANode* valid_node : valid_node_set) { + if (LayerCoord(*valid_node) != first_coord) { + valid_node->get_orient_violation_number_map()[oppo_orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), oppo_orientation)) { + valid_node->get_neighbor_node_map()[oppo_orientation]->get_orient_violation_number_map()[orientation]++; + } + } + if (LayerCoord(*valid_node) != second_coord) { + valid_node->get_orient_violation_number_map()[orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), orientation)) { + valid_node->get_neighbor_node_map()[orientation]->get_orient_violation_number_map()[oppo_orientation]++; + } } } } } -std::map> PinAccessor::getNodeOrientationMap(PABox& pa_box, NetShape& net_shape) +std::map> PinAccessor::getNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged) { std::map> node_orientation_map; if (net_shape.get_is_routing()) { - node_orientation_map = getRoutingNodeOrientationMap(pa_box, net_shape); + node_orientation_map = getRoutingNodeOrientationMap(pa_box, net_shape, need_enlarged); } else { - node_orientation_map = getCutNodeOrientationMap(pa_box, net_shape); + node_orientation_map = getCutNodeOrientationMap(pa_box, net_shape, need_enlarged); } return node_orientation_map; } -std::map> PinAccessor::getRoutingNodeOrientationMap(PABox& pa_box, NetShape& net_shape) +std::map> PinAccessor::getRoutingNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); std::map& layer_enclosure_map = RTDM.getDatabase().get_layer_enclosure_map(); @@ -1812,7 +1721,19 @@ std::map> PinAccessor::getRoutingNodeOrientationM } int32_t layer_idx = net_shape.get_layer_idx(); RoutingLayer& routing_layer = routing_layer_list[layer_idx]; - int32_t min_spacing = routing_layer.getMinSpacing(net_shape.get_rect()); + // x_spacing y_spacing + std::vector> spacing_pair_list; + { + // prl + int32_t prl_spacing = routing_layer.getPRLSpacing(net_shape.get_rect()); + spacing_pair_list.emplace_back(prl_spacing, prl_spacing); + // eol + if (routing_layer.isPreferH()) { + spacing_pair_list.emplace_back(routing_layer.get_eol_spacing(), routing_layer.get_eol_within()); + } else { + spacing_pair_list.emplace_back(routing_layer.get_eol_within(), routing_layer.get_eol_spacing()); + } + } int32_t half_wire_width = routing_layer.get_min_width() / 2; PlanarRect& enclosure = layer_enclosure_map[layer_idx]; int32_t enclosure_half_x_span = enclosure.getXSpan() / 2; @@ -1821,12 +1742,19 @@ std::map> PinAccessor::getRoutingNodeOrientationM GridMap& pa_node_map = pa_box.get_layer_node_map()[layer_idx]; std::map> node_orientation_map; // wire 与 net_shape - { - // 膨胀size为 min_spacing + half_wire_width - int32_t enlarged_size = min_spacing + half_wire_width; + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = half_wire_width; + int32_t enlarged_y_size = half_wire_width; + if (need_enlarged) { + // 膨胀size为 half_wire_width + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } // 贴合的也不算违例 - enlarged_size -= 1; - PlanarRect planar_enlarged_rect = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_size); + enlarged_x_size -= 1; + enlarged_y_size -= 1; + PlanarRect planar_enlarged_rect + = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(planar_enlarged_rect, pa_box.get_box_track_axis())) { PANode& node = pa_node_map[grid_coord.get_x()][grid_coord.get_y()]; for (const Orientation& orientation : orientation_set) { @@ -1842,10 +1770,14 @@ std::map> PinAccessor::getRoutingNodeOrientationM } } // enclosure 与 net_shape - { - // 膨胀size为 min_spacing + enclosure_half_span - int32_t enlarged_x_size = min_spacing + enclosure_half_x_span; - int32_t enlarged_y_size = min_spacing + enclosure_half_y_span; + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = enclosure_half_x_span; + int32_t enlarged_y_size = enclosure_half_y_span; + if (need_enlarged) { + // 膨胀size为 enclosure_half_span + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } // 贴合的也不算违例 enlarged_x_size -= 1; enlarged_y_size -= 1; @@ -1869,7 +1801,7 @@ std::map> PinAccessor::getRoutingNodeOrientationM return node_orientation_map; } -std::map> PinAccessor::getCutNodeOrientationMap(PABox& pa_box, NetShape& net_shape) +std::map> PinAccessor::getCutNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged) { std::vector& cut_layer_list = RTDM.getDatabase().get_cut_layer_list(); std::map>& cut_to_adjacent_routing_map = RTDM.getDatabase().get_cut_to_adjacent_routing_map(); @@ -1877,39 +1809,76 @@ std::map> PinAccessor::getCutNodeOrientationMap(P if (net_shape.get_is_routing()) { RTLOG.error(Loc::current(), "The type of net_shape is routing!"); } - std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[net_shape.get_layer_idx()]; - if (adjacent_routing_layer_idx_list.size() != 2) { - // 如果相邻层只有一个,将不会在那一层打via - return {}; + CutLayer& cut_layer = cut_layer_list[net_shape.get_layer_idx()]; + std::map>> cut_spacing_map; + { + int32_t curr_cut_layer_idx = net_shape.get_layer_idx(); + if (0 <= curr_cut_layer_idx && curr_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[curr_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_curr_x_spacing(), cut_layer.get_curr_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_curr_prl_spacing(), cut_layer.get_curr_y_spacing()); + cut_spacing_map[curr_cut_layer_idx] = spacing_pair_list; + } + } + int32_t below_cut_layer_idx = net_shape.get_layer_idx() - 1; + if (0 <= below_cut_layer_idx && below_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[below_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_below_x_spacing(), cut_layer.get_below_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_below_prl_spacing(), cut_layer.get_below_y_spacing()); + cut_spacing_map[below_cut_layer_idx] = spacing_pair_list; + } + } + int32_t above_cut_layer_idx = net_shape.get_layer_idx() + 1; + if (0 <= above_cut_layer_idx && above_cut_layer_idx < static_cast(cut_layer_list.size())) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[above_cut_layer_idx]; + if (adjacent_routing_layer_idx_list.size() == 2) { + std::vector> spacing_pair_list; + spacing_pair_list.emplace_back(cut_layer.get_above_x_spacing(), cut_layer.get_above_prl_spacing()); + spacing_pair_list.emplace_back(cut_layer.get_above_prl_spacing(), cut_layer.get_above_y_spacing()); + cut_spacing_map[above_cut_layer_idx] = spacing_pair_list; + } + } } - int32_t below_routing_layer_idx = adjacent_routing_layer_idx_list.front(); - int32_t above_routing_layer_idx = adjacent_routing_layer_idx_list.back(); - RTUTIL.swapByASC(below_routing_layer_idx, above_routing_layer_idx); - - std::vector>& layer_node_map = pa_box.get_layer_node_map(); std::map> node_orientation_map; - - // 膨胀size为 min_spacing + cut_shape_half_span - int32_t cut_spacing = cut_layer_list[net_shape.get_layer_idx()].getMinSpacing(); - PlanarRect& cut_shape = layer_via_master_list[below_routing_layer_idx].front().get_cut_shape_list().front(); - int32_t enlarged_x_size = cut_spacing + cut_shape.getXSpan() / 2; - int32_t enlarged_y_size = cut_spacing + cut_shape.getYSpan() / 2; - // 贴合的也不算违例 - enlarged_x_size -= 1; - enlarged_y_size -= 1; - PlanarRect space_enlarged_rect - = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); - for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(space_enlarged_rect, pa_box.get_box_track_axis())) { - if (!RTUTIL.exist(orientation_set, Orientation::kAbove) && !RTUTIL.exist(orientation_set, Orientation::kBelow)) { - continue; - } - PANode& below_node = layer_node_map[below_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; - if (RTUTIL.exist(below_node.get_neighbor_node_map(), Orientation::kAbove)) { - node_orientation_map[&below_node].insert(Orientation::kAbove); - } - PANode& above_node = layer_node_map[above_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; - if (RTUTIL.exist(above_node.get_neighbor_node_map(), Orientation::kBelow)) { - node_orientation_map[&above_node].insert(Orientation::kBelow); + for (auto& [cut_layer_idx, spacing_pair_list] : cut_spacing_map) { + std::vector adjacent_routing_layer_idx_list = cut_to_adjacent_routing_map[cut_layer_idx]; + int32_t below_routing_layer_idx = adjacent_routing_layer_idx_list.front(); + int32_t above_routing_layer_idx = adjacent_routing_layer_idx_list.back(); + RTUTIL.swapByASC(below_routing_layer_idx, above_routing_layer_idx); + PlanarRect& cut_shape = layer_via_master_list[below_routing_layer_idx].front().get_cut_shape_list().front(); + int32_t cut_shape_half_x_span = cut_shape.getXSpan() / 2; + int32_t cut_shape_half_y_span = cut_shape.getYSpan() / 2; + std::vector>& layer_node_map = pa_box.get_layer_node_map(); + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = cut_shape_half_x_span; + int32_t enlarged_y_size = cut_shape_half_y_span; + if (need_enlarged) { + // 膨胀size为 cut_shape_half_span + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } + // 贴合的也不算违例 + enlarged_x_size -= 1; + enlarged_y_size -= 1; + PlanarRect space_enlarged_rect + = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); + for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(space_enlarged_rect, pa_box.get_box_track_axis())) { + if (!RTUTIL.exist(orientation_set, Orientation::kAbove) && !RTUTIL.exist(orientation_set, Orientation::kBelow)) { + continue; + } + PANode& below_node = layer_node_map[below_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; + if (RTUTIL.exist(below_node.get_neighbor_node_map(), Orientation::kAbove)) { + node_orientation_map[&below_node].insert(Orientation::kAbove); + } + PANode& above_node = layer_node_map[above_routing_layer_idx][grid_coord.get_x()][grid_coord.get_y()]; + if (RTUTIL.exist(above_node.get_neighbor_node_map(), Orientation::kBelow)) { + node_orientation_map[&above_node].insert(Orientation::kBelow); + } + } } } return node_orientation_map; @@ -1923,15 +1892,21 @@ void PinAccessor::updateSummary(PAModel& pa_model) { Die& die = RTDM.getDatabase().get_die(); std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::map& routing_access_point_num_map = RTDM.getSummary().pa_summary.routing_access_point_num_map; - std::map& type_access_point_num_map = RTDM.getSummary().pa_summary.type_access_point_num_map; - int32_t& total_access_point_num = RTDM.getSummary().pa_summary.total_access_point_num; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_access_point_num_map = summary.pa_summary.routing_access_point_num_map; + std::map& type_access_point_num_map = summary.pa_summary.type_access_point_num_map; + int32_t& total_access_point_num = summary.pa_summary.total_access_point_num; + std::map& routing_violation_num_map = summary.pa_summary.routing_violation_num_map; + int32_t& total_violation_num = summary.pa_summary.total_violation_num; for (RoutingLayer& routing_layer : routing_layer_list) { routing_access_point_num_map[routing_layer.get_layer_idx()] = 0; + routing_violation_num_map[routing_layer.get_layer_idx()] = 0; } - type_access_point_num_map = {{AccessPointType::kNone, 0}, {AccessPointType::kTrackGrid, 0}, {AccessPointType::kOnShape, 0}}; + type_access_point_num_map = {{AccessPointType::kNone, 0}, {AccessPointType::kNoAccess, 0}, {AccessPointType::kTrackGrid, 0}}; total_access_point_num = 0; + total_violation_num = 0; for (auto& [net_idx, access_point_list] : RTDM.getNetAccessPointMap(die)) { for (AccessPoint* access_point : access_point_list) { @@ -1940,14 +1915,22 @@ void PinAccessor::updateSummary(PAModel& pa_model) total_access_point_num++; } } + for (Violation* violation : RTDM.getViolationSet(die)) { + routing_violation_num_map[violation->get_violation_shape().get_layer_idx()]++; + total_violation_num++; + } } void PinAccessor::printSummary(PAModel& pa_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::map& routing_access_point_num_map = RTDM.getSummary().pa_summary.routing_access_point_num_map; - std::map& type_access_point_num_map = RTDM.getSummary().pa_summary.type_access_point_num_map; - int32_t& total_access_point_num = RTDM.getSummary().pa_summary.total_access_point_num; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_access_point_num_map = summary.pa_summary.routing_access_point_num_map; + std::map& type_access_point_num_map = summary.pa_summary.type_access_point_num_map; + int32_t& total_access_point_num = summary.pa_summary.total_access_point_num; + std::map& routing_violation_num_map = summary.pa_summary.routing_violation_num_map; + int32_t& total_violation_num = summary.pa_summary.total_violation_num; fort::char_table routing_access_point_num_map_table; { @@ -1975,10 +1958,20 @@ void PinAccessor::printSummary(PAModel& pa_model) type_access_point_num_map_table << fort::header << "Total" << total_access_point_num << RTUTIL.getPercentage(total_access_point_num, total_access_point_num) << fort::endr; } - std::vector table_list; - table_list.push_back(routing_access_point_num_map_table); - table_list.push_back(type_access_point_num_map_table); - RTUTIL.printTableList(table_list); + fort::char_table routing_violation_num_map_table; + { + routing_violation_num_map_table << fort::header << "routing_layer" + << "violation_num" + << "proportion" << fort::endr; + for (RoutingLayer& routing_layer : routing_layer_list) { + routing_violation_num_map_table << routing_layer.get_layer_name() << routing_violation_num_map[routing_layer.get_layer_idx()] + << RTUTIL.getPercentage(routing_violation_num_map[routing_layer.get_layer_idx()], total_violation_num) + << fort::endr; + } + routing_violation_num_map_table << fort::header << "Total" << total_violation_num + << RTUTIL.getPercentage(total_violation_num, total_violation_num) << fort::endr; + } + RTUTIL.printTableList({routing_access_point_num_map_table, type_access_point_num_map_table, routing_violation_num_map_table}); } void PinAccessor::outputPlanarPinCSV(PAModel& pa_model) @@ -2175,28 +2168,10 @@ void PinAccessor::debugPlotPAModel(PAModel& pa_model, std::string flag) gp_gds.addStruct(access_point_struct); } - // best_coord - for (PANet& pa_net : pa_model.get_pa_net_list()) { - GPStruct best_coord_struct(RTUTIL.getString("best_coord(net_", pa_net.get_net_idx(), ")")); - for (PAPin& pa_pin : pa_net.get_pa_pin_list()) { - PlanarCoord& best_coord = pa_pin.get_best_coord(); - - int32_t x = best_coord.get_x(); - int32_t y = best_coord.get_y(); - - GPBoundary best_coord_boundary; - best_coord_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(pa_pin.get_routing_shape_list().front().get_layer_idx())); - best_coord_boundary.set_data_type(static_cast(GPDataType::kBestCoord)); - best_coord_boundary.set_rect(x - point_size, y - point_size, x + point_size, y + point_size); - best_coord_struct.push(best_coord_boundary); - } - gp_gds.addStruct(best_coord_struct); - } - // violation { - GPStruct violation_struct("violation"); for (Violation* violation : RTDM.getViolationSet(die)) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation->get_violation_type()))); EXTLayerRect& violation_shape = violation->get_violation_shape(); GPBoundary gp_boundary; @@ -2208,8 +2183,8 @@ void PinAccessor::debugPlotPAModel(PAModel& pa_model, std::string flag) gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(pa_temp_directory_path, flag, "_pa_model.gds"); @@ -2618,73 +2593,65 @@ void PinAccessor::debugPlotPABox(PABox& pa_box, int32_t curr_task_idx, std::stri gp_boundary.set_rect(pa_task->get_bounding_box()); task_struct.push(gp_boundary); } - for (auto& [net_idx, task_result_map] : pa_box.get_net_task_result_map()) { - for (auto& [task_idx, segment_list] : task_result_map) { - for (Segment& segment : segment_list) { - LayerCoord first_coord = segment.get_first(); - LayerCoord second_coord = segment.get_second(); - int32_t first_layer_idx = first_coord.get_layer_idx(); - int32_t second_layer_idx = second_coord.get_layer_idx(); - int32_t half_width = routing_layer_list[first_layer_idx].get_min_width() / 2; + for (Segment& segment : pa_box.get_net_task_result_map()[pa_task->get_net_idx()][pa_task->get_task_idx()]) { + LayerCoord first_coord = segment.get_first(); + LayerCoord second_coord = segment.get_second(); + int32_t first_layer_idx = first_coord.get_layer_idx(); + int32_t second_layer_idx = second_coord.get_layer_idx(); + int32_t half_width = routing_layer_list[first_layer_idx].get_min_width() / 2; - if (first_layer_idx == second_layer_idx) { - GPBoundary gp_boundary; - gp_boundary.set_data_type(static_cast(GPDataType::kPath)); - gp_boundary.set_rect(RTUTIL.getEnlargedRect(first_coord, second_coord, half_width)); - gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(first_layer_idx)); - task_struct.push(gp_boundary); - } else { - RTUTIL.swapByASC(first_layer_idx, second_layer_idx); - for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { - ViaMaster& via_master = layer_via_master_list[layer_idx].front(); + if (first_layer_idx == second_layer_idx) { + GPBoundary gp_boundary; + gp_boundary.set_data_type(static_cast(GPDataType::kPath)); + gp_boundary.set_rect(RTUTIL.getEnlargedRect(first_coord, second_coord, half_width)); + gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(first_layer_idx)); + task_struct.push(gp_boundary); + } else { + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + for (int32_t layer_idx = first_layer_idx; layer_idx < second_layer_idx; layer_idx++) { + ViaMaster& via_master = layer_via_master_list[layer_idx].front(); - LayerRect& above_enclosure = via_master.get_above_enclosure(); - LayerRect offset_above_enclosure(RTUTIL.getOffsetRect(above_enclosure, first_coord), above_enclosure.get_layer_idx()); - GPBoundary above_boundary; - above_boundary.set_rect(offset_above_enclosure); - above_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(above_enclosure.get_layer_idx())); - above_boundary.set_data_type(static_cast(GPDataType::kPath)); - task_struct.push(above_boundary); + LayerRect& above_enclosure = via_master.get_above_enclosure(); + LayerRect offset_above_enclosure(RTUTIL.getOffsetRect(above_enclosure, first_coord), above_enclosure.get_layer_idx()); + GPBoundary above_boundary; + above_boundary.set_rect(offset_above_enclosure); + above_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(above_enclosure.get_layer_idx())); + above_boundary.set_data_type(static_cast(GPDataType::kPath)); + task_struct.push(above_boundary); - LayerRect& below_enclosure = via_master.get_below_enclosure(); - LayerRect offset_below_enclosure(RTUTIL.getOffsetRect(below_enclosure, first_coord), below_enclosure.get_layer_idx()); - GPBoundary below_boundary; - below_boundary.set_rect(offset_below_enclosure); - below_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(below_enclosure.get_layer_idx())); - below_boundary.set_data_type(static_cast(GPDataType::kPath)); - task_struct.push(below_boundary); + LayerRect& below_enclosure = via_master.get_below_enclosure(); + LayerRect offset_below_enclosure(RTUTIL.getOffsetRect(below_enclosure, first_coord), below_enclosure.get_layer_idx()); + GPBoundary below_boundary; + below_boundary.set_rect(offset_below_enclosure); + below_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(below_enclosure.get_layer_idx())); + below_boundary.set_data_type(static_cast(GPDataType::kPath)); + task_struct.push(below_boundary); - for (PlanarRect& cut_shape : via_master.get_cut_shape_list()) { - LayerRect offset_cut_shape(RTUTIL.getOffsetRect(cut_shape, first_coord), via_master.get_cut_layer_idx()); - GPBoundary cut_boundary; - cut_boundary.set_rect(offset_cut_shape); - cut_boundary.set_layer_idx(RTGP.getGDSIdxByCut(via_master.get_cut_layer_idx())); - cut_boundary.set_data_type(static_cast(GPDataType::kPath)); - task_struct.push(cut_boundary); - } - } + for (PlanarRect& cut_shape : via_master.get_cut_shape_list()) { + LayerRect offset_cut_shape(RTUTIL.getOffsetRect(cut_shape, first_coord), via_master.get_cut_layer_idx()); + GPBoundary cut_boundary; + cut_boundary.set_rect(offset_cut_shape); + cut_boundary.set_layer_idx(RTGP.getGDSIdxByCut(via_master.get_cut_layer_idx())); + cut_boundary.set_data_type(static_cast(GPDataType::kPath)); + task_struct.push(cut_boundary); } } } } - for (auto& [net_idx, task_patch_map] : pa_box.get_net_task_patch_map()) { - for (auto& [task_idx, patch_list] : task_patch_map) { - for (EXTLayerRect& patch : patch_list) { - GPBoundary gp_boundary; - gp_boundary.set_rect(patch.get_real_rect()); - gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(patch.get_layer_idx())); - gp_boundary.set_data_type(static_cast(GPDataType::kPath)); - task_struct.push(gp_boundary); - } - } + for (EXTLayerRect& patch : pa_box.get_net_task_patch_map()[pa_task->get_net_idx()][pa_task->get_task_idx()]) { + GPBoundary gp_boundary; + gp_boundary.set_rect(patch.get_real_rect()); + gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(patch.get_layer_idx())); + gp_boundary.set_data_type(static_cast(GPDataType::kPath)); + task_struct.push(gp_boundary); } gp_gds.addStruct(task_struct); } // violation { - GPStruct violation_struct("violation"); for (Violation& violation : pa_box.get_violation_list()) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation.get_violation_type()))); EXTLayerRect& violation_shape = violation.get_violation_shape(); GPBoundary gp_boundary; @@ -2696,8 +2663,8 @@ void PinAccessor::debugPlotPABox(PABox& pa_box, int32_t curr_task_idx, std::stri gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(pa_temp_directory_path, flag, "_pa_box_", pa_box.get_pa_box_id().get_x(), "_", diff --git a/src/operation/iRT/source/module/pin_accessor/PinAccessor.hpp b/src/operation/iRT/source/module/pin_accessor/PinAccessor.hpp index a36cfec42..1e28b8856 100644 --- a/src/operation/iRT/source/module/pin_accessor/PinAccessor.hpp +++ b/src/operation/iRT/source/module/pin_accessor/PinAccessor.hpp @@ -53,20 +53,18 @@ class PinAccessor PinAccessor& operator=(PinAccessor&& other) = delete; // function PAModel initPAModel(); + void setPAParameter(PAModel& pa_model); + void initAccessPointList(PAModel& pa_model); std::vector convertToPANetList(std::vector& net_list); PANet convertToPANet(Net& net); - void initAccessPointList(PAModel& pa_model); std::vector getLegalShapeList(PAModel& pa_model, int32_t net_idx, Pin* pin); std::vector getPlanarLegalRectList(PAModel& pa_model, int32_t curr_net_idx, std::vector& pin_shape_list); - std::vector getAccessPointList(int32_t pin_idx, std::vector& legal_shape_list); + std::vector getAccessPointList(PAModel& pa_model, int32_t pin_idx, std::vector& legal_shape_list); + void uniformSampleCoordList(PAModel& pa_model, std::vector& layer_coord_list); void uploadAccessPointList(PAModel& pa_model); - void buildNonConflictPoint(PAModel& pa_model); - std::vector> getPinSegmentList(PAModel& pa_model); - std::vector> getPinGroupList(std::vector>& pin_segment_list); - std::map getPinBestCoordMap(std::vector& pin_group); - void setPAParameter(PAModel& pa_model); void initPABoxMap(PAModel& pa_model); void buildBoxSchedule(PAModel& pa_model); + void exemptPinShape(PABox& pa_box); void routePABoxMap(PAModel& pa_model); void buildFixedRect(PABox& pa_box); void buildAccessResult(PABox& pa_box); @@ -93,12 +91,6 @@ class PinAccessor void resetSinglePath(PABox& pa_box); void updateTaskResult(PABox& pa_box); std::vector> getRoutingSegmentList(PABox& pa_box); - void patchSingleTask(PABox& pa_box); - std::vector getMinimumAreaPatchList(PABox& pa_box); - std::vector getMinStepPatchList(PABox& pa_box); - std::vector getPatchViolationList(PABox& pa_box); - void updateTaskPatch(PABox& pa_box); - std::vector getRoutingPatchList(PABox& pa_box); void resetSingleTask(PABox& pa_box); void pushToOpenList(PABox& pa_box, PANode* curr_node); PANode* popFromOpenList(PABox& pa_box); @@ -112,12 +104,13 @@ class PinAccessor double getEstimateViaCost(PABox& pa_box, PANode* start_node, PANode* end_node); void updateViolationList(PABox& pa_box); std::vector getCostViolationList(PABox& pa_box); - std::vector getTaskScheduleByViolation(PABox& pa_box); + void updateTaskSchedule(PABox& pa_box, std::vector& routing_task_list); void uploadAccessResult(PABox& pa_box); void uploadViolation(PABox& pa_box); void freePABox(PABox& pa_box); int32_t getViolationNum(); - void updatePAModel(PAModel& pa_model); + void uploadAccessPoint(PAModel& pa_model); + void ignoreViolation(PAModel& pa_model); #if 1 // update env void updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect* fixed_rect, bool is_routing); @@ -125,10 +118,11 @@ class PinAccessor void updateFixedRectToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch); void updateNetResultToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, Segment& segment); void updateNetResultToGraph(PABox& pa_box, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch); - void updateViolationToGraph(PABox& pa_box, ChangeType change_type, Violation& violation); - std::map> getNodeOrientationMap(PABox& pa_box, NetShape& net_shape); - std::map> getRoutingNodeOrientationMap(PABox& pa_box, NetShape& net_shape); - std::map> getCutNodeOrientationMap(PABox& pa_box, NetShape& net_shape); + void addViolationToGraph(PABox& pa_box, Violation& violation); + void addViolationToGraph(PABox& pa_box, LayerRect& searched_rect, std::vector>& overlap_segment_list); + std::map> getNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged); + std::map> getRoutingNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged); + std::map> getCutNodeOrientationMap(PABox& pa_box, NetShape& net_shape, bool need_enlarged); #endif #if 1 // exhibit diff --git a/src/operation/iRT/source/module/pin_accessor/framwork.txt b/src/operation/iRT/source/module/pin_accessor/framwork.txt index d4906b03b..84992d722 100644 --- a/src/operation/iRT/source/module/pin_accessor/framwork.txt +++ b/src/operation/iRT/source/module/pin_accessor/framwork.txt @@ -1,22 +1,25 @@ initPAModel:初始化model +setPAParameter:设置pa_model的参数 initAccessPointList:用boost得到pinshape上的合法区域并生成ap uploadAccessPointList:将中间结果暂时存储至顶层 -setPAParameter:设置pa_model的参数 -initPABoxMap:构建PABox框架,里面主要数据为空 +initPABoxMap:构建PABox框架,里面主要数据为空 buildBoxSchedule:构建时间表 routePABoxMap: - buildFixedRect:将GCellmap中的fix_rect(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 + buildFixedRect:将GCellmap中的fix_rect(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 + buildAccessResult:将GCellmap中的access结果(与此Box覆盖)以指针的方式拷贝到Box内,不需要对GCellmap删除或添加 + buildViolation:将GCellMap中的violation以实体的方式拷贝到Box内,对于完全在Box内的,在GCellMap中删除 initPATaskList:构建task任务 buildBoxTrackAxis:构建Box内的track_axis - buildLayerNodeMap:构建Box的Graph,只有节点,其他信息后续构建 + buildLayerNodeMap:构建Box的Graph,只有节点,其他信息后续构建 buildPANodeNeighbor:将所有节点连接 - buildOrientNetMap:构建Graph的cost,fix_rect从Box中得到,在pa阶段net_access_result为布线结果 + buildOrientNetMap:构建Graph的cost,fix_rect从Box中得到,在pa阶段net_access_result为布线结果 routePABox: initTaskSchedule:初始化task布线调度表 - routePATask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 - updateViolationList:首先得到Violation存到Box下面,然后Violation结果从graph中删除,再加入新的结果 + routePATask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 + updateViolationList:首先得到Violation存到Box下面,然后Violation结果从graph中删除,再加入新的结果 getTaskScheduleByViolation:通过Violation得到新的布线调度 - uploadAccessResult:构建access数据,并加入gcell_map - uploadViolation:将violation加入gcell_map + uploadAccessResult:构建access数据,并加入GCellMap + uploadViolation:将violation加入GCellMap freePABox:析构task_list和node_map -updatePAModel:更新顶层gcell_map +uploadAccessPoint:将access数据更新到顶层GCellMap +ignoreViolation:将整个版图结果进行检查并将violation加入ignore \ No newline at end of file diff --git a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PABox.hpp b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PABox.hpp index f3519479d..31e1e0059 100644 --- a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PABox.hpp +++ b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PABox.hpp @@ -87,7 +87,6 @@ class PABox std::vector& get_path_node_list() { return _path_node_list; } std::vector& get_single_task_visited_node_list() { return _single_task_visited_node_list; } std::vector>& get_routing_segment_list() { return _routing_segment_list; } - std::vector& get_routing_patch_list() { return _routing_patch_list; } void set_curr_pa_task(PATask* curr_pa_task) { _curr_pa_task = curr_pa_task; } void set_start_node_list_list(const std::vector>& start_node_list_list) { @@ -103,7 +102,6 @@ class PABox { _routing_segment_list = routing_segment_list; } - void set_routing_patch_list(const std::vector& routing_patch_list) { _routing_patch_list = routing_patch_list; } // single path PriorityQueue, CmpPANodeCost>& get_open_queue() { return _open_queue; } std::vector& get_single_path_visited_node_list() { return _single_path_visited_node_list; } @@ -139,7 +137,6 @@ class PABox std::vector _path_node_list; std::vector _single_task_visited_node_list; std::vector> _routing_segment_list; - std::vector _routing_patch_list; // single path PriorityQueue, CmpPANodeCost> _open_queue; std::vector _single_path_visited_node_list; diff --git a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAParameter.hpp b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAParameter.hpp index 2425f0753..c27bc11f5 100644 --- a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAParameter.hpp +++ b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAParameter.hpp @@ -23,7 +23,7 @@ class PAParameter public: PAParameter() = default; PAParameter(double prefer_wire_unit, double non_prefer_wire_unit, double via_unit, int32_t size, int32_t offset, double fixed_rect_unit, - double routed_rect_unit, double violation_unit, int32_t max_routed_times) + double routed_rect_unit, double violation_unit, int32_t max_routed_times, int32_t max_candidate_point_num) { _prefer_wire_unit = prefer_wire_unit; _non_prefer_wire_unit = non_prefer_wire_unit; @@ -34,6 +34,7 @@ class PAParameter _routed_rect_unit = routed_rect_unit; _violation_unit = violation_unit; _max_routed_times = max_routed_times; + _max_candidate_point_num = max_candidate_point_num; } ~PAParameter() = default; // getter @@ -46,6 +47,7 @@ class PAParameter double get_routed_rect_unit() const { return _routed_rect_unit; } double get_violation_unit() const { return _violation_unit; } int32_t get_max_routed_times() const { return _max_routed_times; } + int32_t get_max_candidate_point_num() const { return _max_candidate_point_num; } // setter void set_prefer_wire_unit(const double prefer_wire_unit) { _prefer_wire_unit = prefer_wire_unit; } void set_non_prefer_wire_unit(const double non_prefer_wire_unit) { _non_prefer_wire_unit = non_prefer_wire_unit; } @@ -56,6 +58,7 @@ class PAParameter void set_routed_rect_unit(const double routed_rect_unit) { _routed_rect_unit = routed_rect_unit; } void set_violation_unit(const double violation_unit) { _violation_unit = violation_unit; } void set_max_routed_times(const int32_t max_routed_times) { _max_routed_times = max_routed_times; } + void set_max_candidate_point_num(const int32_t max_candidate_point_num) { _max_candidate_point_num = max_candidate_point_num; } private: double _prefer_wire_unit = 0; @@ -67,6 +70,7 @@ class PAParameter double _routed_rect_unit = 0; double _violation_unit = 0; int32_t _max_routed_times = 0; + int32_t _max_candidate_point_num = 0; }; } // namespace irt diff --git a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAPin.hpp b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAPin.hpp index a92ed986f..0211316ff 100644 --- a/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAPin.hpp +++ b/src/operation/iRT/source/module/pin_accessor/pa_data_manager/PAPin.hpp @@ -29,16 +29,13 @@ class PAPin : public Pin // getter std::vector& get_access_point_list() { return _access_point_list; } bool get_is_accessed() const { return _is_accessed; } - PlanarCoord& get_best_coord() { return _best_coord; } // setter void set_access_point_list(const std::vector& access_point_list) { _access_point_list = access_point_list; } void set_is_accessed(const bool is_accessed) { _is_accessed = is_accessed; } - void set_best_coord(const PlanarCoord& best_coord) { _best_coord = best_coord; } // function private: std::vector _access_point_list; bool _is_accessed = false; - PlanarCoord _best_coord; }; } // namespace irt diff --git a/src/operation/iRT/source/module/supply_analyzer/SupplyAnalyzer.cpp b/src/operation/iRT/source/module/supply_analyzer/SupplyAnalyzer.cpp index 5a3335f58..59ab3b574 100644 --- a/src/operation/iRT/source/module/supply_analyzer/SupplyAnalyzer.cpp +++ b/src/operation/iRT/source/module/supply_analyzer/SupplyAnalyzer.cpp @@ -57,13 +57,12 @@ void SupplyAnalyzer::analyze() SAModel sa_model = initSAModel(); buildSupplySchedule(sa_model); analyzeSupply(sa_model); + // debugPlotSAModel(sa_model); updateSummary(sa_model); printSummary(sa_model); outputPlanarSupplyCSV(sa_model); outputLayerSupplyCSV(sa_model); RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); - - // debugPlotSAModel(sa_model); } // private @@ -172,6 +171,14 @@ void SupplyAnalyzer::analyzeSupply(SAModel& sa_model) } } } + for (auto& [net_idx, patch_set] : RTDM.getNetAccessPatchMap(search_rect)) { + for (EXTLayerRect* patch : patch_set) { + if (search_rect.get_layer_idx() != patch->get_layer_idx()) { + continue; + } + obs_rect_list.push_back(patch->get_real_rect()); + } + } } for (LayerRect& wire : getCrossingWireList(search_rect)) { if (isAccess(wire, obs_rect_list)) { @@ -234,7 +241,7 @@ bool SupplyAnalyzer::isAccess(LayerRect& wire, std::vector& obs_rect RoutingLayer& routing_layer = routing_layer_list[wire.get_layer_idx()]; for (PlanarRect& obs_rect : obs_rect_list) { - int32_t enlarged_size = routing_layer.getMinSpacing(obs_rect); + int32_t enlarged_size = routing_layer.getPRLSpacing(obs_rect); PlanarRect enlarged_rect = RTUTIL.getEnlargedRect(obs_rect, enlarged_size); if (RTUTIL.isOpenOverlap(enlarged_rect, wire)) { // 阻塞 @@ -250,8 +257,10 @@ void SupplyAnalyzer::updateSummary(SAModel& sa_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); - std::map& routing_supply_map = RTDM.getSummary().sa_summary.routing_supply_map; - int32_t& total_supply = RTDM.getSummary().sa_summary.total_supply; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_supply_map = summary.sa_summary.routing_supply_map; + int32_t& total_supply = summary.sa_summary.total_supply; for (RoutingLayer& routing_layer : routing_layer_list) { routing_supply_map[routing_layer.get_layer_idx()] = 0; @@ -273,8 +282,10 @@ void SupplyAnalyzer::updateSummary(SAModel& sa_model) void SupplyAnalyzer::printSummary(SAModel& sa_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::map& routing_supply_map = RTDM.getSummary().sa_summary.routing_supply_map; - int32_t& total_supply = RTDM.getSummary().sa_summary.total_supply; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_supply_map = summary.sa_summary.routing_supply_map; + int32_t& total_supply = summary.sa_summary.total_supply; fort::char_table routing_supply_map_table; { @@ -287,9 +298,7 @@ void SupplyAnalyzer::printSummary(SAModel& sa_model) } routing_supply_map_table << fort::header << "Total" << total_supply << RTUTIL.getPercentage(total_supply, total_supply) << fort::endr; } - std::vector table_list; - table_list.push_back(routing_supply_map_table); - RTUTIL.printTableList(table_list); + RTUTIL.printTableList({routing_supply_map_table}); } void SupplyAnalyzer::outputPlanarSupplyCSV(SAModel& sa_model) diff --git a/src/operation/iRT/source/module/supply_analyzer/framwork.txt b/src/operation/iRT/source/module/supply_analyzer/framwork.txt index 76fa621df..2fff02c55 100644 --- a/src/operation/iRT/source/module/supply_analyzer/framwork.txt +++ b/src/operation/iRT/source/module/supply_analyzer/framwork.txt @@ -1,5 +1,5 @@ initSAModel:初始化model buildSupplySchedule:构建将要计算的Schedule -analyzeSupply:分析GCell之间的形状等特征,确定supply +analyzeSupply:分析GCell之间的形状等特征,确定supply diff --git a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp index c88592b4f..c9394cc90 100644 --- a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp +++ b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp @@ -61,9 +61,9 @@ void TopologyGenerator::generate() buildOrientSupply(tg_model); // debugCheckTGModel(tg_model); generateTGModel(tg_model); - // outputGuide(tg_model); updateSummary(tg_model); printSummary(tg_model); + outputGuide(tg_model); outputPlanarSupplyCSV(tg_model); outputPlanarDemandCSV(tg_model); outputPlanarOverflowCSV(tg_model); @@ -108,10 +108,14 @@ TGNet TopologyGenerator::convertToTGNet(Net& net) void TopologyGenerator::setTGParameter(TGModel& tg_model) { + int32_t topo_spilt_length = 10; + double congestion_unit = 2; /** * topo_spilt_length, congestion_unit */ - TGParameter tg_parameter(10, 2); + // clang-format off + TGParameter tg_parameter(topo_spilt_length, congestion_unit); + // clang-format on RTLOG.info(Loc::current(), "topo_spilt_length: ", tg_parameter.get_topo_spilt_length()); RTLOG.info(Loc::current(), "congestion_unit: ", tg_parameter.get_congestion_unit()); tg_model.set_tg_parameter(tg_parameter); @@ -477,12 +481,14 @@ void TopologyGenerator::updateSummary(TGModel& tg_model) ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); Die& die = RTDM.getDatabase().get_die(); GridMap& gcell_map = RTDM.getDatabase().get_gcell_map(); + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - int32_t& total_demand = RTDM.getSummary().tg_summary.total_demand; - int32_t& total_overflow = RTDM.getSummary().tg_summary.total_overflow; - double& total_wire_length = RTDM.getSummary().tg_summary.total_wire_length; - std::map>& clock_timing = RTDM.getSummary().tg_summary.clock_timing; - std::map& power_map = RTDM.getSummary().tg_summary.power_map; + + int32_t& total_demand = summary.tg_summary.total_demand; + int32_t& total_overflow = summary.tg_summary.total_overflow; + double& total_wire_length = summary.tg_summary.total_wire_length; + std::map>& clock_timing = summary.tg_summary.clock_timing; + std::map& power_map = summary.tg_summary.power_map; std::vector& tg_net_list = tg_model.get_tg_net_list(); GridMap& tg_node_map = tg_model.get_tg_node_map(); @@ -554,12 +560,14 @@ void TopologyGenerator::updateSummary(TGModel& tg_model) void TopologyGenerator::printSummary(TGModel& tg_model) { + Summary& summary = RTDM.getDatabase().get_summary(); int32_t enable_timing = RTDM.getConfig().enable_timing; - int32_t& total_demand = RTDM.getSummary().tg_summary.total_demand; - int32_t& total_overflow = RTDM.getSummary().tg_summary.total_overflow; - double& total_wire_length = RTDM.getSummary().tg_summary.total_wire_length; - std::map>& clock_timing = RTDM.getSummary().tg_summary.clock_timing; - std::map& power_map = RTDM.getSummary().tg_summary.power_map; + + int32_t& total_demand = summary.tg_summary.total_demand; + int32_t& total_overflow = summary.tg_summary.total_overflow; + double& total_wire_length = summary.tg_summary.total_wire_length; + std::map>& clock_timing = summary.tg_summary.clock_timing; + std::map& power_map = summary.tg_summary.power_map; fort::char_table summary_table; { @@ -567,23 +575,99 @@ void TopologyGenerator::printSummary(TGModel& tg_model) summary_table << fort::header << "total_overflow" << total_overflow << fort::endr; summary_table << fort::header << "total_wire_length" << total_wire_length << fort::endr; } - fort::char_table timing_and_power_table; + fort::char_table timing_table; + fort::char_table power_table; if (enable_timing) { - timing_and_power_table << fort::header << "Clock" - << "TNS" - << "WNS" - << "Freq(MHz)" << fort::endr; + timing_table << fort::header << "clock_name" + << "tns" + << "wns" + << "freq" << fort::endr; for (auto& [clock_name, timing_map] : clock_timing) { - timing_and_power_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; + timing_table << clock_name << timing_map["TNS"] << timing_map["WNS"] << timing_map["Freq(MHz)"] << fort::endr; } + power_table << fort::header << "power_type" << "power_value" << fort::endr; for (auto& [type, power] : power_map) { - timing_and_power_table << fort::header << type << power << fort::endr; + power_table << type << power << fort::endr; } } - std::vector table_list; - table_list.push_back(summary_table); - table_list.push_back(timing_and_power_table); - RTUTIL.printTableList(table_list); + RTUTIL.printTableList({summary_table}); + RTUTIL.printTableList({timing_table, power_table}); +} + +void TopologyGenerator::outputGuide(TGModel& tg_model) +{ + int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + Die& die = RTDM.getDatabase().get_die(); + std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); + std::string& tg_temp_directory_path = RTDM.getConfig().tg_temp_directory_path; + int32_t output_inter_result = RTDM.getConfig().output_inter_result; + if (!output_inter_result) { + return; + } + std::vector& tg_net_list = tg_model.get_tg_net_list(); + + std::ofstream* guide_file_stream = RTUTIL.getOutputFileStream(tg_temp_directory_path + "route.guide"); + if (guide_file_stream == nullptr) { + return; + } + RTUTIL.pushStream(guide_file_stream, "guide net_name\n"); + RTUTIL.pushStream(guide_file_stream, "pin grid_x grid_y real_x real_y layer energy name\n"); + RTUTIL.pushStream(guide_file_stream, "wire grid1_x grid1_y grid2_x grid2_y real1_x real1_y real2_x real2_y layer\n"); + RTUTIL.pushStream(guide_file_stream, "via grid_x grid_y real_x real_y layer1 layer2\n"); + + for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { + TGNet& tg_net = tg_net_list[net_idx]; + RTUTIL.pushStream(guide_file_stream, "guide ", tg_net.get_origin_net()->get_net_name(), "\n"); + + for (TGPin& tg_pin : tg_net.get_tg_pin_list()) { + AccessPoint& access_point = tg_pin.get_access_point(); + double grid_x = access_point.get_grid_x(); + double grid_y = access_point.get_grid_y(); + double real_x = access_point.get_real_x() / 1.0 / micron_dbu; + double real_y = access_point.get_real_y() / 1.0 / micron_dbu; + std::string layer = routing_layer_list[access_point.get_layer_idx()].get_layer_name(); + std::string connnect; + if (tg_pin.get_is_driven()) { + connnect = "driven"; + } else { + connnect = "load"; + } + RTUTIL.pushStream(guide_file_stream, "pin ", grid_x, " ", grid_y, " ", real_x, " ", real_y, " ", layer, " ", connnect, " ", + tg_pin.get_pin_name(), "\n"); + } + for (Segment* segment : segment_set) { + LayerCoord first_layer_coord = segment->get_first(); + double grid1_x = first_layer_coord.get_x(); + double grid1_y = first_layer_coord.get_y(); + int32_t first_layer_idx = first_layer_coord.get_layer_idx(); + + PlanarCoord first_mid_coord = RTUTIL.getRealRectByGCell(first_layer_coord, gcell_axis).getMidPoint(); + double real1_x = first_mid_coord.get_x() / 1.0 / micron_dbu; + double real1_y = first_mid_coord.get_y() / 1.0 / micron_dbu; + + LayerCoord second_layer_coord = segment->get_second(); + double grid2_x = second_layer_coord.get_x(); + double grid2_y = second_layer_coord.get_y(); + int32_t second_layer_idx = second_layer_coord.get_layer_idx(); + + PlanarCoord second_mid_coord = RTUTIL.getRealRectByGCell(second_layer_coord, gcell_axis).getMidPoint(); + double real2_x = second_mid_coord.get_x() / 1.0 / micron_dbu; + double real2_y = second_mid_coord.get_y() / 1.0 / micron_dbu; + + if (first_layer_idx != second_layer_idx) { + RTUTIL.swapByASC(first_layer_idx, second_layer_idx); + std::string layer1 = routing_layer_list[first_layer_idx].get_layer_name(); + std::string layer2 = routing_layer_list[second_layer_idx].get_layer_name(); + RTUTIL.pushStream(guide_file_stream, "via ", grid1_x, " ", grid1_y, " ", real1_x, " ", real1_y, " ", layer1, " ", layer2, "\n"); + } else { + std::string layer = routing_layer_list[first_layer_idx].get_layer_name(); + RTUTIL.pushStream(guide_file_stream, "wire ", grid1_x, " ", grid1_y, " ", grid2_x, " ", grid2_y, " ", real1_x, " ", real1_y, " ", + real2_x, " ", real2_y, " ", layer, "\n"); + } + } + } + RTUTIL.closeFileStream(guide_file_stream); } void TopologyGenerator::outputPlanarSupplyCSV(TGModel& tg_model) @@ -682,84 +766,6 @@ void TopologyGenerator::debugCheckTGModel(TGModel& tg_model) } } -void TopologyGenerator::outputGuide(TGModel& tg_model) -{ - Monitor monitor; - RTLOG.info(Loc::current(), "Starting..."); - - int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); - ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); - Die& die = RTDM.getDatabase().get_die(); - std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::string& tg_temp_directory_path = RTDM.getConfig().tg_temp_directory_path; - - std::vector& tg_net_list = tg_model.get_tg_net_list(); - - std::ofstream* guide_file_stream = RTUTIL.getOutputFileStream(tg_temp_directory_path + "route.guide"); - if (guide_file_stream == nullptr) { - return; - } - RTUTIL.pushStream(guide_file_stream, "guide net_name\n"); - RTUTIL.pushStream(guide_file_stream, "pin grid_x grid_y real_x real_y layer energy name\n"); - RTUTIL.pushStream(guide_file_stream, "wire grid1_x grid1_y grid2_x grid2_y real1_x real1_y real2_x real2_y layer\n"); - RTUTIL.pushStream(guide_file_stream, "via grid_x grid_y real_x real_y layer1 layer2\n"); - - for (auto& [net_idx, segment_set] : RTDM.getNetGlobalResultMap(die)) { - TGNet& tg_net = tg_net_list[net_idx]; - RTUTIL.pushStream(guide_file_stream, "guide ", tg_net.get_origin_net()->get_net_name(), "\n"); - - for (TGPin& tg_pin : tg_net.get_tg_pin_list()) { - AccessPoint& access_point = tg_pin.get_access_point(); - double grid_x = access_point.get_grid_x(); - double grid_y = access_point.get_grid_y(); - double real_x = access_point.get_real_x() / 1.0 / micron_dbu; - double real_y = access_point.get_real_y() / 1.0 / micron_dbu; - std::string layer = routing_layer_list[access_point.get_layer_idx()].get_layer_name(); - std::string connnect; - if (tg_pin.get_is_driven()) { - connnect = "driven"; - } else { - connnect = "load"; - } - RTUTIL.pushStream(guide_file_stream, "pin ", grid_x, " ", grid_y, " ", real_x, " ", real_y, " ", layer, " ", connnect, " ", - tg_pin.get_pin_name(), "\n"); - } - for (Segment* segment : segment_set) { - LayerCoord first_layer_coord = segment->get_first(); - double grid1_x = first_layer_coord.get_x(); - double grid1_y = first_layer_coord.get_y(); - int32_t first_layer_idx = first_layer_coord.get_layer_idx(); - - PlanarCoord first_mid_coord = RTUTIL.getRealRectByGCell(first_layer_coord, gcell_axis).getMidPoint(); - double real1_x = first_mid_coord.get_x() / 1.0 / micron_dbu; - double real1_y = first_mid_coord.get_y() / 1.0 / micron_dbu; - - LayerCoord second_layer_coord = segment->get_second(); - double grid2_x = second_layer_coord.get_x(); - double grid2_y = second_layer_coord.get_y(); - int32_t second_layer_idx = second_layer_coord.get_layer_idx(); - - PlanarCoord second_mid_coord = RTUTIL.getRealRectByGCell(second_layer_coord, gcell_axis).getMidPoint(); - double real2_x = second_mid_coord.get_x() / 1.0 / micron_dbu; - double real2_y = second_mid_coord.get_y() / 1.0 / micron_dbu; - - if (first_layer_idx != second_layer_idx) { - RTUTIL.swapByASC(first_layer_idx, second_layer_idx); - std::string layer1 = routing_layer_list[first_layer_idx].get_layer_name(); - std::string layer2 = routing_layer_list[second_layer_idx].get_layer_name(); - RTUTIL.pushStream(guide_file_stream, "via ", grid1_x, " ", grid1_y, " ", real1_x, " ", real1_y, " ", layer1, " ", layer2, "\n"); - } else { - std::string layer = routing_layer_list[first_layer_idx].get_layer_name(); - RTUTIL.pushStream(guide_file_stream, "wire ", grid1_x, " ", grid1_y, " ", grid2_x, " ", grid2_y, " ", real1_x, " ", real1_y, " ", - real2_x, " ", real2_y, " ", layer, "\n"); - } - } - } - RTUTIL.closeFileStream(guide_file_stream); - - RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo()); -} - #endif } // namespace irt diff --git a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp index 35f1f2d2f..80243d563 100644 --- a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp +++ b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp @@ -68,6 +68,7 @@ class TopologyGenerator #if 1 // exhibit void updateSummary(TGModel& tg_model); void printSummary(TGModel& tg_model); + void outputGuide(TGModel& tg_model); void outputPlanarSupplyCSV(TGModel& tg_model); void outputPlanarDemandCSV(TGModel& tg_model); void outputPlanarOverflowCSV(TGModel& tg_model); @@ -75,7 +76,6 @@ class TopologyGenerator #if 1 // debug void debugCheckTGModel(TGModel& tg_model); - void outputGuide(TGModel& tg_model); #endif }; diff --git a/src/operation/iRT/source/module/topology_generator/framwork.txt b/src/operation/iRT/source/module/topology_generator/framwork.txt index d041bcf5a..dce2f0077 100644 --- a/src/operation/iRT/source/module/topology_generator/framwork.txt +++ b/src/operation/iRT/source/module/topology_generator/framwork.txt @@ -1,7 +1,7 @@ +initTGModel:初始化model setTGParameter:设置tg_model的参数 initTGTaskList:构建TGTask,数据结构是TGNet -buildTGNodeMap:构建Graph,只有节点,其他信息后续构建 +buildTGNodeMap:构建Graph,只有节点,其他信息后续构建 buildTGNodeNeighbor:将所有节点连接 buildOrientSupply:构建Graph的supply -generateTGModel:生成线网的拓扑 -uploadNetResult:将布线结果加入gcell_map \ No newline at end of file +generateTGModel:生成线网的拓扑 \ No newline at end of file diff --git a/src/operation/iRT/source/module/track_assigner/TrackAssigner.cpp b/src/operation/iRT/source/module/track_assigner/TrackAssigner.cpp index 1219f3806..4548f17e1 100644 --- a/src/operation/iRT/source/module/track_assigner/TrackAssigner.cpp +++ b/src/operation/iRT/source/module/track_assigner/TrackAssigner.cpp @@ -107,11 +107,19 @@ TANet TrackAssigner::convertToTANet(Net& net) void TrackAssigner::setTAParameter(TAModel& ta_model) { - int32_t cost_unit = 8; + int32_t cost_unit = RTDM.getOnlyPitch(); + double prefer_wire_unit = 1; + double non_prefer_wire_unit = 2.5; + double via_unit = cost_unit; + double fixed_rect_unit = 4 * non_prefer_wire_unit * cost_unit; + double routed_rect_unit = 2 * via_unit; + double violation_unit = 4 * non_prefer_wire_unit * cost_unit; /** * prefer_wire_unit, fixed_rect_unit, routed_rect_unit, violation_unit, max_routed_times */ - TAParameter ta_parameter(1, 128 * cost_unit, 32 * cost_unit, 32 * cost_unit, 4); + // clang-format off + TAParameter ta_parameter(prefer_wire_unit, fixed_rect_unit, routed_rect_unit, violation_unit, 10); + // clang-format on RTLOG.info(Loc::current(), "prefer_wire_unit: ", ta_parameter.get_prefer_wire_unit()); RTLOG.info(Loc::current(), "fixed_rect_unit: ", ta_parameter.get_fixed_rect_unit()); RTLOG.info(Loc::current(), "routed_rect_unit: ", ta_parameter.get_routed_rect_unit()); @@ -175,7 +183,7 @@ void TrackAssigner::buildPanelSchedule(TAModel& ta_model) { std::vector>& layer_panel_list = ta_model.get_layer_panel_list(); - int32_t range = 2; + int32_t range = 3; std::vector> ta_panel_id_list_list; for (int32_t layer_idx = 0; layer_idx < static_cast(layer_panel_list.size()); layer_idx++) { @@ -218,13 +226,14 @@ void TrackAssigner::assignTAPanelMap(TAModel& ta_model) buildTANodeMap(ta_panel); buildTANodeNeighbor(ta_panel); buildOrientNetMap(ta_panel); + exemptPinShape(ta_panel); // debugCheckTAPanel(ta_panel); // debugPlotTAPanel(ta_panel, -1, "before"); routeTAPanel(ta_panel); // debugPlotTAPanel(ta_panel, -1, "after"); uploadNetResult(ta_panel); - uploadViolation(ta_panel); } + uploadViolation(ta_panel); freeTAPanel(ta_panel); } assigned_panel_num += ta_panel_id_list.size(); @@ -238,23 +247,61 @@ void TrackAssigner::assignTAPanelMap(TAModel& ta_model) void TrackAssigner::buildFixedRect(TAPanel& ta_panel) { - ta_panel.set_type_layer_net_fixed_rect_map(RTDM.getTypeLayerNetFixedRectMap(ta_panel.get_panel_rect())); + // fixed_rect + for (auto& [is_routing, layer_net_fixed_rect_map] : RTDM.getTypeLayerNetFixedRectMap(ta_panel.get_panel_rect())) { + for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { + if (is_routing != true || layer_idx != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } + ta_panel.set_net_fixed_rect_map(net_fixed_rect_map); + break; + } + } } void TrackAssigner::buildAccessResult(TAPanel& ta_panel) { - ta_panel.set_net_access_result_map(RTDM.getNetAccessResultMap(ta_panel.get_panel_rect())); - ta_panel.set_net_access_patch_map(RTDM.getNetAccessPatchMap(ta_panel.get_panel_rect())); + for (auto& [net_idx, segment_set] : RTDM.getNetAccessResultMap(ta_panel.get_panel_rect())) { + for (Segment* segment : segment_set) { + for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { + if (net_shape.get_is_routing() != true || net_shape.get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } + ta_panel.get_net_access_result_map()[net_idx].push_back(net_shape); + } + } + } + for (auto& [net_idx, patch_set] : RTDM.getNetAccessPatchMap(ta_panel.get_panel_rect())) { + for (EXTLayerRect* patch : patch_set) { + if (patch->get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } + ta_panel.get_net_access_patch_map()[net_idx].insert(patch); + } + } } void TrackAssigner::buildNetResult(TAPanel& ta_panel) { - ta_panel.set_net_detailed_result_map(RTDM.getNetDetailedResultMap(ta_panel.get_panel_rect())); + for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(ta_panel.get_panel_rect())) { + for (Segment* segment : segment_set) { + for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { + if (net_shape.get_is_routing() != true || net_shape.get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } + ta_panel.get_net_detailed_result_map()[net_idx].push_back(net_shape); + } + } + } } void TrackAssigner::buildViolation(TAPanel& ta_panel) { for (Violation* violation : RTDM.getViolationSet(ta_panel.get_panel_rect())) { + if (violation->get_is_routing() != true + || violation->get_violation_shape().get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } if (!RTUTIL.isInside(ta_panel.get_panel_rect().get_real_rect(), violation->get_violation_shape().get_real_rect())) { continue; } @@ -433,22 +480,15 @@ void TrackAssigner::buildTANodeNeighbor(TAPanel& ta_panel) void TrackAssigner::buildOrientNetMap(TAPanel& ta_panel) { - for (auto& [is_routing, layer_net_fixed_rect_map] : ta_panel.get_type_layer_net_fixed_rect_map()) { - for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { - if (is_routing != true || layer_idx != ta_panel.get_panel_rect().get_layer_idx()) { - continue; - } - for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { - for (auto& fixed_rect : fixed_rect_set) { - updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, fixed_rect, true); - } - } - break; + for (auto& [net_idx, fixed_rect_set] : ta_panel.get_net_fixed_rect_map()) { + for (EXTLayerRect* fixed_rect : fixed_rect_set) { + updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, fixed_rect, true); } } - for (auto& [net_idx, segment_set] : ta_panel.get_net_access_result_map()) { - for (Segment* segment : segment_set) { - updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, *segment); + + for (auto& [net_idx, rect_list] : ta_panel.get_net_access_result_map()) { + for (LayerRect& rect : rect_list) { + updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, rect, true); } } for (auto& [net_idx, patch_set] : ta_panel.get_net_access_patch_map()) { @@ -456,13 +496,28 @@ void TrackAssigner::buildOrientNetMap(TAPanel& ta_panel) updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, *patch); } } - for (auto& [net_idx, segment_set] : ta_panel.get_net_detailed_result_map()) { - for (Segment* segment : segment_set) { - updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, *segment); + for (auto& [net_idx, rect_list] : ta_panel.get_net_detailed_result_map()) { + for (LayerRect& rect : rect_list) { + updateFixedRectToGraph(ta_panel, ChangeType::kAdd, net_idx, rect, true); } } for (Violation& violation : ta_panel.get_violation_list()) { - updateViolationToGraph(ta_panel, ChangeType::kAdd, violation); + addViolationToGraph(ta_panel, violation); + } +} + +void TrackAssigner::exemptPinShape(TAPanel& ta_panel) +{ + GridMap& ta_node_map = ta_panel.get_ta_node_map(); + for (int32_t x = 0; x < ta_node_map.get_x_size(); x++) { + for (int32_t y = 0; y < ta_node_map.get_y_size(); y++) { + TANode& ta_node = ta_node_map[x][y]; + for (auto& [orient, net_set] : ta_node.get_orient_fixed_rect_map()) { + if (RTUTIL.exist(net_set, -1) && net_set.size() >= 2) { + net_set.erase(-1); + } + } + } } } @@ -473,20 +528,20 @@ void TrackAssigner::routeTAPanel(TAPanel& ta_panel) if (!enable_lsa) { routeTAPanelBySelf(ta_panel); } else { - routeTAPanelByOther(ta_panel); + routeTAPanelByInterface(ta_panel); } } void TrackAssigner::routeTAPanelBySelf(TAPanel& ta_panel) { - std::vector ta_task_list = initTaskSchedule(ta_panel); - while (!ta_task_list.empty()) { - for (TATask* ta_task : ta_task_list) { - routeTATask(ta_panel, ta_task); - ta_task->addRoutedTimes(); + std::vector routing_task_list = initTaskSchedule(ta_panel); + while (!routing_task_list.empty()) { + for (TATask* routing_task : routing_task_list) { + routeTATask(ta_panel, routing_task); + routing_task->addRoutedTimes(); } updateViolationList(ta_panel); - ta_task_list = getTaskScheduleByViolation(ta_panel); + updateTaskSchedule(ta_panel, routing_task_list); } } @@ -618,7 +673,7 @@ void TrackAssigner::expandSearching(TAPanel& ta_panel) if (neighbor_node->isOpen() && know_cost < neighbor_node->get_known_cost()) { neighbor_node->set_known_cost(know_cost); neighbor_node->set_parent_node(path_head_node); - // 对优先队列中的值修改了,需要重新建堆 + // 对优先队列中的值修改了,需要重新建堆 std::make_heap(open_queue.begin(), open_queue.end(), CmpTANodeCost()); } else if (neighbor_node->isNone()) { neighbor_node->set_known_cost(know_cost); @@ -675,7 +730,7 @@ void TrackAssigner::resetStartAndEnd(TAPanel& ta_panel) TANode* path_head_node = ta_panel.get_path_head_node(); int32_t end_node_list_idx = ta_panel.get_end_node_list_idx(); - // 对于抵达的终点pin,只保留到达的node + // 对于抵达的终点pin,只保留到达的node end_node_list_list[end_node_list_idx].clear(); end_node_list_list[end_node_list_idx].push_back(path_head_node); @@ -691,7 +746,7 @@ void TrackAssigner::resetStartAndEnd(TAPanel& ta_panel) } } if (start_node_list_list.size() == 1) { - // 初始化时,要把start_node_list_list的pin只留一个ap点 + // 初始化时,要把start_node_list_list的pin只留一个ap点 // 后续只要将end_node_list_list的pin保留一个ap点 start_node_list_list.front().clear(); start_node_list_list.front().push_back(path_node); @@ -900,107 +955,181 @@ double TrackAssigner::getEstimateViaCost(TAPanel& ta_panel, TANode* start_node, void TrackAssigner::updateViolationList(TAPanel& ta_panel) { - std::vector new_violation_list = getCostViolationList(ta_panel); - - std::vector& violation_list = ta_panel.get_violation_list(); - // 原结果从graph删除 - for (Violation& violation : violation_list) { - updateViolationToGraph(ta_panel, ChangeType::kDel, violation); + ta_panel.get_violation_list().clear(); + for (Violation new_violation : getCostViolationList(ta_panel)) { + if (new_violation.get_is_routing() != true + || new_violation.get_violation_shape().get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { + continue; + } + if (!RTUTIL.isInside(ta_panel.get_panel_rect().get_real_rect(), new_violation.get_violation_shape().get_real_rect())) { + continue; + } + ta_panel.get_violation_list().push_back(new_violation); } - violation_list = new_violation_list; // 新结果添加到graph - for (Violation& violation : violation_list) { - updateViolationToGraph(ta_panel, ChangeType::kAdd, violation); + for (Violation& violation : ta_panel.get_violation_list()) { + addViolationToGraph(ta_panel, violation); } } std::vector TrackAssigner::getCostViolationList(TAPanel& ta_panel) { - std::string top_name - = RTUTIL.getString("ta_panel_", ta_panel.get_ta_panel_id().get_layer_idx(), "_", ta_panel.get_ta_panel_id().get_panel_idx()); - PlanarRect check_region = ta_panel.get_panel_rect().get_real_rect(); - std::vector> env_shape_list; - std::map>> net_pin_shape_map; - for (auto& [is_routing, layer_net_fixed_rect_map] : ta_panel.get_type_layer_net_fixed_rect_map()) { - for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { - if (is_routing != true || layer_idx != ta_panel.get_panel_rect().get_layer_idx()) { + ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis(); + + std::vector net_shape_list; + for (auto& [net_idx, task_result_map] : ta_panel.get_net_task_result_map()) { + for (auto& [task_idx, segment_list] : task_result_map) { + for (Segment& segment : segment_list) { + for (NetShape net_shape : RTDM.getNetShapeList(net_idx, segment)) { + net_shape_list.push_back(net_shape); + } + } + } + } + std::vector violation_list; + for (NetShape& net_shape : net_shape_list) { + for (auto& [net_idx, fixed_rect_set] : ta_panel.get_net_fixed_rect_map()) { + if (net_shape.get_net_idx() == net_idx) { continue; } - for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { - if (net_idx == -1) { - for (auto& fixed_rect : fixed_rect_set) { - env_shape_list.emplace_back(fixed_rect, true); - } - } else { - for (auto& fixed_rect : fixed_rect_set) { - net_pin_shape_map[net_idx].emplace_back(fixed_rect, true); - } + for (EXTLayerRect* fixed_rect : fixed_rect_set) { + if (RTUTIL.isClosedOverlap(net_shape, fixed_rect->get_real_rect())) { + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_rect(RTUTIL.getOverlap(net_shape, fixed_rect->get_real_rect())); + ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); + ext_layer_rect.set_layer_idx(ta_panel.get_ta_panel_id().get_layer_idx()); + + Violation violation; + violation.set_violation_type(ViolationType::kMetalShort); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set({net_shape.get_net_idx(), net_idx}); + violation.set_required_size(0); + violation_list.push_back(violation); } } + } + for (auto& [net_idx, rect_list] : ta_panel.get_net_access_result_map()) { + if (net_shape.get_net_idx() == net_idx) { + continue; + } + for (LayerRect& rect : rect_list) { + if (RTUTIL.isClosedOverlap(net_shape, rect)) { + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_rect(RTUTIL.getOverlap(net_shape, rect)); + ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); + ext_layer_rect.set_layer_idx(ta_panel.get_ta_panel_id().get_layer_idx()); + + Violation violation; + violation.set_violation_type(ViolationType::kMetalShort); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set({net_shape.get_net_idx(), net_idx}); + violation.set_required_size(0); + violation_list.push_back(violation); + } + } + } + for (auto& [net_idx, patch_set] : ta_panel.get_net_access_patch_map()) { + if (net_shape.get_net_idx() == net_idx) { + continue; + } + for (EXTLayerRect* patch : patch_set) { + if (RTUTIL.isClosedOverlap(net_shape, patch->get_real_rect())) { + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_rect(RTUTIL.getOverlap(net_shape, patch->get_real_rect())); + ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); + ext_layer_rect.set_layer_idx(ta_panel.get_ta_panel_id().get_layer_idx()); + + Violation violation; + violation.set_violation_type(ViolationType::kMetalShort); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set({net_shape.get_net_idx(), net_idx}); + violation.set_required_size(0); + violation_list.push_back(violation); + } + } + } + for (auto& [net_idx, rect_list] : ta_panel.get_net_detailed_result_map()) { + if (net_shape.get_net_idx() == net_idx) { + continue; + } + for (LayerRect& rect : rect_list) { + if (RTUTIL.isClosedOverlap(net_shape, rect)) { + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_rect(RTUTIL.getOverlap(net_shape, rect)); + ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); + ext_layer_rect.set_layer_idx(ta_panel.get_ta_panel_id().get_layer_idx()); + + Violation violation; + violation.set_violation_type(ViolationType::kMetalShort); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set({net_shape.get_net_idx(), net_idx}); + violation.set_required_size(0); + violation_list.push_back(violation); + } + } + } + } + for (size_t i = 0; i < net_shape_list.size(); i++) { + for (size_t j = i + 1; j < net_shape_list.size(); j++) { + if (net_shape_list[i].get_net_idx() == net_shape_list[j].get_net_idx()) { + continue; + } + if (RTUTIL.isClosedOverlap(net_shape_list[i], net_shape_list[j])) { + EXTLayerRect ext_layer_rect; + ext_layer_rect.set_real_rect(RTUTIL.getOverlap(net_shape_list[i], net_shape_list[j])); + ext_layer_rect.set_grid_rect(RTUTIL.getClosedGCellGridRect(ext_layer_rect.get_real_rect(), gcell_axis)); + ext_layer_rect.set_layer_idx(ta_panel.get_ta_panel_id().get_layer_idx()); + + Violation violation; + violation.set_violation_type(ViolationType::kMetalShort); + violation.set_violation_shape(ext_layer_rect); + violation.set_is_routing(true); + violation.set_violation_net_set({net_shape_list[i].get_net_idx(), net_shape_list[j].get_net_idx()}); + violation.set_required_size(0); + violation_list.push_back(violation); + } + } + } + return violation_list; +} + +void TrackAssigner::updateTaskSchedule(TAPanel& ta_panel, std::vector& routing_task_list) +{ + int32_t max_routed_times = ta_panel.get_ta_parameter()->get_max_routed_times(); + + std::set visited_routing_task_set; + std::vector new_routing_task_list; + for (Violation& violation : ta_panel.get_violation_list()) { + for (TATask* ta_task : ta_panel.get_ta_task_list()) { + if (!RTUTIL.exist(violation.get_violation_net_set(), ta_task->get_net_idx())) { + continue; + } + if (ta_task->get_routed_times() < max_routed_times && !RTUTIL.exist(visited_routing_task_set, ta_task)) { + visited_routing_task_set.insert(ta_task); + new_routing_task_list.push_back(ta_task); + } break; } } - std::map*>> net_env_result_map; - for (auto& [net_idx, segment_set] : ta_panel.get_net_access_result_map()) { - for (Segment* segment : segment_set) { - net_env_result_map[net_idx].push_back(segment); - } - } - for (auto& [net_idx, segment_set] : ta_panel.get_net_detailed_result_map()) { - for (Segment* segment : segment_set) { - net_env_result_map[net_idx].push_back(segment); - } - } - std::map> net_env_patch_map; - for (auto& [net_idx, patch_set] : ta_panel.get_net_access_patch_map()) { - for (EXTLayerRect* patch : patch_set) { - net_env_patch_map[net_idx].push_back(patch); - } - } - std::map>> net_check_result_map; - for (auto& [net_idx, task_result_map] : ta_panel.get_net_task_result_map()) { - for (auto& [task_idx, segment_list] : task_result_map) { - for (Segment& segment : segment_list) { - net_check_result_map[net_idx].emplace_back(segment); - } - } - } - DETask de_task; - de_task.set_process_type_set({DEProcessType::kRoutingCost, DEProcessType::kCutCost}); - de_task.set_top_name(top_name); - de_task.set_check_region(check_region); - de_task.set_env_shape_list(env_shape_list); - de_task.set_net_pin_shape_map(net_pin_shape_map); - de_task.set_net_env_result_map(net_env_result_map); - de_task.set_net_env_patch_map(net_env_patch_map); - de_task.set_net_check_result_map(net_check_result_map); - return RTDE.getViolationList(de_task); -} + routing_task_list = new_routing_task_list; -std::vector TrackAssigner::getTaskScheduleByViolation(TAPanel& ta_panel) -{ - int32_t max_routed_times = ta_panel.get_ta_parameter()->get_max_routed_times(); - - std::set violation_net_set; - for (Violation& violation : ta_panel.get_violation_list()) { - for (int32_t violation_net : violation.get_violation_net_set()) { - violation_net_set.insert(violation_net); - } - } - std::vector ta_task_list; + std::vector new_ta_task_list; for (TATask* ta_task : ta_panel.get_ta_task_list()) { - if (!RTUTIL.exist(violation_net_set, ta_task->get_net_idx())) { - continue; + if (!RTUTIL.exist(visited_routing_task_set, ta_task)) { + new_ta_task_list.push_back(ta_task); } - if (ta_task->get_routed_times() >= max_routed_times) { - continue; - } - ta_task_list.push_back(ta_task); } - return ta_task_list; + for (TATask* routing_task : routing_task_list) { + new_ta_task_list.push_back(routing_task); + } + ta_panel.set_ta_task_list(new_ta_task_list); } -void TrackAssigner::routeTAPanelByOther(TAPanel& ta_panel) +void TrackAssigner::routeTAPanelByInterface(TAPanel& ta_panel) { RTI.routeTAPanel(ta_panel); updateViolationList(ta_panel); @@ -1050,7 +1179,7 @@ void TrackAssigner::updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_ if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { return; } - for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape)) { + for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { ta_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1061,19 +1190,18 @@ void TrackAssigner::updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_ } } -void TrackAssigner::updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, Segment& segment) +void TrackAssigner::updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, LayerRect& rect, bool is_routing) { - for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, segment)) { - if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { - continue; - } - for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape)) { - for (Orientation orientation : orientation_set) { - if (change_type == ChangeType::kAdd) { - ta_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); - } else if (change_type == ChangeType::kDel) { - ta_node->get_orient_fixed_rect_map()[orientation].erase(net_shape.get_net_idx()); - } + NetShape net_shape(net_idx, rect, is_routing); + if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { + return; + } + for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape, true)) { + for (Orientation orientation : orientation_set) { + if (change_type == ChangeType::kAdd) { + ta_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); + } else if (change_type == ChangeType::kDel) { + ta_node->get_orient_fixed_rect_map()[orientation].erase(net_shape.get_net_idx()); } } } @@ -1085,7 +1213,7 @@ void TrackAssigner::updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_ if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { return; } - for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape)) { + for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { ta_node->get_orient_fixed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1102,7 +1230,7 @@ void TrackAssigner::updateNetResultToGraph(TAPanel& ta_panel, ChangeType change_ if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { continue; } - for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape)) { + for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape, true)) { for (Orientation orientation : orientation_set) { if (change_type == ChangeType::kAdd) { ta_node->get_orient_routed_rect_map()[orientation].insert(net_shape.get_net_idx()); @@ -1114,35 +1242,114 @@ void TrackAssigner::updateNetResultToGraph(TAPanel& ta_panel, ChangeType change_ } } -void TrackAssigner::updateViolationToGraph(TAPanel& ta_panel, ChangeType change_type, Violation& violation) +void TrackAssigner::addViolationToGraph(TAPanel& ta_panel, Violation& violation) { NetShape net_shape(-1, violation.get_violation_shape().getRealLayerRect(), violation.get_is_routing()); if (!net_shape.get_is_routing() || (ta_panel.get_ta_panel_id().get_layer_idx() != net_shape.get_layer_idx())) { return; } - for (auto& [ta_node, orientation_set] : getNodeOrientationMap(ta_panel, net_shape)) { - for (Orientation orientation : orientation_set) { - if (change_type == ChangeType::kAdd) { - ta_node->get_orient_violation_number_map()[orientation]++; - } else if (change_type == ChangeType::kDel) { - ta_node->get_orient_violation_number_map()[orientation]--; + LayerRect searched_rect; + { + EXTLayerRect& violation_shape = violation.get_violation_shape(); + searched_rect.set_rect(RTUTIL.getEnlargedRect(violation_shape.get_real_rect(), RTDM.getOnlyPitch())); + if (violation.get_is_routing()) { + searched_rect.set_layer_idx(violation_shape.get_layer_idx()); + } else { + RTLOG.error(Loc::current(), "The violation layer is cut!"); + } + } + std::vector> overlap_segment_list; + for (auto& [net_idx, task_result_map] : ta_panel.get_net_task_result_map()) { + for (auto& [task_idx, segment_list] : task_result_map) { + if (!RTUTIL.exist(violation.get_violation_net_set(), net_idx)) { + continue; + } + for (Segment& segment : segment_list) { + if (!RTUTIL.isOverlap(searched_rect, segment)) { + continue; + } + overlap_segment_list.push_back(segment); + } + } + } + addViolationToGraph(ta_panel, searched_rect, overlap_segment_list); +} + +void TrackAssigner::addViolationToGraph(TAPanel& ta_panel, LayerRect& searched_rect, std::vector>& overlap_segment_list) +{ + ScaleAxis& panel_track_axis = ta_panel.get_panel_track_axis(); + GridMap& ta_node_map = ta_panel.get_ta_node_map(); + + for (Segment& overlap_segment : overlap_segment_list) { + LayerCoord& first_coord = overlap_segment.get_first(); + LayerCoord& second_coord = overlap_segment.get_second(); + if (first_coord == second_coord) { + continue; + } + PlanarRect real_rect = RTUTIL.getEnlargedRect(first_coord, second_coord, 0); + if (!RTUTIL.existTrackGrid(real_rect, panel_track_axis)) { + continue; + } + PlanarRect grid_rect = RTUTIL.getTrackGrid(real_rect, panel_track_axis); + std::map> distance_node_map; + { + for (int32_t x = grid_rect.get_ll_x(); x <= grid_rect.get_ur_x(); x++) { + for (int32_t y = grid_rect.get_ll_y(); y <= grid_rect.get_ur_y(); y++) { + TANode* ta_node = &ta_node_map[x][y]; + if (searched_rect.get_layer_idx() != ta_node->get_layer_idx()) { + continue; + } + int32_t distance = 0; + if (!RTUTIL.isInside(searched_rect.get_rect(), ta_node->get_planar_coord())) { + distance = RTUTIL.getManhattanDistance(searched_rect.getMidPoint(), ta_node->get_planar_coord()); + } + distance_node_map[distance].insert(ta_node); + } + } + } + std::set valid_node_set; + if (!distance_node_map[0].empty()) { + valid_node_set = distance_node_map[0]; + } else { + for (auto& [distance, node_set] : distance_node_map) { + valid_node_set.insert(node_set.begin(), node_set.end()); + if (valid_node_set.size() >= 2) { + break; + } + } + } + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + Orientation oppo_orientation = RTUTIL.getOppositeOrientation(orientation); + for (TANode* valid_node : valid_node_set) { + if (LayerCoord(*valid_node) != first_coord) { + valid_node->get_orient_violation_number_map()[oppo_orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), oppo_orientation)) { + valid_node->get_neighbor_node_map()[oppo_orientation]->get_orient_violation_number_map()[orientation]++; + } + } + if (LayerCoord(*valid_node) != second_coord) { + valid_node->get_orient_violation_number_map()[orientation]++; + if (RTUTIL.exist(valid_node->get_neighbor_node_map(), orientation)) { + valid_node->get_neighbor_node_map()[orientation]->get_orient_violation_number_map()[oppo_orientation]++; + } } } } } -std::map> TrackAssigner::getNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape) +std::map> TrackAssigner::getNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape, bool need_enlarged) { std::map> node_orientation_map; if (net_shape.get_is_routing()) { - node_orientation_map = getRoutingNodeOrientationMap(ta_panel, net_shape); + node_orientation_map = getRoutingNodeOrientationMap(ta_panel, net_shape, need_enlarged); } else { RTLOG.error(Loc::current(), "The type of net_shape is cut!"); } return node_orientation_map; } -std::map> TrackAssigner::getRoutingNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape) +std::map> TrackAssigner::getRoutingNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape, + bool need_enlarged) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); if (!net_shape.get_is_routing()) { @@ -1153,18 +1360,37 @@ std::map> TrackAssigner::getRoutingNodeOrientatio } int32_t layer_idx = net_shape.get_layer_idx(); RoutingLayer& routing_layer = routing_layer_list[layer_idx]; - int32_t min_spacing = routing_layer.getMinSpacing(net_shape.get_rect()); + // x_spacing y_spacing + std::vector> spacing_pair_list; + { + // prl + int32_t prl_spacing = routing_layer.getPRLSpacing(net_shape.get_rect()); + spacing_pair_list.emplace_back(prl_spacing, prl_spacing); + // eol + if (routing_layer.isPreferH()) { + spacing_pair_list.emplace_back(routing_layer.get_eol_spacing(), routing_layer.get_eol_within()); + } else { + spacing_pair_list.emplace_back(routing_layer.get_eol_within(), routing_layer.get_eol_spacing()); + } + } int32_t half_wire_width = routing_layer.get_min_width() / 2; GridMap& ta_node_map = ta_panel.get_ta_node_map(); std::map> node_orientation_map; - // wire - { - // 膨胀size为 min_spacing + half_wire_width - int32_t enlarged_size = min_spacing + half_wire_width; + // wire 与 net_shape + for (auto& [x_spacing, y_spacing] : spacing_pair_list) { + int32_t enlarged_x_size = half_wire_width; + int32_t enlarged_y_size = half_wire_width; + if (need_enlarged) { + // 膨胀size为 half_wire_width + spacing + enlarged_x_size += x_spacing; + enlarged_y_size += y_spacing; + } // 贴合的也不算违例 - enlarged_size -= 1; - PlanarRect planar_enlarged_rect = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_size); + enlarged_x_size -= 1; + enlarged_y_size -= 1; + PlanarRect planar_enlarged_rect + = RTUTIL.getEnlargedRect(net_shape.get_rect(), enlarged_x_size, enlarged_y_size, enlarged_x_size, enlarged_y_size); for (auto& [grid_coord, orientation_set] : RTUTIL.getTrackGridOrientationMap(planar_enlarged_rect, ta_panel.get_panel_track_axis())) { TANode& node = ta_node_map[grid_coord.get_x()][grid_coord.get_y()]; for (const Orientation& orientation : orientation_set) { @@ -1191,10 +1417,12 @@ void TrackAssigner::updateSummary(TAModel& ta_model) int32_t micron_dbu = RTDM.getDatabase().get_micron_dbu(); Die& die = RTDM.getDatabase().get_die(); std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::map& routing_wire_length_map = RTDM.getSummary().ta_summary.routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().ta_summary.total_wire_length; - std::map& routing_violation_num_map = RTDM.getSummary().ta_summary.routing_violation_num_map; - int32_t& total_violation_num = RTDM.getSummary().ta_summary.total_violation_num; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_wire_length_map = summary.ta_summary.routing_wire_length_map; + double& total_wire_length = summary.ta_summary.total_wire_length; + std::map& routing_violation_num_map = summary.ta_summary.routing_violation_num_map; + int32_t& total_violation_num = summary.ta_summary.total_violation_num; for (RoutingLayer& routing_layer : routing_layer_list) { routing_wire_length_map[routing_layer.get_layer_idx()] = 0; @@ -1223,10 +1451,12 @@ void TrackAssigner::updateSummary(TAModel& ta_model) void TrackAssigner::printSummary(TAModel& ta_model) { std::vector& routing_layer_list = RTDM.getDatabase().get_routing_layer_list(); - std::map& routing_wire_length_map = RTDM.getSummary().ta_summary.routing_wire_length_map; - double& total_wire_length = RTDM.getSummary().ta_summary.total_wire_length; - std::map& routing_violation_num_map = RTDM.getSummary().ta_summary.routing_violation_num_map; - int32_t& total_violation_num = RTDM.getSummary().ta_summary.total_violation_num; + Summary& summary = RTDM.getDatabase().get_summary(); + + std::map& routing_wire_length_map = summary.ta_summary.routing_wire_length_map; + double& total_wire_length = summary.ta_summary.total_wire_length; + std::map& routing_violation_num_map = summary.ta_summary.routing_violation_num_map; + int32_t& total_violation_num = summary.ta_summary.total_violation_num; fort::char_table routing_wire_length_map_table; { @@ -1254,10 +1484,7 @@ void TrackAssigner::printSummary(TAModel& ta_model) routing_violation_num_map_table << fort::header << "Total" << total_violation_num << RTUTIL.getPercentage(total_violation_num, total_violation_num) << fort::endr; } - std::vector table_list; - table_list.push_back(routing_wire_length_map_table); - table_list.push_back(routing_violation_num_map_table); - RTUTIL.printTableList(table_list); + RTUTIL.printTableList({routing_wire_length_map_table, routing_violation_num_map_table}); } void TrackAssigner::outputNetCSV(TAModel& ta_model) @@ -1507,8 +1734,8 @@ void TrackAssigner::debugPlotTAModel(TAModel& ta_model, std::string flag) // violation { - GPStruct violation_struct("violation"); for (Violation* violation : RTDM.getViolationSet(die)) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation->get_violation_type()))); EXTLayerRect& violation_shape = violation->get_violation_shape(); GPBoundary gp_boundary; @@ -1520,8 +1747,8 @@ void TrackAssigner::debugPlotTAModel(TAModel& ta_model, std::string flag) gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(ta_temp_directory_path, flag, "_ta_model.gds"); @@ -1848,44 +2075,27 @@ void TrackAssigner::debugPlotTAPanel(TAPanel& ta_panel, int32_t curr_task_idx, s } // fixed_rect - for (auto& [is_routing, layer_net_fixed_rect_map] : ta_panel.get_type_layer_net_fixed_rect_map()) { - for (auto& [layer_idx, net_fixed_rect_map] : layer_net_fixed_rect_map) { - if (is_routing != true || layer_idx != ta_panel.get_panel_rect().get_layer_idx()) { - continue; - } - for (auto& [net_idx, fixed_rect_set] : net_fixed_rect_map) { - GPStruct fixed_rect_struct(RTUTIL.getString("fixed_rect(net_", net_idx, ")")); - for (auto& fixed_rect : fixed_rect_set) { - GPBoundary gp_boundary; - gp_boundary.set_data_type(static_cast(GPDataType::kShape)); - gp_boundary.set_rect(fixed_rect->get_real_rect()); - gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(ta_panel.get_panel_rect().get_layer_idx())); - fixed_rect_struct.push(gp_boundary); - } - gp_gds.addStruct(fixed_rect_struct); - } - break; + for (auto& [net_idx, fixed_rect_set] : ta_panel.get_net_fixed_rect_map()) { + GPStruct fixed_rect_struct(RTUTIL.getString("fixed_rect(net_", net_idx, ")")); + for (auto& fixed_rect : fixed_rect_set) { + GPBoundary gp_boundary; + gp_boundary.set_data_type(static_cast(GPDataType::kShape)); + gp_boundary.set_rect(fixed_rect->get_real_rect()); + gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(fixed_rect->get_layer_idx())); + fixed_rect_struct.push(gp_boundary); } + gp_gds.addStruct(fixed_rect_struct); } // net_access_result - for (auto& [net_idx, segment_set] : ta_panel.get_net_access_result_map()) { + for (auto& [net_idx, rect_list] : ta_panel.get_net_access_result_map()) { GPStruct access_result_struct(RTUTIL.getString("access_result(net_", net_idx, ")")); - for (Segment* segment : segment_set) { - for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { - if (net_shape.get_is_routing() != true || net_shape.get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { - continue; - } - GPBoundary gp_boundary; - gp_boundary.set_data_type(static_cast(GPDataType::kShape)); - gp_boundary.set_rect(net_shape.get_rect()); - if (net_shape.get_is_routing()) { - gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(net_shape.get_layer_idx())); - } else { - gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(net_shape.get_layer_idx())); - } - access_result_struct.push(gp_boundary); - } + for (LayerRect& rect : rect_list) { + GPBoundary gp_boundary; + gp_boundary.set_data_type(static_cast(GPDataType::kShape)); + gp_boundary.set_rect(rect); + gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(rect.get_layer_idx())); + access_result_struct.push(gp_boundary); } gp_gds.addStruct(access_result_struct); } @@ -1904,23 +2114,14 @@ void TrackAssigner::debugPlotTAPanel(TAPanel& ta_panel, int32_t curr_task_idx, s } // net_detailed_result - for (auto& [net_idx, segment_set] : ta_panel.get_net_detailed_result_map()) { + for (auto& [net_idx, rect_list] : ta_panel.get_net_detailed_result_map()) { GPStruct detailed_result_struct(RTUTIL.getString("detailed_result(net_", net_idx, ")")); - for (Segment* segment : segment_set) { - for (NetShape& net_shape : RTDM.getNetShapeList(net_idx, *segment)) { - if (net_shape.get_is_routing() != true || net_shape.get_layer_idx() != ta_panel.get_panel_rect().get_layer_idx()) { - continue; - } - GPBoundary gp_boundary; - gp_boundary.set_data_type(static_cast(GPDataType::kShape)); - gp_boundary.set_rect(net_shape.get_rect()); - if (net_shape.get_is_routing()) { - gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(net_shape.get_layer_idx())); - } else { - gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(net_shape.get_layer_idx())); - } - detailed_result_struct.push(gp_boundary); - } + for (LayerRect& rect : rect_list) { + GPBoundary gp_boundary; + gp_boundary.set_data_type(static_cast(GPDataType::kShape)); + gp_boundary.set_rect(rect); + gp_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(rect.get_layer_idx())); + detailed_result_struct.push(gp_boundary); } gp_gds.addStruct(detailed_result_struct); } @@ -1998,8 +2199,8 @@ void TrackAssigner::debugPlotTAPanel(TAPanel& ta_panel, int32_t curr_task_idx, s // violation { - GPStruct violation_struct("violation"); for (Violation& violation : ta_panel.get_violation_list()) { + GPStruct violation_struct(RTUTIL.getString("violation_", GetViolationTypeName()(violation.get_violation_type()))); EXTLayerRect& violation_shape = violation.get_violation_shape(); GPBoundary gp_boundary; @@ -2011,8 +2212,8 @@ void TrackAssigner::debugPlotTAPanel(TAPanel& ta_panel, int32_t curr_task_idx, s gp_boundary.set_layer_idx(RTGP.getGDSIdxByCut(violation_shape.get_layer_idx())); } violation_struct.push(gp_boundary); + gp_gds.addStruct(violation_struct); } - gp_gds.addStruct(violation_struct); } std::string gds_file_path = RTUTIL.getString(ta_temp_directory_path, flag, "_ta_panel_", ta_panel.get_ta_panel_id().get_layer_idx(), "_", diff --git a/src/operation/iRT/source/module/track_assigner/TrackAssigner.hpp b/src/operation/iRT/source/module/track_assigner/TrackAssigner.hpp index 370abdd8a..25bace8cc 100644 --- a/src/operation/iRT/source/module/track_assigner/TrackAssigner.hpp +++ b/src/operation/iRT/source/module/track_assigner/TrackAssigner.hpp @@ -65,6 +65,7 @@ class TrackAssigner void buildTANodeMap(TAPanel& ta_panel); void buildTANodeNeighbor(TAPanel& ta_panel); void buildOrientNetMap(TAPanel& ta_panel); + void exemptPinShape(TAPanel& ta_panel); void routeTAPanel(TAPanel& ta_panel); void routeTAPanelBySelf(TAPanel& ta_panel); std::vector initTaskSchedule(TAPanel& ta_panel); @@ -95,8 +96,8 @@ class TrackAssigner double getEstimateViaCost(TAPanel& ta_panel, TANode* start_node, TANode* end_node); void updateViolationList(TAPanel& ta_panel); std::vector getCostViolationList(TAPanel& ta_panel); - std::vector getTaskScheduleByViolation(TAPanel& ta_panel); - void routeTAPanelByOther(TAPanel& ta_panel); + void updateTaskSchedule(TAPanel& ta_panel, std::vector& routing_task_list); + void routeTAPanelByInterface(TAPanel& ta_panel); void uploadNetResult(TAPanel& ta_panel); void uploadViolation(TAPanel& ta_panel); void freeTAPanel(TAPanel& ta_panel); @@ -104,12 +105,13 @@ class TrackAssigner #if 1 // update env void updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, EXTLayerRect* fixed_rect, bool is_routing); - void updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, Segment& segment); + void updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, LayerRect& rect, bool is_routing); void updateFixedRectToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, EXTLayerRect& patch); void updateNetResultToGraph(TAPanel& ta_panel, ChangeType change_type, int32_t net_idx, Segment& segment); - void updateViolationToGraph(TAPanel& ta_panel, ChangeType change_type, Violation& violation); - std::map> getNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape); - std::map> getRoutingNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape); + void addViolationToGraph(TAPanel& ta_panel, Violation& violation); + void addViolationToGraph(TAPanel& ta_panel, LayerRect& searched_rect, std::vector>& overlap_segment_list); + std::map> getNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape, bool need_enlarged); + std::map> getRoutingNodeOrientationMap(TAPanel& ta_panel, NetShape& net_shape, bool need_enlarged); #endif #if 1 // exhibit diff --git a/src/operation/iRT/source/module/track_assigner/framwork.txt b/src/operation/iRT/source/module/track_assigner/framwork.txt index 55baf2703..8594d5f7c 100644 --- a/src/operation/iRT/source/module/track_assigner/framwork.txt +++ b/src/operation/iRT/source/module/track_assigner/framwork.txt @@ -1,24 +1,25 @@ initTAModel:初始化ta_net setTAParameter:设置ta_model的参数 -initTAPanelMap:构建TAPanel框架,里面主要数据为空 +initTAPanelMap:构建TAPanel框架,里面主要数据为空 buildPanelSchedule:构建时间表 assignTAPanelMap: - buildFixedRect:将GCellmap中的fix_rect(与此Panel覆盖)以指针的方式拷贝到Panel内,不需要对GCellmap删除或添加 - buildAccessResult:将GCellmap中的access_result(与此Panel覆盖)以指针的方式拷贝到Panel内,不需要对GCellmap删除或添加 + buildFixedRect:将GCellmap中的fix_rect(与此Panel覆盖)以指针的方式拷贝到Panel内,不需要对GCellmap删除或添加 + buildAccessResult:将GCellmap中的access_result(与此Panel覆盖)以指针的方式拷贝到Panel内,不需要对GCellmap删除或添加 + buildNetResult:将GCellMap中的net_result(与此Panel覆盖)以指针的方式拷贝到Panel内,不需要对GCellmap删除或添加 + buildViolation:将GCellMap中的violation以实体的方式拷贝到Panel的violation_list,对于完全在Panel内的,在GCellMap中删除 initTATaskList:构建task任务 buildPanelTrackAxis:构建Panel内的track_axis - buildTANodeMap:构建Panel的Graph,只有节点,其他信息后续构建 + buildTANodeMap:构建Panel的Graph,只有节点,其他信息后续构建 buildTANodeNeighbor:将所有节点连接 - buildOrientNetMap:构建Graph的cost,fix_rect从Panel中得到,在ta阶段net_access_result为fix结果 + buildOrientNetMap:构建Graph的cost,fix_rect从Panel中得到,在ta阶段net_access_result为fix结果 routeTAPanel: initTaskSchedule:初始化task布线调度表 - routeTATask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 - updateViolationList:首先得到Violation存到Box下面,然后Violation结果从graph中删除,再加入新的结果 + routeTATask:给task布线,在此函数末尾,布线结果从graph中删除,再加入新的结果 + updateViolationList:首先得到Violation存到Panel下面,然后Violation结果从graph中删除,再加入新的结果 getTaskScheduleByViolation:通过Violation得到新的布线调度 - uploadNetResult:将布线结果加入gcell_map - uploadViolation:将violation加入gcell_map + uploadNetResult:将布线结果加入GCellMap + uploadViolation:将violation加入GCellMap freeTAPanel:析构task_list和node_map - diff --git a/src/operation/iRT/source/module/track_assigner/ta_data_manager/TAPanel.hpp b/src/operation/iRT/source/module/track_assigner/ta_data_manager/TAPanel.hpp index a7ac22ce9..18365bb9a 100644 --- a/src/operation/iRT/source/module/track_assigner/ta_data_manager/TAPanel.hpp +++ b/src/operation/iRT/source/module/track_assigner/ta_data_manager/TAPanel.hpp @@ -37,13 +37,10 @@ class TAPanel TAPanelId& get_ta_panel_id() { return _ta_panel_id; } TAParameter* get_ta_parameter() { return _ta_parameter; } std::vector& get_ta_task_list() { return _ta_task_list; } - std::map>>>& get_type_layer_net_fixed_rect_map() - { - return _type_layer_net_fixed_rect_map; - } - std::map*>>& get_net_access_result_map() { return _net_access_result_map; } + std::map>& get_net_fixed_rect_map() { return _net_fixed_rect_map; } + std::map>& get_net_access_result_map() { return _net_access_result_map; } std::map>& get_net_access_patch_map() { return _net_access_patch_map; } - std::map*>>& get_net_detailed_result_map() { return _net_detailed_result_map; } + std::map>& get_net_detailed_result_map() { return _net_detailed_result_map; } std::map>>>& get_net_task_result_map() { return _net_task_result_map; } std::vector& get_violation_list() { return _violation_list; } ScaleAxis& get_panel_track_axis() { return _panel_track_axis; } @@ -53,12 +50,11 @@ class TAPanel void set_ta_panel_id(const TAPanelId& ta_panel_id) { _ta_panel_id = ta_panel_id; } void set_ta_parameter(TAParameter* ta_parameter) { _ta_parameter = ta_parameter; } void set_ta_task_list(const std::vector& ta_task_list) { _ta_task_list = ta_task_list; } - void set_type_layer_net_fixed_rect_map( - const std::map>>>& type_layer_net_fixed_rect_map) + void set_net_fixed_rect_map(const std::map>& net_fixed_rect_map) { - _type_layer_net_fixed_rect_map = type_layer_net_fixed_rect_map; + _net_fixed_rect_map = net_fixed_rect_map; } - void set_net_access_result_map(const std::map*>>& net_access_result_map) + void set_net_access_result_map(const std::map>& net_access_result_map) { _net_access_result_map = net_access_result_map; } @@ -66,14 +62,10 @@ class TAPanel { _net_access_patch_map = net_access_patch_map; } - void set_net_detailed_result_map(const std::map*>>& net_detailed_result_map) + void set_net_detailed_result_map(const std::map>& net_detailed_result_map) { _net_detailed_result_map = net_detailed_result_map; } - void set_net_task_result_map(const std::map>>>& net_task_result_map) - { - _net_task_result_map = net_task_result_map; - } void set_violation_list(const std::vector& violation_list) { _violation_list = violation_list; } void set_panel_track_axis(const ScaleAxis& panel_track_axis) { _panel_track_axis = panel_track_axis; } void set_ta_node_map(const GridMap& ta_node_map) { _ta_node_map = ta_node_map; } @@ -120,10 +112,10 @@ class TAPanel TAPanelId _ta_panel_id; TAParameter* _ta_parameter = nullptr; std::vector _ta_task_list; - std::map>>> _type_layer_net_fixed_rect_map; - std::map*>> _net_access_result_map; + std::map> _net_fixed_rect_map; + std::map> _net_access_result_map; std::map> _net_access_patch_map; - std::map*>> _net_detailed_result_map; + std::map> _net_detailed_result_map; std::map>>> _net_task_result_map; std::vector _violation_list; ScaleAxis _panel_track_axis; diff --git a/src/operation/iRT/source/toolkit/utility/Utility.hpp b/src/operation/iRT/source/toolkit/utility/Utility.hpp index c3b5328f4..543702c8a 100644 --- a/src/operation/iRT/source/toolkit/utility/Utility.hpp +++ b/src/operation/iRT/source/toolkit/utility/Utility.hpp @@ -392,8 +392,8 @@ class Utility /** * !在检测DRC中 - * 如果a与b中有膨胀矩形,那么则用isOpenOverlap - * 如果a与b中都是真实矩形,那么用isClosedOverlap + * 如果a与b中有膨胀矩形,那么则用isOpenOverlap + * 如果a与b中都是真实矩形,那么用isClosedOverlap * * isOpenOverlap:不考虑边的overlap */ @@ -401,8 +401,8 @@ class Utility /** * !在检测DRC中 - * 如果a与b中有膨胀矩形,那么则用isOpenOverlap - * 如果a与b中都是真实矩形,那么用isClosedOverlap + * 如果a与b中有膨胀矩形,那么则用isOpenOverlap + * 如果a与b中都是真实矩形,那么用isClosedOverlap * * isClosedOverlap:考虑边的overlap */ @@ -462,7 +462,7 @@ class Utility && first_layer_idx <= coord.get_layer_idx() && coord.get_layer_idx() <= second_layer_idx); } - // 判断coord是否在rect内,可以选择是否包含边界 + // 判断coord是否在rect内,可以选择是否包含边界 static bool isInside(const PlanarRect& rect, const PlanarCoord& coord, bool boundary = true) { int32_t coord_x = coord.get_x(), coord_y = coord.get_y(); @@ -682,8 +682,102 @@ class Utility return ratio; } + static Segment getOverlap(const LayerRect& rect, const Segment& segment) + { + int32_t rect_ll_x = rect.get_ll_x(); + int32_t rect_ll_y = rect.get_ll_y(); + int32_t rect_ur_x = rect.get_ur_x(); + int32_t rect_ur_y = rect.get_ur_y(); + int32_t rect_layer_idx = rect.get_layer_idx(); + + int32_t first_x = segment.get_first().get_x(); + int32_t first_y = segment.get_first().get_y(); + int32_t first_layer_idx = segment.get_first().get_layer_idx(); + int32_t second_x = segment.get_second().get_x(); + int32_t second_y = segment.get_second().get_y(); + int32_t second_layer_idx = segment.get_second().get_layer_idx(); + swapByASC(first_x, second_x); + swapByASC(first_y, second_y); + swapByASC(first_layer_idx, second_layer_idx); + + if (first_y == second_y && first_layer_idx == second_layer_idx) { + if (first_y >= rect_ll_y && first_y <= rect_ur_y && rect_layer_idx == first_layer_idx) { + int32_t overlap_min_x = std::max(rect_ll_x, std::min(first_x, second_x)); + int32_t overlap_max_x = std::min(rect_ur_x, std::max(first_x, second_x)); + + if (overlap_min_x <= overlap_max_x) { + return Segment(LayerCoord(overlap_min_x, first_y, rect_layer_idx), + LayerCoord(overlap_max_x, first_y, rect_layer_idx)); + } + } + } else if (first_x == second_x && first_layer_idx == second_layer_idx) { + if (first_x >= rect_ll_x && first_x <= rect_ur_x && rect_layer_idx == first_layer_idx) { + int32_t overlap_min_y = std::max(rect_ll_y, std::min(first_y, second_y)); + int32_t overlap_max_y = std::min(rect_ur_y, std::max(first_y, second_y)); + + if (overlap_min_y <= overlap_max_y) { + return Segment(LayerCoord(first_x, overlap_min_y, rect_layer_idx), + LayerCoord(first_x, overlap_max_y, rect_layer_idx)); + } + } + } else if (first_x == second_x && first_y == second_y) { + if (first_x >= rect_ll_x && first_x <= rect_ur_x && first_y >= rect_ll_y && first_y <= rect_ur_y + && rect_layer_idx >= std::min(first_layer_idx, second_layer_idx) + && rect_layer_idx <= std::max(first_layer_idx, second_layer_idx)) { + return Segment(LayerCoord(first_x, first_y, rect_layer_idx), LayerCoord(first_x, first_y, rect_layer_idx)); + } + } + return Segment(LayerCoord(-1, -1, -1), LayerCoord(-1, -1, -1)); + } + + static bool isOverlap(const LayerRect& rect, const Segment& segment) + { + int32_t rect_ll_x = rect.get_ll_x(); + int32_t rect_ll_y = rect.get_ll_y(); + int32_t rect_ur_x = rect.get_ur_x(); + int32_t rect_ur_y = rect.get_ur_y(); + int32_t rect_layer_idx = rect.get_layer_idx(); + + int32_t first_x = segment.get_first().get_x(); + int32_t first_y = segment.get_first().get_y(); + int32_t first_layer_idx = segment.get_first().get_layer_idx(); + int32_t second_x = segment.get_second().get_x(); + int32_t second_y = segment.get_second().get_y(); + int32_t second_layer_idx = segment.get_second().get_layer_idx(); + swapByASC(first_x, second_x); + swapByASC(first_y, second_y); + swapByASC(first_layer_idx, second_layer_idx); + + if (first_y == second_y && first_layer_idx == second_layer_idx) { + if (first_y >= rect_ll_y && first_y <= rect_ur_y && rect_layer_idx == first_layer_idx) { + int32_t overlap_min_x = std::max(rect_ll_x, std::min(first_x, second_x)); + int32_t overlap_max_x = std::min(rect_ur_x, std::max(first_x, second_x)); + + if (overlap_min_x <= overlap_max_x) { + return true; + } + } + } else if (first_x == second_x && first_layer_idx == second_layer_idx) { + if (first_x >= rect_ll_x && first_x <= rect_ur_x && rect_layer_idx == first_layer_idx) { + int32_t overlap_min_y = std::max(rect_ll_y, std::min(first_y, second_y)); + int32_t overlap_max_y = std::min(rect_ur_y, std::max(first_y, second_y)); + + if (overlap_min_y <= overlap_max_y) { + return true; + } + } + } else if (first_x == second_x && first_y == second_y) { + if (first_x >= rect_ll_x && first_x <= rect_ur_x && first_y >= rect_ll_y && first_y <= rect_ur_y + && rect_layer_idx >= std::min(first_layer_idx, second_layer_idx) + && rect_layer_idx <= std::max(first_layer_idx, second_layer_idx)) { + return true; + } + } + return false; + } + /** - * 分开矩形,将master矩形用rect进行分开,并不是求差集 + * 分开矩形,将master矩形用rect进行分开,并不是求差集 * ┌────────────────────────────────────┐ split ┌────────────────────────────────────┐ * │ master │ ──────> │ c │ * │ ┌─────────────────┐ │ └────────────────────────────────────┘ @@ -695,9 +789,9 @@ class Utility * │ │ │ │ * │ a │ │ b │ * └───────────┘ └──────┘ - * 如上图所示,输入master和rect - * 若split方向为horizontal,将得到a和b,可以理解为在横向上分开 - * 若split方向为vertical,将得到c + * 如上图所示,输入master和rect + * 若split方向为horizontal,将得到a和b,可以理解为在横向上分开 + * 若split方向为vertical,将得到c */ static std::vector getSplitRectList(const PlanarRect& master, const PlanarRect& rect, Direction split_direction) { @@ -890,14 +984,14 @@ class Utility return node_list; } - // 以层序遍历获取树的所有结点,可以控制遍历最大深度 + // 以层序遍历获取树的所有结点,可以控制遍历最大深度 template static std::vector*>> getLevelOrder(MTree& tree, int32_t max_level = -1) { return getLevelOrder(tree.get_root(), max_level); } - // 以层序遍历获取树的所有结点,可以控制遍历最大深度 + // 以层序遍历获取树的所有结点,可以控制遍历最大深度 template static std::vector*>> getLevelOrder(TNode* root, int32_t max_level = -1) { @@ -959,14 +1053,14 @@ class Utility return false; } - // 对树结点内的值进行转换,需要自定义转换函数 + // 对树结点内的值进行转换,需要自定义转换函数 template static MTree convertTree(MTree& old_tree, const std::function& convert, Args&... args) { return MTree(convertTree(old_tree.get_root(), convert, args...)); } - // 对树结点内的值进行转换,需要自定义转换函数 + // 对树结点内的值进行转换,需要自定义转换函数 template static TNode* convertTree(TNode* old_root, const std::function& convert, Args&... args) { @@ -1022,7 +1116,7 @@ class Utility return segment_list; } - // 通过树根节点和边集构建一棵树,也会消除多个连通分量 + // 通过树根节点和边集构建一棵树,也会消除多个连通分量 template static MTree getTreeBySegList(const T& root_value, const std::vector>& segment_list) { @@ -1083,7 +1177,7 @@ class Utility #if 1 // 与GCell有关的计算 - // 如果与边缘相交,则取内的,不取边缘上 + // 如果与边缘相交,则取内的,不取边缘上 static PlanarRect getOpenGCellGridRect(const PlanarRect& real_rect, ScaleAxis& gcell_axis) { int32_t real_ll_x = real_rect.get_ll_x(); @@ -1298,7 +1392,7 @@ class Utility #if 1 // 与Track有关的计算 /** - * 计算边界包含的刻度列表,如果边界与刻度重合,那么也会包含在内 + * 计算边界包含的刻度列表,如果边界与刻度重合,那么也会包含在内 */ static std::vector getScaleList(int32_t begin_line, int32_t end_line, std::vector& scale_grid_list) { @@ -1324,6 +1418,41 @@ class Utility return scale_line_list; } + /** + * 反取begin_line和end_line之外的数据,比begin_line小的存pre_scale_list,比end_line大的存post_scale_set + */ + static void getScaleList(int32_t begin_line, int32_t end_line, std::vector& scale_grid_list, + std::vector& pre_scale_list, std::vector& post_scale_set) + { + swapByASC(begin_line, end_line); + + std::vector scale_line_list; + for (ScaleGrid& scale_grid : scale_grid_list) { + if (scale_grid.get_step_length() == 0) { + if (scale_grid.get_start_line() < begin_line) { + pre_scale_list.push_back(scale_grid.get_start_line()); + } + if (end_line < scale_grid.get_start_line()) { + post_scale_set.push_back(scale_grid.get_start_line()); + } + } else { + for (int32_t scale_line = scale_grid.get_start_line(); scale_line <= scale_grid.get_end_line(); + scale_line += scale_grid.get_step_length()) { + if (scale_line < begin_line) { + pre_scale_list.push_back(scale_line); + } + if (end_line < scale_line) { + post_scale_set.push_back(scale_line); + } + } + } + } + std::sort(pre_scale_list.begin(), pre_scale_list.end()); + pre_scale_list.erase(std::unique(pre_scale_list.begin(), pre_scale_list.end()), pre_scale_list.end()); + std::sort(post_scale_set.begin(), post_scale_set.end()); + post_scale_set.erase(std::unique(post_scale_set.begin(), post_scale_set.end()), post_scale_set.end()); + } + static bool existTrackGrid(const PlanarCoord& real_coord, ScaleAxis& track_axis) { PlanarCoord grid_coord = getTrackGrid(real_coord, track_axis); @@ -1991,8 +2120,8 @@ class Utility /** * curr_layer_idx在可布线层内 - * 如果不是最高可布线层,向上打孔 - * 是最高可布线层,向下打孔 + * 如果不是最高可布线层,向上打孔 + * 是最高可布线层,向下打孔 * * curr_layer_idx在可布线层外 * 打孔到最近的可布线层 @@ -2263,7 +2392,7 @@ class Utility * 下面每个字母表示一个独立的直角多边形 * 求解(A ∪ B) - (D ∪ E ∪ F) * 转((A - D) ∩ (A - E) ∩ (A - F)) ∪ ((B - D) ∩ (B - E) ∩ (B - F)) - * 其中利用(A - D)、(A - E)等式中结果不可能出现线,实现boost结果传递 + * 其中利用(A - D)、(A - E)等式中结果不可能出现线,实现boost结果传递 */ // 将输入解析 // 其中master_poly_list为(A ∪ B) @@ -2289,7 +2418,7 @@ class Utility BGMultiPolyDBL diff_multi_poly; bg::difference(master_poly, rect_poly, diff_multi_poly); if (diff_multi_poly.empty()) { - // 当(A - D)为空,后续(A - D) ∩ (A - E) ∩ (A - F)结果为空,直接跳过 + // 当(A - D)为空,后续(A - D) ∩ (A - E) ∩ (A - F)结果为空,直接跳过 diff_multi_poly_list.clear(); break; } else { @@ -2372,13 +2501,13 @@ class Utility for (const PlanarRect& special_rect : special_rect_list) { if (special_rect.get_ll() == special_rect.get_ur()) { /** - * 对于点矩形, 在其中一个rect内(包含边界)则被删除 + * 对于点矩形, 在其中一个rect内(不包含边界)则被删除 */ PlanarCoord point = special_rect.get_ll(); bool exist_inside = false; for (const PlanarRect& rect : rect_list) { - if (rect.get_ll_x() <= point.get_x() && point.get_x() <= rect.get_ur_x() && rect.get_ll_y() <= point.get_y() - && point.get_y() <= rect.get_ur_y()) { + if (rect.get_ll_x() < point.get_x() && point.get_x() < rect.get_ur_x() && rect.get_ll_y() < point.get_y() + && point.get_y() < rect.get_ur_y()) { exist_inside = true; break; } @@ -2405,12 +2534,12 @@ class Utility int32_t seg_second_x = segment.get_second().get_x(); int32_t seg_y = segment.get_first().get_y(); if (rect_ll_y <= seg_y && seg_y <= rect_ur_y && seg_first_x < rect_ur_x && rect_ll_x < seg_second_x) { - if (seg_first_x < rect_ll_x) { + if (seg_first_x <= rect_ll_x) { // 提出左突出 segment_list_temp.emplace_back(segment.get_first(), PlanarCoord(rect_ll_x, seg_y)); } - if (rect_ur_x < seg_second_x) { - // 提出右突出的 + if (rect_ur_x <= seg_second_x) { + // 提出右突出 segment_list_temp.emplace_back(PlanarCoord(rect_ur_x, seg_y), segment.get_second()); } } else { @@ -2421,12 +2550,12 @@ class Utility int32_t seg_second_y = segment.get_second().get_y(); int32_t seg_x = segment.get_first().get_x(); if (rect_ll_x <= seg_x && seg_x <= rect_ur_x && seg_first_y < rect_ur_y && rect_ll_y < seg_second_y) { - if (seg_first_y < rect_ll_y) { + if (seg_first_y <= rect_ll_y) { // 提出下突出 segment_list_temp.emplace_back(segment.get_first(), PlanarCoord(seg_x, rect_ll_y)); } - if (rect_ur_y < seg_second_y) { - // 提出上突出的 + if (rect_ur_y <= seg_second_y) { + // 提出上突出 segment_list_temp.emplace_back(PlanarCoord(seg_x, rect_ur_y), segment.get_second()); } } else { @@ -2478,7 +2607,7 @@ class Utility master_poly += convertToGTLRectInt(master); } if (!is_open) { - // 提取点矩形,线段矩形 + // 提取点矩形,线段矩形 std::vector gtl_rect_list; gtl::get_rectangles(gtl_rect_list, master_poly, gtl::HORIZONTAL); gtl::get_rectangles(gtl_rect_list, master_poly, gtl::VERTICAL); diff --git a/src/operation/iRT/test/test_boost/test_boost.cpp b/src/operation/iRT/test/test_boost/test_boost.cpp index bfd334d28..410f4dfd8 100644 --- a/src/operation/iRT/test/test_boost/test_boost.cpp +++ b/src/operation/iRT/test/test_boost/test_boost.cpp @@ -391,7 +391,7 @@ class RTUtil * 下面每个字母表示一个独立的直角多边形 * 求解(A ∪ B) - (D ∪ E ∪ F) * 转((A - D) ∩ (A - E) ∩ (A - F)) ∪ ((B - D) ∩ (B - E) ∩ (B - F)) - * 其中利用(A - D)、(A - E)等式中结果不可能出现线,实现boost结果传递 + * 其中利用(A - D)、(A - E)等式中结果不可能出现线,实现boost结果传递 */ // 将输入解析 // 其中master_poly_list为(A ∪ B) @@ -417,7 +417,7 @@ class RTUtil BGMultiPolyDBL diff_multi_poly; bg::difference(master_poly, rect_poly, diff_multi_poly); if (diff_multi_poly.empty()) { - // 当(A - D)为空,后续(A - D) ∩ (A - E) ∩ (A - F)结果为空,直接跳过 + // 当(A - D)为空,后续(A - D) ∩ (A - E) ∩ (A - F)结果为空,直接跳过 diff_multi_poly_list.clear(); break; } else { @@ -574,7 +574,7 @@ class RTUtil master_poly += gtl::rectangle_data(master.get_ll_x(), master.get_ll_y(), master.get_ur_x(), master.get_ur_y()); } if (!is_open) { - // 提取点矩形,线段矩形 + // 提取点矩形,线段矩形 std::vector> gtl_rect_list; gtl::get_rectangles(gtl_rect_list, master_poly, gtl::HORIZONTAL); gtl::get_rectangles(gtl_rect_list, master_poly, gtl::VERTICAL); diff --git a/src/operation/iRT/test/test_pa/test_pa.cpp b/src/operation/iRT/test/test_pa/test_pa.cpp index e5bfd24b3..360911be3 100644 --- a/src/operation/iRT/test/test_pa/test_pa.cpp +++ b/src/operation/iRT/test/test_pa/test_pa.cpp @@ -7,10 +7,10 @@ using namespace std; // Function to find all connected components -vector> findConnectedComponents(vector>& relations) +vector> findConnectedComponents(vector>& relations) { - unordered_map> graph; - unordered_set visited; + unordered_map> graph; + unordered_set visited; // Build the graph for (const auto& relation : relations) { @@ -18,19 +18,19 @@ vector> findConnectedComponents(vector>& relations) graph[relation.second].push_back(relation.first); } - vector> connectedComponents; + vector> connectedComponents; // Helper function to perform DFS and find all nodes in the current connected component - auto dfs = [&](int node, vector& component) { - stack s; + auto dfs = [&](int32_t node, vector& component) { + stack s; s.push(node); while (!s.empty()) { - int current = s.top(); + int32_t current = s.top(); s.pop(); if (visited.count(current) == 0) { visited.insert(current); component.push_back(current); - for (int neighbor : graph[current]) { + for (int32_t neighbor : graph[current]) { if (visited.count(neighbor) == 0) { s.push(neighbor); } @@ -42,7 +42,7 @@ vector> findConnectedComponents(vector>& relations) // Find all connected components for (const auto& node : graph) { if (visited.count(node.first) == 0) { - vector component; + vector component; dfs(node.first, component); connectedComponents.push_back(component); } @@ -51,17 +51,17 @@ vector> findConnectedComponents(vector>& relations) return connectedComponents; } -int main() +int32_t main() { // Example input: vector of pairs representing the relations - vector> relations = {{8, 9}, {1, 2}, {2, 3}, {4, 5}, {7, 6}, {7, 8}}; + vector> relations = {{8, 9}, {1, 2}, {2, 3}, {4, 5}, {7, 6}, {7, 8}}; // Find all connected components - vector> connectedComponents = findConnectedComponents(relations); + vector> connectedComponents = findConnectedComponents(relations); // Print the connected components for (const auto& component : connectedComponents) { - for (int node : component) { + for (int32_t node : component) { cout << node << " "; } cout << endl; diff --git a/src/operation/iSTA/api/TimingIDBAdapter.cc b/src/operation/iSTA/api/TimingIDBAdapter.cc index 4a6625050..3e7f14b15 100644 --- a/src/operation/iSTA/api/TimingIDBAdapter.cc +++ b/src/operation/iSTA/api/TimingIDBAdapter.cc @@ -724,7 +724,7 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { if (!link_all_cell) { configStaLinkCells(); } - + _ista->linkLibertys(); _ista->set_design_name(_idb_design->get_design_name().c_str()); @@ -776,7 +776,9 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { inst_cell->get_cell_port_or_port_bus(port_base_name.c_str()); LOG_INFO_IF(!library_port_or_port_bus) - << cell_port_name << " port is not found."; + << cell_port_name << " port is not found in lib cell " + << inst_cell->get_cell_name() << " of " + << inst_cell->get_owner_lib()->get_file_name(); std::unique_ptr pin_bus; PinBus* found_pin_bus = nullptr; @@ -817,6 +819,9 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { } auto& created_inst = design_netlist.addInstance(std::move(sta_inst)); crossRef(&created_inst, db_inst); + + LOG_INFO_EVERY_N(10000) + << "build inst num: " << design_netlist.getInstanceNum(); } }; @@ -857,8 +862,12 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { std::string inst_name = std::regex_replace(raw_name, re, ""); auto* sta_inst = design_netlist.findInstance(inst_name.c_str()); + LOG_FATAL_IF(!sta_inst) << "Instance " << inst_name << " not found"; auto inst_pin = sta_inst->getPin(cell_port_name.c_str()); - LOG_FATAL_IF(!inst_pin); + LOG_FATAL_IF(!inst_pin) + << "Instance " << sta_inst->getFullName() << " cell Pin " + << cell_port_name << " not found for cell " + << sta_inst->get_inst_cell()->get_cell_name(); if (sta_net) { sta_net->addPinPort(*inst_pin); @@ -889,6 +898,9 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { } } } + + LOG_INFO_EVERY_N(10000) + << "build net num: " << design_netlist.getNetNum(); } }; @@ -896,6 +908,10 @@ unsigned TimingIDBAdapter::convertDBToTimingNetlist(bool link_all_cell) { build_ports(); build_nets(); + LOG_INFO << "build instance num: " << design_netlist.getInstanceNum(); + LOG_INFO << "build port num: " << design_netlist.getPortNum(); + LOG_INFO << "build net num: " << design_netlist.getNetNum(); + return 1; } diff --git a/src/operation/iSTA/main.cc b/src/operation/iSTA/main.cc index 6db56f2ed..bc03ae677 100644 --- a/src/operation/iSTA/main.cc +++ b/src/operation/iSTA/main.cc @@ -68,6 +68,7 @@ int registerCommands() { registerTclCmd(CmdReportConstraint, "report_constraint"); registerTclCmd(CmdDefToVerilog, "def_to_verilog"); registerTclCmd(CmdVerilogToDef, "verilog_to_def"); + registerTclCmd(CmdDumpGraphData, "dump_graph_data"); return EXIT_SUCCESS; } diff --git a/src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc b/src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc index b4d8f0391..6de06ad81 100644 --- a/src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc +++ b/src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc @@ -857,7 +857,6 @@ void RcNet::updateRcTiming(RustSpefNet* spef_net) { // } } - rust_free_spef_net(spef_net); } /** * @brief net load diff --git a/src/operation/iSTA/source/module/netlist/Netlist.hh b/src/operation/iSTA/source/module/netlist/Netlist.hh index 6eb535523..0cdaf0c8f 100644 --- a/src/operation/iSTA/source/module/netlist/Netlist.hh +++ b/src/operation/iSTA/source/module/netlist/Netlist.hh @@ -179,6 +179,7 @@ class Netlist : public DesignObject { std::size_t getInstanceNum() { return _instances.size(); } std::size_t getNetNum() { return _nets.size(); } + std::size_t getPortNum() { return _ports.size(); } void reset(); diff --git a/src/operation/iSTA/source/module/python-api/PythonSta.cc b/src/operation/iSTA/source/module/python-api/PythonSta.cc index 7fb163a41..7644a0104 100644 --- a/src/operation/iSTA/source/module/python-api/PythonSta.cc +++ b/src/operation/iSTA/source/module/python-api/PythonSta.cc @@ -43,6 +43,10 @@ PYBIND11_MODULE(ista_cpp, m) { m.def("display_timing_tns_map", display_timing_tns_map); m.def("display_slew_map", display_slew_map); m.def("get_used_libs", get_used_libs); + + m.def("build_timing_graph", build_timing_graph); + m.def("update_clock_timing", update_clock_timing); + m.def("dump_graph_data", dump_graph_data, ("graph_file")); } } // namespace ista diff --git a/src/operation/iSTA/source/module/python-api/PythonSta.hh b/src/operation/iSTA/source/module/python-api/PythonSta.hh index b25e7be56..617df7c3a 100644 --- a/src/operation/iSTA/source/module/python-api/PythonSta.hh +++ b/src/operation/iSTA/source/module/python-api/PythonSta.hh @@ -224,4 +224,32 @@ std::vector get_used_libs() { return ret; } +/** + * @brief Only build timing graph. + * + */ +void build_timing_graph() { + auto* ista = ista::Sta::getOrCreateSta(); + ista->buildGraph(); +} + +/** + * @brief Only update clock timing. + * + */ +void update_clock_timing() { + auto* ista = ista::Sta::getOrCreateSta(); + ista->updateClockTiming(); +} + +/** + * @brief Print the graph in yaml format. + * + * @param graph_file + */ +void dump_graph_data(std::string graph_file) { + auto* ista = ista::Sta::getOrCreateSta(); + ista->dumpGraphData(graph_file.c_str()); +} + } // namespace ista diff --git a/src/operation/iSTA/source/module/shell-cmd/CmdDumpGraphData.cc b/src/operation/iSTA/source/module/shell-cmd/CmdDumpGraphData.cc new file mode 100644 index 000000000..08fc2061f --- /dev/null +++ b/src/operation/iSTA/source/module/shell-cmd/CmdDumpGraphData.cc @@ -0,0 +1,50 @@ +// *************************************************************************************** +// 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. +// *************************************************************************************** +/** + * @file CmdDumpGraphData.cc + * @author simin tao (taosm@pcl.ac.cn) + * @brief The implemention of dump graph data command. + * @version 0.1 + * @date 2024-11-06 + */ +#include "ShellCmd.hh" + +namespace ista { + +CmdDumpGraphData::CmdDumpGraphData(const char* cmd_name) : TclCmd(cmd_name) { + auto* graph_option = new TclStringOption("graph_file", 1, nullptr); + addOption(graph_option); + +} + +unsigned CmdDumpGraphData::check() { return 1; } + +unsigned CmdDumpGraphData::exec() { + if (!check()) { + return 0; + } + + TclOption* graph_file_option = getOptionOrArg("graph_file"); + auto* graph_file = graph_file_option->getStringVal(); + + auto* ista = ista::Sta::getOrCreateSta(); + ista->dumpGraphData(graph_file); + + return 1; +} + +} \ No newline at end of file diff --git a/src/operation/iSTA/source/module/shell-cmd/ShellCmd.hh b/src/operation/iSTA/source/module/shell-cmd/ShellCmd.hh index 93f115b44..48ff76e2b 100644 --- a/src/operation/iSTA/source/module/shell-cmd/ShellCmd.hh +++ b/src/operation/iSTA/source/module/shell-cmd/ShellCmd.hh @@ -198,4 +198,17 @@ class CmdVerilogToDef : public TclCmd { unsigned exec(); }; +/** + * @brief dump graph data. + * + */ +class CmdDumpGraphData : public TclCmd { + public: + explicit CmdDumpGraphData(const char* cmd_name); + ~CmdDumpGraphData() override = default; + + unsigned check(); + unsigned exec(); +}; + } // namespace ista diff --git a/src/operation/iSTA/source/module/sta/Sta.cc b/src/operation/iSTA/source/module/sta/Sta.cc index bc53cd1d1..121452c36 100644 --- a/src/operation/iSTA/source/module/sta/Sta.cc +++ b/src/operation/iSTA/source/module/sta/Sta.cc @@ -649,7 +649,7 @@ void Sta::linkDesignWithRustParser(const char *top_cell_name) { net_name = rust_convert_verilog_id(net_id)->id; } else if (rust_is_bus_index_id(net_id)) { net_name = rust_convert_verilog_index_id(net_id)->id; - } else { + } else if (rust_is_bus_slice_id(net_id)) { net_name = rust_convert_verilog_slice_id(net_id)->id; } // fix net name contain backslash @@ -797,6 +797,13 @@ void Sta::linkDesignWithRustParser(const char *top_cell_name) { } rust_free_verilog_file(_rust_verilog_file_ptr); LOG_INFO << "link design " << top_cell_name << " end"; + + LOG_INFO << "design " << top_cell_name + << " inst num: " << design_netlist.getInstanceNum(); + LOG_INFO << "design " << top_cell_name + << " net num: " << design_netlist.getNetNum(); + LOG_INFO << "design " << top_cell_name + << " port num: " << design_netlist.getPortNum(); } /** @@ -2355,8 +2362,7 @@ unsigned Sta::updateClockTiming() { StaApplySdc(StaApplySdc::PropType::kApplySdcPostNormalClockProp), StaClockPropagation( StaClockPropagation::PropType::kUpdateGeneratedClockProp), - StaApplySdc(StaApplySdc::PropType::kApplySdcPostClockProp) - }; + StaApplySdc(StaApplySdc::PropType::kApplySdcPostClockProp)}; for (auto &func : funcs) { the_graph.exec(func); @@ -2642,7 +2648,19 @@ void Sta::dumpNetlistData() { LOG_INFO << "cell_types.txt written to " << std::string(design_work_space) + std::string("/cell_types.txt") << std::endl; - outputJson.close(); + outputTxt.close(); +} + +/** + * @brief dump timing graph data. + * + */ +void Sta::dumpGraphData(const char *graph_file) { + StaDumpYaml dump_data; + dump_data.set_yaml_file_path(graph_file); + + auto &the_graph = get_graph(); + the_graph.exec(dump_data); } /** diff --git a/src/operation/iSTA/source/module/sta/Sta.hh b/src/operation/iSTA/source/module/sta/Sta.hh index 57ca86629..3a54ad1da 100644 --- a/src/operation/iSTA/source/module/sta/Sta.hh +++ b/src/operation/iSTA/source/module/sta/Sta.hh @@ -479,6 +479,8 @@ class Sta { void dumpVertexData(std::vector vertex_names); void dumpNetlistData(); + void dumpGraphData(const char* graph_file); + void buildClockTrees(); // const char* getUnit(const char* unit_name); diff --git a/src/operation/iSTA/source/module/sta/StaBuildRCTree.cc b/src/operation/iSTA/source/module/sta/StaBuildRCTree.cc index bd00137c8..26741b292 100644 --- a/src/operation/iSTA/source/module/sta/StaBuildRCTree.cc +++ b/src/operation/iSTA/source/module/sta/StaBuildRCTree.cc @@ -130,6 +130,7 @@ unsigned StaBuildRCTree::operator()(StaGraph* the_graph) { auto* rc_net = getSta()->getRcNet(design_net); // DLOG_INFO << "Update Rc tree timing " << spef_name; rc_net->updateRcTiming(spef_net); + rust_free_spef_net(spef_net); } else { LOG_FATAL << "build rc tree not found design net " << spef_net->_name; @@ -156,7 +157,10 @@ unsigned StaBuildRCTree::operator()(StaGraph* the_graph) { auto* rc_net = getSta()->getRcNet(design_net); // DLOG_INFO << "Update Rc tree timing " << spef_name; rc_net->updateRcTiming(rust_spef_net); - // printYaml(spef_net); + + // printYaml(*rust_spef_net); + rust_free_spef_net(rust_spef_net); + } else { LOG_FATAL << "build rc tree not found design net " << spef_name; } @@ -168,7 +172,7 @@ unsigned StaBuildRCTree::operator()(StaGraph* the_graph) { // ProfilerStop(); - // printYamlText("spef_1W.yaml"); + // printYamlText("spef.yaml"); LOG_INFO << "build rc tree end"; diff --git a/src/operation/iSTA/source/module/sta/StaDump.cc b/src/operation/iSTA/source/module/sta/StaDump.cc index f3b8a53a5..58f597212 100644 --- a/src/operation/iSTA/source/module/sta/StaDump.cc +++ b/src/operation/iSTA/source/module/sta/StaDump.cc @@ -22,14 +22,13 @@ * @date 2021-04-22 */ -#include "StaDump.hh" - #include #include #include #include +#include "StaDump.hh" #include "ThreadPool/ThreadPool.h" namespace ista { @@ -165,10 +164,11 @@ unsigned StaDumpYaml::operator()(StaArc* the_arc) { arc_node["src"] = arc->get_src()->getName(); arc_node["snk"] = arc->get_snk()->getName(); - arc_node["arc_type"] = - arc->isDelayArc() - ? (arc->isInstArc() ? "cell Delay" : "net Delay") - : arc->isSetupArc() ? "Setup" : arc->isHoldArc() ? "Hold" : "Other"; + arc_node["arc_type"] = arc->isDelayArc() + ? (arc->isInstArc() ? "cell Delay" : "net Delay") + : arc->isSetupArc() ? "Setup" + : arc->isHoldArc() ? "Hold" + : "Other"; YAML::Node delay_node; arc_node["arc_delay_data"] = delay_node; @@ -204,12 +204,18 @@ unsigned StaDumpYaml::operator()(StaGraph* the_graph) { LOG_INFO << "dump graph arc total arc " << the_graph->numArc(); StaVertex* the_vertex; - FOREACH_VERTEX(the_graph, the_vertex) { the_vertex->exec(*this); } + FOREACH_VERTEX(the_graph, the_vertex) { + the_vertex->exec(*this); + LOG_INFO_EVERY_N(10000) << "dump 10000 vertexes ..."; + } StaArc* the_arc; - FOREACH_ARC(the_graph, the_arc) { the_arc->exec(*this); } + FOREACH_ARC(the_graph, the_arc) { + the_arc->exec(*this); + LOG_INFO_EVERY_N(10000) << "dump 10000 arcs ..."; + } - printText("graph.yaml"); + printText(_yaml_file_path.c_str()); LOG_INFO << "dump graph yaml end"; return 1; @@ -224,6 +230,8 @@ void StaDumpYaml::printText(const char* file_name) { std::ofstream file(file_name, std::ios::trunc); file << _node << std::endl; file.close(); + + LOG_INFO << "output yaml file path: " << file_name; } /** @@ -282,14 +290,16 @@ unsigned StaDumpDelayYaml::operator()(StaArc* the_arc) { auto* snk_obj = snk_node->get_design_obj(); arc_node["net_name"] = the_net->get_name(); arc_node["fanout"] = the_net->getLoads().size(); - arc_node["Elmore"] = - rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kElmore).value_or(0.0); - arc_node["D2M"] = - rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kD2M).value_or(0.0); - arc_node["ECM"] = - rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kECM).value_or(0.0); - arc_node["D2MC"] = - rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kD2MC).value_or(0.0); + if (rc_net) { + arc_node["Elmore"] = + rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kElmore).value_or(0.0); + arc_node["D2M"] = + rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kD2M).value_or(0.0); + arc_node["ECM"] = + rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kECM).value_or(0.0); + arc_node["D2MC"] = + rc_net->delayNs(*snk_obj, RcNet::DelayMethod::kD2MC).value_or(0.0); + } } return 1; diff --git a/src/operation/iSTA/source/module/sta/StaDump.hh b/src/operation/iSTA/source/module/sta/StaDump.hh index 41a715b1c..0b5a9fb44 100644 --- a/src/operation/iSTA/source/module/sta/StaDump.hh +++ b/src/operation/iSTA/source/module/sta/StaDump.hh @@ -41,12 +41,18 @@ class StaDumpYaml : public StaFunc { void printText(const char* file_name); + void set_yaml_file_path(const char* yaml_file_path) { + _yaml_file_path = yaml_file_path; + } + auto& get_yaml_file_path() { return _yaml_file_path; } + protected: YAML::Node _node; + std::string _yaml_file_path; }; /** - * @brief The class for dump delay data in yaml text file for traing data. + * @brief The class for dump delay data in yaml text file for training data. * */ class StaDumpDelayYaml : public StaDumpYaml { diff --git a/src/operation/iSTA/source/module/sta/StaReport.cc b/src/operation/iSTA/source/module/sta/StaReport.cc index b4bddc119..6b2cefe99 100644 --- a/src/operation/iSTA/source/module/sta/StaReport.cc +++ b/src/operation/iSTA/source/module/sta/StaReport.cc @@ -738,9 +738,16 @@ unsigned StaReportPathDump::operator()(StaSeqPathData* seq_path_data) { path_stack.pop(); } + std::string design_work_space = + dump_yaml.getSta()->get_design_work_space(); + std::string path_dir = design_work_space + "/path"; + std::filesystem::create_directories(path_dir); + + static unsigned file_id = 1; std::string now_time = Time::getNowWallTime(); std::string tmp = Str::replace(now_time, ":", "_"); - const char* text_file_name = Str::printf("path_%s.yml", tmp.c_str()); + const char* text_file_name = Str::printf( + "%s/path_%s_%d.yaml", path_dir.c_str(), tmp.c_str(), file_id++); dump_yaml.printText(text_file_name); @@ -791,7 +798,7 @@ unsigned StaReportPathYaml::operator()(StaSeqPathData* seq_path_data) { std::string now_time = Time::getNowWallTime(); std::string tmp = Str::replace(now_time, ":", "_"); const char* text_file_name = Str::printf( - "%s/path_delay_%s_%d.yml", path_dir.c_str(), tmp.c_str(), file_id++); + "%s/path_delay_%s_%d.yaml", path_dir.c_str(), tmp.c_str(), file_id++); dump_delay_yaml.printText(text_file_name); diff --git a/src/operation/iTO/CMakeLists.txt b/src/operation/iTO/CMakeLists.txt index c31ee3ccd..4d828aca0 100644 --- a/src/operation/iTO/CMakeLists.txt +++ b/src/operation/iTO/CMakeLists.txt @@ -16,7 +16,7 @@ message(STATUS "================= TO: Debugging Options =================") # set(DEBUG_ITO_EVALUATOR ON) # source/module/fix_drv -set(DEBUG_ITO_FIX_DRV ON) +# set(DEBUG_ITO_FIX_DRV ON) # source/module/fix_hold # set(DEBUG_ITO_FIX_HOLD ON) diff --git a/src/operation/iTO/README.md b/src/operation/iTO/README.md index a6a659f1b..50ecafacf 100644 --- a/src/operation/iTO/README.md +++ b/src/operation/iTO/README.md @@ -43,6 +43,7 @@ iTO提供了4个Tcl命令: "max_allowed_buffering_fanout": 20, // 针对setup,线网的fanout超过该值时不会对其进行缓冲器插入优化 "min_divide_fanout": 8 // 针对setup,线网的fanout大于该值时通过插入缓冲器把fanout降低 "optimize_endpoints_percent": 1.0 //针对setup,需要优化的违例端点占全部违例端点的比例 +"drv_optimize_iter_number": 5 // 针对drv,drv优化的执行次数 ``` diff --git a/src/operation/iTO/source/config/Config.json b/src/operation/iTO/source/config/Config.json index f863c902a..b8f39064d 100644 --- a/src/operation/iTO/source/config/Config.json +++ b/src/operation/iTO/source/config/Config.json @@ -54,5 +54,6 @@ "number_of_decreasing_slack_iter": 5, "max_allowed_buffering_fanout": 20, "min_divide_fanout": 8, - "optimize_endpoints_percent": 1.0 + "optimize_endpoints_percent": 1.0, + "drv_optimize_iter_number": 5 } \ No newline at end of file diff --git a/src/operation/iTO/source/config/JsonParser.cpp b/src/operation/iTO/source/config/JsonParser.cpp index a4f55b84e..713c80623 100644 --- a/src/operation/iTO/source/config/JsonParser.cpp +++ b/src/operation/iTO/source/config/JsonParser.cpp @@ -110,6 +110,7 @@ void JsonParser::jsonToConfig(Json* json) toConfig->set_max_allowed_buffering_fanout(json->at("max_allowed_buffering_fanout").get()); toConfig->set_min_divide_fanout(json->at("min_divide_fanout").get()); toConfig->set_optimize_endpoints_percent(json->at("optimize_endpoints_percent").get()); + toConfig->set_drv_optimize_iter_number(json->at("drv_optimize_iter_number").get()); // Set specific names prefixes auto specific_prefix = json->at("specific_prefix"); diff --git a/src/operation/iTO/source/config/ToConfig.h b/src/operation/iTO/source/config/ToConfig.h index 842137d40..1fd7c04a5 100644 --- a/src/operation/iTO/source/config/ToConfig.h +++ b/src/operation/iTO/source/config/ToConfig.h @@ -78,6 +78,7 @@ class ToConfig { void set_max_allowed_buffering_fanout(int num) { _max_allowed_buffering_fanout = num; } void set_min_divide_fanout(int num) { _min_divide_fanout = num; } void set_optimize_endpoints_percent(float num) { _optimize_endpoints_percent = num; } + void set_drv_optimize_iter_number(int num) { _drv_optimize_iter_number = num; } void set_drv_buffer_prefix(const string& prefix) { _drv_buffer_prefix = prefix; } void set_drv_net_prefix(const string& prefix) { _drv_net_prefix = prefix; } @@ -117,6 +118,7 @@ class ToConfig { int get_max_allowed_buffering_fanout() { return _max_allowed_buffering_fanout; } int get_min_divide_fanout() { return _min_divide_fanout; } float get_optimize_endpoints_percent() { return _optimize_endpoints_percent; } + int get_drv_optimize_iter_number() { return _drv_optimize_iter_number; } string get_drv_buffer_prefix() const { return _drv_buffer_prefix; } string get_drv_net_prefix() const { return _drv_net_prefix; } @@ -162,6 +164,7 @@ class ToConfig { int _max_allowed_buffering_fanout = 20; int _min_divide_fanout = 8; // Nets with low fanout don't need to divide loads. float _optimize_endpoints_percent = 1.0; // Nets with low fanout don't need to divide loads. + int _drv_optimize_iter_number = 1.0; // max iter number for optimize DRV // output string _out_def_path; diff --git a/src/operation/iTO/source/module/evaluator/EstimateParasitics.cpp b/src/operation/iTO/source/module/evaluator/EstimateParasitics.cpp index ba64a106b..5f5c7909a 100644 --- a/src/operation/iTO/source/module/evaluator/EstimateParasitics.cpp +++ b/src/operation/iTO/source/module/evaluator/EstimateParasitics.cpp @@ -116,9 +116,7 @@ void EstimateParasitics::estimateNetParasitics(Net* net) void EstimateParasitics::estimateInvalidNetParasitics(Net* net, DesignObject* driver_pin_port) { if (_parasitics_invalid_nets.find(net) != _parasitics_invalid_nets.end() && net) { - if (timingEngine->get_sta_engine()->get_ista()->getRcNet(net)) { - timingEngine->get_sta_engine()->resetRcTree(net); - } + excuteWireParasitic(net); _parasitics_invalid_nets.erase(net); @@ -134,6 +132,10 @@ void EstimateParasitics::excuteWireParasitic(Net* curr_net) } // cout << tree; + if (timingEngine->get_sta_engine()->get_ista()->getRcNet(curr_net)) { + timingEngine->get_sta_engine()->resetRcTree(curr_net); + } + vector segment_idx; vector length_wire; tree->driverToLoadLength(tree->get_root(), segment_idx, length_wire, 0); diff --git a/src/operation/iTO/source/module/fix_drv/ViolationOptimizer.cpp b/src/operation/iTO/source/module/fix_drv/ViolationOptimizer.cpp index c9b4b6f29..1e9ba6b40 100644 --- a/src/operation/iTO/source/module/fix_drv/ViolationOptimizer.cpp +++ b/src/operation/iTO/source/module/fix_drv/ViolationOptimizer.cpp @@ -25,6 +25,8 @@ #include "api/TimingIDBAdapter.hh" #include "timing_engine.h" +#include + namespace ito { ViolationOptimizer* ViolationOptimizer::_instance = nullptr; @@ -82,6 +84,10 @@ void ViolationOptimizer::checkAndRepair() int net_connect_port = 0; for (int i = number_driver_vertices - 1; i >= 0; --i) { + if ((number_driver_vertices - i) % 1000 == 0 || i == 0) { + LOG_INFO << "The 1-th Check and repair: " << (number_driver_vertices - i) << "/" << number_driver_vertices << "(" + << (double(number_driver_vertices - i) / number_driver_vertices) * 100 << "%) nets\n"; + } StaVertex* driver = sorted_driver_vertices[i]; auto* design_obj = driver->get_design_obj(); @@ -114,14 +120,25 @@ void ViolationOptimizer::checkAndRepair() void ViolationOptimizer::iterCheckAndRepair() { + int max_iter = toConfig->get_drv_optimize_iter_number(); + int iter = 1; + if (iter == max_iter) { + return; + } + checkViolations(); - int max_iter = 6; - int iter = 1; int prev_violation_num = _violation_nets_map.size(); while (!_violation_nets_map.empty()) { // If there are still a violation nets, the secondary fix is performed. + int which_id = 1; for (auto [net, cap_load_allowed_max] : _violation_nets_map) { + int batch_size = std::max(prev_violation_num / 100, 10); + if (which_id % batch_size == 0 || which_id == prev_violation_num) { + LOG_INFO << "The " << iter + 1 << "-th Check and repair: " << which_id << "/" << prev_violation_num << "(" + << (double(which_id) / prev_violation_num) * 100 << "%) nets\n"; + } + which_id++; optimizeViolationNet(net, cap_load_allowed_max); } int last_violation_num = _violation_nets_map.size(); diff --git a/src/operation/iTO/source/module/fix_drv/ViolationOptimizer_check.cpp b/src/operation/iTO/source/module/fix_drv/ViolationOptimizer_check.cpp index 4dee8cb1f..40e2ed29c 100644 --- a/src/operation/iTO/source/module/fix_drv/ViolationOptimizer_check.cpp +++ b/src/operation/iTO/source/module/fix_drv/ViolationOptimizer_check.cpp @@ -136,6 +136,7 @@ double ViolationOptimizer::calcLoadCap(ista::LibPort* driver_port, double slew) while (slew_diff < 0.0) { lower_cap = upper_cap; upper_cap *= 2.0; + slew_diff = calcSlew(driver_port, upper_cap) - slew; } // 二分法查找最佳电容值 diff --git a/src/operation/iTO/source/module/fix_hold/HoldOptimizer_buffers.cpp b/src/operation/iTO/source/module/fix_hold/HoldOptimizer_buffers.cpp index 3f299dd15..1728c1df4 100644 --- a/src/operation/iTO/source/module/fix_hold/HoldOptimizer_buffers.cpp +++ b/src/operation/iTO/source/module/fix_hold/HoldOptimizer_buffers.cpp @@ -129,7 +129,11 @@ void HoldOptimizer::initBufferCell() auto bufs = toConfig->get_hold_insert_buffers(); for (auto buf : bufs) { auto buffer = timingEngine->get_sta_engine()->findLibertyCell(buf.c_str()); - _available_buffer_cells.emplace_back(buffer); + if (!buffer) { + LOG_INFO << "Buffer cell " << buf.c_str() << " not found" << endl; + } else { + _available_buffer_cells.emplace_back(buffer); + } } } diff --git a/src/operation/iTO/source/module/fix_hold/HoldOptimizer_process.cpp b/src/operation/iTO/source/module/fix_hold/HoldOptimizer_process.cpp index 294eb7e9c..768dd0a16 100644 --- a/src/operation/iTO/source/module/fix_hold/HoldOptimizer_process.cpp +++ b/src/operation/iTO/source/module/fix_hold/HoldOptimizer_process.cpp @@ -175,7 +175,13 @@ int HoldOptimizer::optHoldViolationEnd(TOVertexSeq fanins) { int insert_buffer_count = 0; - for (auto vertex : fanins) { + int batch_size = fanins.size() / 10; + for (int i = 0; i < fanins.size(); i++) { + if ((i + 1) % batch_size == 0 || (i + 1) == fanins.size()) { + LOG_INFO << "Opt hold end: " << (i + 1) << "/" << fanins.size() << "(" << (double(i + 1) / fanins.size()) * 100 << "%)\n"; + } + + auto vertex = fanins[i]; TODesignObjSeq load_vio_pins; TODelay max_insert_delay = std::numeric_limits::max(); @@ -212,6 +218,7 @@ int HoldOptimizer::optHoldViolationEnd(TOVertexSeq fanins) insertBufferOptHold(vertex, insert_number, load_vio_pins); if (toDmInst->get_buffer_num() > _max_numb_insert_buf || toDmInst->reachMaxArea()) { + LOG_INFO << "Reach the maximum number of buffers that can be inserted.\n"; return insert_buffer_count; } } diff --git a/src/operation/iTO/source/module/fix_setup/SetupOptimizer_init.cpp b/src/operation/iTO/source/module/fix_setup/SetupOptimizer_init.cpp index 645778fc1..75aab2d99 100644 --- a/src/operation/iTO/source/module/fix_setup/SetupOptimizer_init.cpp +++ b/src/operation/iTO/source/module/fix_setup/SetupOptimizer_init.cpp @@ -60,7 +60,11 @@ void SetupOptimizer::initBufferCell() auto bufs = toConfig->get_setup_insert_buffers(); for (auto buf : bufs) { auto buffer = timingEngine->get_sta_engine()->findLibertyCell(buf.c_str()); - _available_lib_cell_sizes.emplace_back(buffer); + if (!buffer) { + LOG_INFO << "Buffer cell " << buf.c_str() << " not found" << endl; + } else { + _available_lib_cell_sizes.emplace_back(buffer); + } } } diff --git a/src/operation/iTO/source/module/placer/Placer.cpp b/src/operation/iTO/source/module/placer/Placer.cpp index bf1315027..3fac508da 100644 --- a/src/operation/iTO/source/module/placer/Placer.cpp +++ b/src/operation/iTO/source/module/placer/Placer.cpp @@ -60,7 +60,6 @@ void Placer::initRow() _row_space = toDmInst->init_placer(); _row_height = toDmInst->get_site_height(); _site_width = toDmInst->get_site_width(); - int a = 0; } /** @@ -106,6 +105,9 @@ std::pair Placer::findNearestSpace(unsigned int master_width, int loc_ if (best_opt) { update_loc_x = best_opt->begin(); + if (update_loc_x == -1 || update_loc_y == -1) { + return make_pair(loc_x, loc_y); + } return make_pair(update_loc_x, update_loc_y); } cout << "[Placer::findNearestSpace] Can't find suitable space to place the buffer " diff --git a/src/operation/iTO/source/module/solver/tree_build/TreeBuild.cpp b/src/operation/iTO/source/module/solver/tree_build/TreeBuild.cpp index 443e58a18..af129bbc1 100644 --- a/src/operation/iTO/source/module/solver/tree_build/TreeBuild.cpp +++ b/src/operation/iTO/source/module/solver/tree_build/TreeBuild.cpp @@ -99,6 +99,32 @@ bool TreeBuild::makeRoutingTree(ista::Net* net, RoutingType rout_type) } }; + struct pair_hash { + std::size_t operator()(const std::pair& pair) const + { + return std::hash()(pair.first) ^ std::hash()(pair.second); + } + }; + + auto findDuplicateCoordinates = [](const int* real_x, const int* real_y, int size) { + std::unordered_map> result_map; + std::unordered_map, int, pair_hash> coord_map; + + for (int i = 0; i < size; ++i) { + std::pair coord = {real_x[i], real_y[i]}; + if (coord_map.find(coord) != coord_map.end()) { + if (result_map.find(coord_map[coord]) != result_map.end()) { + result_map[coord_map[coord]].push_back(i); + } else { + result_map[coord_map[coord]] = {i}; + } + } else { + coord_map[coord] = static_cast(i); + } + } + return result_map; + }; + getConnectedPins(net, _pins); int pin_num = _pins.size(); if (pin_num < 2) { @@ -116,6 +142,10 @@ bool TreeBuild::makeRoutingTree(ista::Net* net, RoutingType rout_type) x[i] = pin_loc.get_x(); y[i] = pin_loc.get_y(); + if (pin_loc.get_x() == -1 && pin_loc.get_y() == -1) { + return false; + } + if (pin->isOutput()) { driver_id = i; } @@ -123,6 +153,15 @@ bool TreeBuild::makeRoutingTree(ista::Net* net, RoutingType rout_type) std::swap(_pins[0], _pins[driver_id]); std::swap(x[0], x[driver_id]); std::swap(y[0], y[driver_id]); + + // 对重合的节点坐标进行微调 + auto check = findDuplicateCoordinates(x, y, pin_num); + for (auto c : check) { + for (int i = 0; i < c.second.size(); i++) { + x[c.second[i]] += (i+1); + } + } + driver_id = 0; build(rout_type, x, y, pin_num, driver_id); return true; diff --git a/src/platform/report/report_evaluator/report_evaluator.cpp b/src/platform/report/report_evaluator/report_evaluator.cpp index 423219e08..624bbffe9 100644 --- a/src/platform/report/report_evaluator/report_evaluator.cpp +++ b/src/platform/report/report_evaluator/report_evaluator.cpp @@ -107,7 +107,8 @@ std::shared_ptr ReportEvaluator::createWireLengthReport() std::shared_ptr ReportEvaluator::createCongestionReport() { // evaluate Instance Density & Pin Density - ieval::DensityMapSummary density_map_summay = DENSITY_API_INST->densityMap(); + std::string stage = "place"; // hard code , only for place stage + ieval::DensityMapSummary density_map_summay = DENSITY_API_INST->densityMap(stage); std::string pin_density_file_path = density_map_summay.pin_map_summary.allcell_pin_density; std::ifstream pin_density_file(pin_density_file_path); @@ -183,8 +184,8 @@ std::shared_ptr ReportEvaluator::createCongestionReport() << "Total Overflow" << "Maximal Overflow" << TABLE_ENDLINE; - CONGESTION_API_INST->egrMap(); - ieval::OverflowSummary overflow_summary = CONGESTION_API_INST->egrOverflow(); + CONGESTION_API_INST->egrMap("place"); // hard code , only for place stage + ieval::OverflowSummary overflow_summary = CONGESTION_API_INST->egrOverflow("place"); // hard code , only for place stage *tbl << ieda::Str::printf("%.2f", overflow_summary.weighted_average_overflow_union) << ieda::Str::printf("%.2f", overflow_summary.total_overflow_union) << ieda::Str::printf("%.2f", overflow_summary.max_overflow_union) << TABLE_ENDLINE; diff --git a/src/solver/legalization/method/CMakeLists.txt b/src/solver/legalization/method/CMakeLists.txt index bb2d72566..fd50ec48e 100644 --- a/src/solver/legalization/method/CMakeLists.txt +++ b/src/solver/legalization/method/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(solver_lg_method target_link_libraries(solver_lg_method PRIVATE + usage ipl-module-logger ipl-bridge ipl-configurator diff --git a/src/solver/legalization/method/abacus/Abacus.cc b/src/solver/legalization/method/abacus/Abacus.cc index 4c0b2b695..f344ba935 100644 --- a/src/solver/legalization/method/abacus/Abacus.cc +++ b/src/solver/legalization/method/abacus/Abacus.cc @@ -23,1125 +23,1116 @@ #include "LGDatabase.hh" #include "LGInstance.hh" #include "LGInterval.hh" +#include "usage/usage.hh" namespace ieda_solver { - Abacus::~Abacus() - { - for (auto pair : _cluster_map) { - delete pair.second; +Abacus::~Abacus() +{ + for (auto pair : _cluster_map) { + delete pair.second; + } + _cluster_map.clear(); + _inst_belong_cluster.clear(); + _interval_cluster_root.clear(); + _interval_remain_length.clear(); +} + +void Abacus::initDataRequirement(ipl::LGConfig* lg_config, ipl::LGDatabase* lg_database) +{ + // clean abacus info first. + _cluster_map.clear(); + _inst_belong_cluster.clear(); + _interval_cluster_root.clear(); + _interval_remain_length.clear(); + + _database = lg_database; + _config = lg_config; + + _inst_belong_cluster.resize(_database->get_lgInstance_list().size(), nullptr); + + int32_t interval_cnt = 0; + for (auto& interval_vec : _database->get_lg_layout()->get_interval_2d_list()) { + for (auto* interval : interval_vec) { + interval_cnt++; + _interval_remain_length.push_back(interval->get_max_x() - interval->get_min_x()); } - _cluster_map.clear(); - _inst_belong_cluster.clear(); - _interval_cluster_root.clear(); - _interval_remain_length.clear(); } + _interval_cluster_root.resize(interval_cnt, nullptr); - void Abacus::initDataRequirement(ipl::LGConfig* lg_config, ipl::LGDatabase* lg_database) - { - // clean abacus info first. - _cluster_map.clear(); - _inst_belong_cluster.clear(); - _interval_cluster_root.clear(); - _interval_remain_length.clear(); + _row_height = _database->get_lg_layout()->get_row_height(); + _site_width = _database->get_lg_layout()->get_site_width(); +} - _database = lg_database; - _config = lg_config; +bool Abacus::isInitialized() +{ + return !_cluster_map.empty(); +} - _inst_belong_cluster.resize(_database->get_lgInstance_list().size(), nullptr); +void Abacus::specifyTargetInstList(std::vector& target_inst_list) +{ + _target_inst_list.clear(); + _target_inst_list = target_inst_list; +} - int32_t interval_cnt = 0; - for (auto& interval_vec : _database->get_lg_layout()->get_interval_2d_list()) { - for (auto* interval : interval_vec) { - interval_cnt++; - _interval_remain_length.push_back(interval->get_max_x() - interval->get_min_x()); - } - } - _interval_cluster_root.resize(interval_cnt, nullptr); +bool Abacus::runLegalization() +{ + // Sort all movable instances + std::vector movable_inst_list; + pickAndSortMovableInstList(movable_inst_list); - _row_height = _database->get_lg_layout()->get_row_height(); - _site_width = _database->get_lg_layout()->get_site_width(); - } + int32_t inst_id = 0; - bool Abacus::isInitialized() - { - return !_cluster_map.empty(); - } - - void Abacus::specifyTargetInstList(std::vector& target_inst_list) - { - _target_inst_list.clear(); - _target_inst_list = target_inst_list; - } - - bool Abacus::runLegalization() - { - // Sort all movable instances - std::vector movable_inst_list; - pickAndSortMovableInstList(movable_inst_list); - - int32_t inst_id = 0; - for (auto* inst : movable_inst_list) { - - int32_t best_row = INT32_MAX; - int32_t best_cost = INT32_MAX; - for (int32_t row_idx = 0; row_idx < _database->get_lg_layout()->get_row_num(); row_idx++) { - int32_t cost = placeRow(inst, row_idx, true, false); - - if (cost < best_cost) { - best_cost = cost; - best_row = row_idx; - } - } - - if (best_row == INT32_MAX) { - LOG_ERROR << "Instance: " << inst->get_name() << "Cannot find a row for placement"; - return false; - } - - placeRow(inst, best_row, false, false); - - inst_id++; - if (inst_id % 100000 == 0) { - LOG_INFO << "Place Instance : " << inst_id; - } + ieda::Stats sta_status; + double run_time = 0; + for (auto* inst : movable_inst_list) { + int best_row = get_best_cost_row(inst); + if (best_row == INT32_MAX) { + LOG_ERROR << "Instance: " << inst->get_name() << "Cannot find a row for placement"; + return false; } - return true; + placeRow(inst, best_row, false, false); + + inst_id++; + if (inst_id % 10000 == 0) { + double time_delta = sta_status.elapsedRunTime(); + LOG_INFO << "Place Instance : " << inst_id << ", runtime : " << time_delta - run_time; + + run_time = time_delta; + } } - bool Abacus::runIncrLegalization() - { - int32_t row_range_num = 5; - int32_t row_num = _database->get_lg_layout()->get_row_num(); + LOG_INFO << "Legalization runtime : " << sta_status.elapsedRunTime(); - // spilt new inst from the cluster. - RollbackInfo rollback_info; - for (auto* inst : _target_inst_list) { - splitTargetInst(inst, rollback_info); - } - rollback_info.is_dirty = true; - _rollback_stack.push(rollback_info); + return true; +} - for (auto* inst : _target_inst_list) { - int32_t row_idx = inst->get_coordi().get_y() / _row_height; - int32_t max_row_idx = (row_idx + row_range_num > row_num) ? row_num : row_idx + row_range_num; - int32_t min_row_idx = (row_idx - row_range_num < 0) ? 0 : row_idx - row_range_num; +bool Abacus::runIncrLegalization() +{ + int32_t row_range_num = 5; + int32_t row_num = _database->get_lg_layout()->get_row_num(); - int32_t best_row = INT32_MAX; - int32_t best_cost = INT32_MAX; - for (int32_t row_idx = min_row_idx; row_idx < max_row_idx; row_idx++) { - int32_t cost = placeRow(inst, row_idx, true, false); - if (cost < best_cost) { - best_cost = cost; - best_row = row_idx; - } + // spilt new inst from the cluster. + RollbackInfo rollback_info; + for (auto* inst : _target_inst_list) { + splitTargetInst(inst, rollback_info); + } + rollback_info.is_dirty = true; + _rollback_stack.push(rollback_info); + + for (auto* inst : _target_inst_list) { + int32_t row_idx = inst->get_coordi().get_y() / _row_height; + int32_t max_row_idx = (row_idx + row_range_num > row_num) ? row_num : row_idx + row_range_num; + int32_t min_row_idx = (row_idx - row_range_num < 0) ? 0 : row_idx - row_range_num; + + int32_t best_row = INT32_MAX; + int32_t best_cost = INT32_MAX; + for (int32_t row_idx = min_row_idx; row_idx < max_row_idx; row_idx++) { + int32_t cost = placeRow(inst, row_idx, true, false); + if (cost < best_cost) { + best_cost = cost; + best_row = row_idx; } - placeRow(inst, best_row, false, true); } - - return true; + placeRow(inst, best_row, false, true); } - void Abacus::pickAndSortMovableInstList(std::vector& movable_inst_list) - { - for (auto* inst : _database->get_lgInstance_list()) { - if (inst->get_state() == ipl::LGINSTANCE_STATE::kFixed) { - continue; - } - movable_inst_list.push_back(inst); - } + return true; +} - std::sort(movable_inst_list.begin(), movable_inst_list.end(), - [](ipl::LGInstance* l_inst, ipl::LGInstance* r_inst) { return (l_inst->get_coordi().get_x() < r_inst->get_coordi().get_x()); }); +void Abacus::pickAndSortMovableInstList(std::vector& movable_inst_list) +{ + for (auto* inst : _database->get_lgInstance_list()) { + if (inst->get_state() == ipl::LGINSTANCE_STATE::kFixed) { + continue; + } + movable_inst_list.push_back(inst); } - int32_t Abacus::placeRow(ipl::LGInstance* inst, int32_t row_idx, bool is_trial, bool is_record_cluster) - { - ipl::Rectangle inst_shape = std::move(inst->get_shape()); + std::sort(movable_inst_list.begin(), movable_inst_list.end(), + [](ipl::LGInstance* l_inst, ipl::LGInstance* r_inst) { return (l_inst->get_coordi().get_x() < r_inst->get_coordi().get_x()); }); +} - // Determine clusters and their optimal positions x_c(c): - std::vector interval_list = _database->get_lg_layout()->get_interval_2d_list()[row_idx]; +int32_t Abacus::placeRow(ipl::LGInstance* inst, int32_t row_idx, bool is_trial, bool is_record_cluster) +{ + ipl::Rectangle inst_shape = std::move(inst->get_shape()); - // Select the nearest interval for the instance - int32_t row_interval_idx = searchNearestIntervalIndex(interval_list, inst_shape); - if (row_interval_idx == INT32_MAX) { - // std::cout << "Instance is not overlap with interval!" << std::endl; + // Determine clusters and their optimal positions x_c(c): + std::vector interval_list = _database->get_lg_layout()->get_interval_2d_list()[row_idx]; + + // Select the nearest interval for the instance + int32_t row_interval_idx = searchNearestIntervalIndex(interval_list, inst_shape); + if (row_interval_idx == INT32_MAX) { + // std::cout << "Instance is not overlap with interval!" << std::endl; + return INT32_MAX; + } + + if (_interval_remain_length[interval_list[row_interval_idx]->get_index()] < inst_shape.get_width()) { + // Select the most recent non-full interval + int32_t origin_idx = row_interval_idx; + row_interval_idx = searchRemainSpaceSegIndex(interval_list, inst_shape, origin_idx); + if (row_interval_idx == origin_idx) { + // LOG_INFO << "Row : " << row_idx << " has no room to place."; return INT32_MAX; } - - if (_interval_remain_length[interval_list[row_interval_idx]->get_index()] < inst_shape.get_width()) { - // Select the most recent non-full interval - int32_t origin_idx = row_interval_idx; - row_interval_idx = searchRemainSpaceSegIndex(interval_list, inst_shape, origin_idx); - if (row_interval_idx == origin_idx) { - // LOG_INFO << "Row : " << row_idx << " has no room to place."; - return INT32_MAX; - } - } - - // Arrange inst into interval - auto* target_interval = interval_list[row_interval_idx]; - AbacusCluster target_cluster = std::move(arrangeInstIntoIntervalCluster(inst, target_interval)); - - // Calculate cost - int32_t movement_cost = 0; - int32_t coordi_x = target_cluster.get_min_x(); - int32_t inst_movement_x = INT32_MAX; - for (auto* target_inst : target_cluster.get_inst_list()) { - int32_t origin_x = target_inst->get_coordi().get_x(); - if (target_inst == inst) { - inst_movement_x = std::abs(coordi_x - origin_x); - } - else { - movement_cost += std::abs(coordi_x - origin_x); - } - coordi_x += target_inst->get_shape().get_width(); - } - // Add Inst Coordi Movement Cost - int32_t inst_movement_y = std::abs(row_idx * _row_height - inst_shape.get_ll_y()); - int32_t inst_displacement = inst_movement_x + inst_movement_y; - movement_cost += inst_displacement; - - // Penalize violations of maximum movement constraints - if (inst_displacement > _config->get_max_displacement()) { - movement_cost += _database->get_lg_layout()->get_max_x(); - } - - // Replace cluster - if (!is_trial) { - replaceClusterInfo(target_cluster, is_record_cluster); - this->updateRemainLength(target_interval, -(inst->get_shape().get_width())); - - // debug - // if (target_interval->get_name() == "30_1") { - // LOG_INFO << "***placeRow***"; - // debugIntervalRemainLength(target_interval->get_name()); - // } - } - - return movement_cost; } - int32_t Abacus::searchNearestIntervalIndex(std::vector& segment_list, ipl::Rectangle& inst_shape) - { - if (segment_list.size() == 1) { - return 0; - } + // Arrange inst into interval + auto* target_interval = interval_list[row_interval_idx]; + AbacusCluster target_cluster = std::move(arrangeInstIntoIntervalCluster(inst, target_interval)); - int32_t prev_distance = INT32_MAX; - int32_t segment_idx = INT32_MAX; - for (size_t i = 0; i < segment_list.size(); i++) { - int32_t cur_distance + // Calculate cost + int32_t movement_cost = 0; + int32_t coordi_x = target_cluster.get_min_x(); + int32_t inst_movement_x = INT32_MAX; + for (auto* target_inst : target_cluster.get_inst_list()) { + int32_t origin_x = target_inst->get_coordi().get_x(); + if (target_inst == inst) { + inst_movement_x = std::abs(coordi_x - origin_x); + } else { + movement_cost += std::abs(coordi_x - origin_x); + } + coordi_x += target_inst->get_shape().get_width(); + } + // Add Inst Coordi Movement Cost + int32_t inst_movement_y = std::abs(row_idx * _row_height - inst_shape.get_ll_y()); + int32_t inst_displacement = inst_movement_x + inst_movement_y; + movement_cost += inst_displacement; + + // Penalize violations of maximum movement constraints + if (inst_displacement > _config->get_max_displacement()) { + movement_cost += _database->get_lg_layout()->get_max_x(); + } + + // Replace cluster + if (!is_trial) { + replaceClusterInfo(target_cluster, is_record_cluster); + this->updateRemainLength(target_interval, -(inst->get_shape().get_width())); + + // debug + // if (target_interval->get_name() == "30_1") { + // LOG_INFO << "***placeRow***"; + // debugIntervalRemainLength(target_interval->get_name()); + // } + } + + return movement_cost; +} + +int32_t Abacus::searchNearestIntervalIndex(std::vector& segment_list, ipl::Rectangle& inst_shape) +{ + if (segment_list.size() == 1) { + return 0; + } + + int32_t prev_distance = INT32_MAX; + int32_t segment_idx = INT32_MAX; + for (size_t i = 0; i < segment_list.size(); i++) { + int32_t cur_distance = calDistanceWithBox(inst_shape.get_ll_x(), inst_shape.get_ur_x(), segment_list[i]->get_min_x(), segment_list[i]->get_max_x()); - if (cur_distance > prev_distance) { - segment_idx = i - 1; + if (cur_distance > prev_distance) { + segment_idx = i - 1; + break; + } + if (cur_distance == 0) { + segment_idx = i; + break; + } + + prev_distance = cur_distance; + } + + return segment_idx; +} + +int32_t Abacus::calDistanceWithBox(int32_t min_x, int32_t max_x, int32_t box_min_x, int32_t box_max_x) +{ + if (max_x >= box_min_x && min_x <= box_max_x) { + return 0; + } else if (min_x > box_max_x) { + return (min_x - box_max_x); + } else if (max_x < box_min_x) { + return (box_min_x - max_x); + } else { + return INT32_MAX; + } +} + +int32_t Abacus::searchRemainSpaceSegIndex(std::vector& segment_list, ipl::Rectangle& inst_shape, + int32_t origin_index) +{ + int32_t segment_idx = origin_index; + // int32_t max_range = segment_list.size() - 1; + int32_t max_range = 2; + int32_t range = 1; + while (range <= max_range) { + int32_t r_idx = segment_idx; + if (r_idx + range < static_cast(segment_list.size())) { + r_idx += range; + int32_t interval_idx = segment_list[r_idx]->get_index(); + if (_interval_remain_length[interval_idx] >= inst_shape.get_width()) { + segment_idx = r_idx; break; } - if (cur_distance == 0) { - segment_idx = i; + } + int32_t l_idx = segment_idx; + if (l_idx - range >= 0) { + l_idx -= range; + int32_t interval_idx = segment_list[l_idx]->get_index(); + if (_interval_remain_length[interval_idx] >= inst_shape.get_width()) { + segment_idx = l_idx; break; } - - prev_distance = cur_distance; } - - return segment_idx; + range++; } + return segment_idx; +} - int32_t Abacus::calDistanceWithBox(int32_t min_x, int32_t max_x, int32_t box_min_x, int32_t box_max_x) - { - if (max_x >= box_min_x && min_x <= box_max_x) { - return 0; - } - else if (min_x > box_max_x) { - return (min_x - box_max_x); - } - else if (max_x < box_min_x) { - return (box_min_x - max_x); - } - else { - return INT32_MAX; - } - } +AbacusCluster Abacus::arrangeInstIntoIntervalCluster(ipl::LGInstance* inst, ipl::LGInterval* interval) +{ + auto inst_shape = std::move(inst->get_shape()); + AbacusCluster record_cluster; + auto* cur_cluster = _interval_cluster_root[interval->get_index()]; + auto* last_cluster = cur_cluster; + bool is_collapse = false; - int32_t Abacus::searchRemainSpaceSegIndex(std::vector& segment_list, ipl::Rectangle& inst_shape, - int32_t origin_index) - { - int32_t segment_idx = origin_index; - // int32_t max_range = segment_list.size() - 1; - int32_t max_range = 2; - int32_t range = 1; - while (range <= max_range) { - int32_t r_idx = segment_idx; - if (r_idx + range < static_cast(segment_list.size())) { - r_idx += range; - int32_t interval_idx = segment_list[r_idx]->get_index(); - if (_interval_remain_length[interval_idx] >= inst_shape.get_width()) { - segment_idx = r_idx; - break; - } + if (cur_cluster && (inst_shape.get_ur_x() < cur_cluster->get_min_x())) { + // should insert in the cluster + record_cluster = *cur_cluster; + record_cluster.insertInstance(inst); + legalizeCluster(record_cluster); + is_collapse = true; + } else { + while (cur_cluster) { + if (checkOverlapWithBox(inst_shape.get_ll_x(), inst_shape.get_ur_x(), cur_cluster->get_min_x(), cur_cluster->get_max_x())) { + record_cluster = *cur_cluster; + record_cluster.insertInstance(inst); + legalizeCluster(record_cluster); + is_collapse = true; + break; } - int32_t l_idx = segment_idx; - if (l_idx - range >= 0) { - l_idx -= range; - int32_t interval_idx = segment_list[l_idx]->get_index(); - if (_interval_remain_length[interval_idx] >= inst_shape.get_width()) { - segment_idx = l_idx; - break; - } - } - range++; - } - return segment_idx; - } - - AbacusCluster Abacus::arrangeInstIntoIntervalCluster(ipl::LGInstance* inst, ipl::LGInterval* interval) - { - auto inst_shape = std::move(inst->get_shape()); - AbacusCluster record_cluster; - auto* cur_cluster = _interval_cluster_root[interval->get_index()]; - auto* last_cluster = cur_cluster; - bool is_collapse = false; - - if (cur_cluster && (inst_shape.get_ur_x() < cur_cluster->get_min_x())) { - // should insert in the cluster - record_cluster = *cur_cluster; - record_cluster.insertInstance(inst); - legalizeCluster(record_cluster); - is_collapse = true; - } - else { - while (cur_cluster) { - if (checkOverlapWithBox(inst_shape.get_ll_x(), inst_shape.get_ur_x(), cur_cluster->get_min_x(), cur_cluster->get_max_x())) { + auto* back_cluster = findCluster(cur_cluster->get_back_cluster()); + if (back_cluster) { + // tmp fix bug. + if (inst_shape.get_ll_x() >= cur_cluster->get_max_x() && inst_shape.get_ur_x() <= back_cluster->get_min_x()) { record_cluster = *cur_cluster; record_cluster.insertInstance(inst); legalizeCluster(record_cluster); is_collapse = true; break; } - auto* back_cluster = findCluster(cur_cluster->get_back_cluster()); - if (back_cluster) { - // tmp fix bug. - if (inst_shape.get_ll_x() >= cur_cluster->get_max_x() && inst_shape.get_ur_x() <= back_cluster->get_min_x()) { - record_cluster = *cur_cluster; - record_cluster.insertInstance(inst); - legalizeCluster(record_cluster); - is_collapse = true; - break; - } - last_cluster = back_cluster; - } - cur_cluster = back_cluster; + last_cluster = back_cluster; } + cur_cluster = back_cluster; } - - if (!is_collapse) { - // Create new cluster - std::string cluster_name = obtainUniqueClusterName(inst->get_name()); - record_cluster = AbacusCluster(cluster_name); - - // auto* exist_cluster = findCluster(inst->get_name()); - // if (exist_cluster) { - // record_cluster = AbacusCluster(exist_cluster->get_name() + "_2024"); - // } - // else { - // record_cluster = AbacusCluster(inst->get_name()); - // } - // // record_cluster = AbacusCluster(inst->get_name()); - - record_cluster.add_inst(inst); - record_cluster.appendInst(inst); - record_cluster.set_belong_interval(interval); - if (last_cluster) { - record_cluster.set_front_cluster(last_cluster->get_name()); - } - legalizeCluster(record_cluster); - } - - return record_cluster; } - void Abacus::legalizeCluster(AbacusCluster& cluster) - { - arrangeClusterMinXCoordi(cluster); - int32_t cur_min_x, front_max_x, back_min_x; + if (!is_collapse) { + // Create new cluster + std::string cluster_name = obtainUniqueClusterName(inst->get_name()); + record_cluster = AbacusCluster(cluster_name); + + // auto* exist_cluster = findCluster(inst->get_name()); + // if (exist_cluster) { + // record_cluster = AbacusCluster(exist_cluster->get_name() + "_2024"); + // } + // else { + // record_cluster = AbacusCluster(inst->get_name()); + // } + // // record_cluster = AbacusCluster(inst->get_name()); + + record_cluster.add_inst(inst); + record_cluster.appendInst(inst); + record_cluster.set_belong_interval(interval); + if (last_cluster) { + record_cluster.set_front_cluster(last_cluster->get_name()); + } + legalizeCluster(record_cluster); + } + + return record_cluster; +} + +void Abacus::legalizeCluster(AbacusCluster& cluster) +{ + arrangeClusterMinXCoordi(cluster); + int32_t cur_min_x, front_max_x, back_min_x; + cur_min_x = cluster.get_min_x(); + front_max_x = obtainFrontMaxX(cluster); + + back_min_x = obtainBackMinX(cluster); + while ((cur_min_x < front_max_x) || (cur_min_x + cluster.get_total_width() > back_min_x)) { + while (cur_min_x < front_max_x) { + AbacusCluster front_cluster = *(this->findCluster(cluster.get_front_cluster())); + mergeWithPreviousCluster(cluster, front_cluster); + arrangeClusterMinXCoordi(cluster); + cur_min_x = cluster.get_min_x(); + front_max_x = obtainFrontMaxX(cluster); + + // front_cluster.appendCluster(cluster); + + // front_cluster.set_back_cluster(cluster.get_back_cluster()); + // arrangeClusterMinXCoordi(front_cluster); + // cur_min_x = front_cluster.get_min_x(); + // front_max_x = obtainFrontMaxX(front_cluster); + // cluster = front_cluster; + } + cur_min_x = cluster.get_min_x(); - front_max_x = obtainFrontMaxX(cluster); - back_min_x = obtainBackMinX(cluster); - while ((cur_min_x < front_max_x) || (cur_min_x + cluster.get_total_width() > back_min_x)) { - while (cur_min_x < front_max_x) { - - AbacusCluster front_cluster = *(this->findCluster(cluster.get_front_cluster())); - mergeWithPreviousCluster(cluster, front_cluster); - arrangeClusterMinXCoordi(cluster); - cur_min_x = cluster.get_min_x(); - front_max_x = obtainFrontMaxX(cluster); - - // front_cluster.appendCluster(cluster); - - // front_cluster.set_back_cluster(cluster.get_back_cluster()); - // arrangeClusterMinXCoordi(front_cluster); - // cur_min_x = front_cluster.get_min_x(); - // front_max_x = obtainFrontMaxX(front_cluster); - // cluster = front_cluster; - - } + while (cur_min_x + cluster.get_total_width() > back_min_x) { + auto* back_cluster = this->findCluster(cluster.get_back_cluster()); + mergeWithNextCluster(cluster, *back_cluster); + // cluster.appendCluster(*back_cluster); + // cluster.set_back_cluster(back_cluster->get_back_cluster()); + arrangeClusterMinXCoordi(cluster); cur_min_x = cluster.get_min_x(); back_min_x = obtainBackMinX(cluster); - while (cur_min_x + cluster.get_total_width() > back_min_x) { - auto* back_cluster = this->findCluster(cluster.get_back_cluster()); - mergeWithNextCluster(cluster, *back_cluster); - - // cluster.appendCluster(*back_cluster); - // cluster.set_back_cluster(back_cluster->get_back_cluster()); - arrangeClusterMinXCoordi(cluster); - cur_min_x = cluster.get_min_x(); - back_min_x = obtainBackMinX(cluster); - } - } - - } - - void Abacus::mergeWithPreviousCluster(AbacusCluster& cluster, AbacusCluster prev_cluster) { - AbacusCluster tmp_cluster(cluster.get_name()); - tmp_cluster.set_belong_interval(cluster.get_belong_interval()); - tmp_cluster.appendInstList(prev_cluster.get_inst_list()); - tmp_cluster.appendCluster(cluster); - - tmp_cluster.set_front_cluster(prev_cluster.get_front_cluster()); - tmp_cluster.set_back_cluster(cluster.get_back_cluster()); - - cluster = std::move(tmp_cluster); - } - - void Abacus::mergeWithNextCluster(AbacusCluster& cluster, AbacusCluster next_cluster) { - cluster.appendCluster(next_cluster); - cluster.set_back_cluster(next_cluster.get_back_cluster()); - } - - void Abacus::arrangeClusterMinXCoordi(AbacusCluster& cluster) - { - int32_t cluster_x = (cluster.get_weight_q() / cluster.get_weight_e()); - cluster_x = (cluster_x / _site_width) * _site_width; - - int32_t boundary_min_x = cluster.get_belong_interval()->get_min_x(); - int32_t boundary_max_x = cluster.get_belong_interval()->get_max_x(); - cluster_x < boundary_min_x ? cluster_x = boundary_min_x : cluster_x; - cluster_x + cluster.get_total_width() > boundary_max_x ? cluster_x = boundary_max_x - cluster.get_total_width() : cluster_x; - - if (cluster_x < boundary_min_x) { - std::cout << "Cluster width is out of interval capcity" << std::endl; - } - - cluster.set_min_x(cluster_x); - } - - int32_t Abacus::obtainFrontMaxX(AbacusCluster& cluster) - { - int32_t front_max_x = cluster.get_belong_interval()->get_min_x(); - auto* front_cluster = this->findCluster(cluster.get_front_cluster()); - if (front_cluster) { - front_max_x = front_cluster->get_max_x(); - } - return front_max_x; - } - - int32_t Abacus::obtainBackMinX(AbacusCluster& cluster) - { - int32_t back_min_x = cluster.get_belong_interval()->get_max_x(); - auto* back_cluster = this->findCluster(cluster.get_back_cluster()); - if (back_cluster) { - back_min_x = back_cluster->get_min_x(); - } - return back_min_x; - } - - bool Abacus::checkOverlapWithBox(int32_t min_x, int32_t max_x, int32_t box_min_x, int32_t box_max_x) - { - if (max_x > box_min_x && min_x < box_max_x) { - return true; - } - else { - return false; } } +} - void Abacus::replaceClusterInfo(AbacusCluster& modify_cluster, bool is_record_cluster) { - auto* origin_interval = modify_cluster.get_belong_interval(); - int32_t coordi_y = origin_interval->get_belong_row()->get_coordinate().get_y(); +void Abacus::mergeWithPreviousCluster(AbacusCluster& cluster, AbacusCluster prev_cluster) +{ + AbacusCluster tmp_cluster(cluster.get_name()); + tmp_cluster.set_belong_interval(cluster.get_belong_interval()); + tmp_cluster.appendInstList(prev_cluster.get_inst_list()); + tmp_cluster.appendCluster(cluster); - // record rollback info - RollbackInfo rollback_info; + tmp_cluster.set_front_cluster(prev_cluster.get_front_cluster()); + tmp_cluster.set_back_cluster(cluster.get_back_cluster()); - auto* cluster_ptr = this->findCluster(modify_cluster.get_name()); - std::string origin_back_cluster_name = ""; - if (!cluster_ptr) { - AbacusCluster* new_cluster = new AbacusCluster(modify_cluster); - this->insertCluster(new_cluster->get_name(), new_cluster); - cluster_ptr = new_cluster; + cluster = std::move(tmp_cluster); +} - if (is_record_cluster) { - rollback_info.addition_clusters.push_back(modify_cluster); - } - } - else { - if (is_record_cluster) { - rollback_info.origin_clusters.push_back(*cluster_ptr); - rollback_info.addition_clusters.push_back(modify_cluster); - } +void Abacus::mergeWithNextCluster(AbacusCluster& cluster, AbacusCluster next_cluster) +{ + cluster.appendCluster(next_cluster); + cluster.set_back_cluster(next_cluster.get_back_cluster()); +} - origin_back_cluster_name = cluster_ptr->get_back_cluster(); - *cluster_ptr = std::move(modify_cluster); - } +void Abacus::arrangeClusterMinXCoordi(AbacusCluster& cluster) +{ + int32_t cluster_x = (cluster.get_weight_q() / cluster.get_weight_e()); + cluster_x = (cluster_x / _site_width) * _site_width; - auto* origin_root = _interval_cluster_root[origin_interval->get_index()]; - std::string front_cluster_name = cluster_ptr->get_front_cluster(); - std::string back_cluster_name = cluster_ptr->get_back_cluster(); - auto* front_cluster = this->findCluster(front_cluster_name); - auto* back_cluster = this->findCluster(back_cluster_name); + int32_t boundary_min_x = cluster.get_belong_interval()->get_min_x(); + int32_t boundary_max_x = cluster.get_belong_interval()->get_max_x(); + cluster_x < boundary_min_x ? cluster_x = boundary_min_x : cluster_x; + cluster_x + cluster.get_total_width() > boundary_max_x ? cluster_x = boundary_max_x - cluster.get_total_width() : cluster_x; - // front cluster case - if (!origin_root && !front_cluster) { - // cur cluster is root - _interval_cluster_root[origin_interval->get_index()] = cluster_ptr; - } - else if (origin_root && !front_cluster) { - // from origin root to cur cluster need to erase. - auto* tmp_cluster = origin_root; - while (tmp_cluster->get_name() != cluster_ptr->get_name()) { - if (is_record_cluster) { - rollback_info.origin_clusters.push_back(*tmp_cluster); - } + if (cluster_x < boundary_min_x) { + std::cout << "Cluster width is out of interval capcity" << std::endl; + } - std::string delete_cluster_name = tmp_cluster->get_name(); - tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); - this->deleteCluster(delete_cluster_name); - if (!tmp_cluster) { - break; - } - } - _interval_cluster_root[origin_interval->get_index()] = cluster_ptr; - } - else if (!origin_root && front_cluster) { - LOG_ERROR << "Interval root is not recorded!!!"; - } - else { - // from front cluster to cur cluster need to erase. - auto* tmp_cluster = this->findCluster(front_cluster->get_back_cluster()); - while (tmp_cluster && (tmp_cluster->get_name() != cluster_ptr->get_name())) { - if (is_record_cluster) { - rollback_info.origin_clusters.push_back(*tmp_cluster); - } + cluster.set_min_x(cluster_x); +} - std::string delete_cluster_name = tmp_cluster->get_name(); - tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); - this->deleteCluster(delete_cluster_name); - } - } +int32_t Abacus::obtainFrontMaxX(AbacusCluster& cluster) +{ + int32_t front_max_x = cluster.get_belong_interval()->get_min_x(); + auto* front_cluster = this->findCluster(cluster.get_front_cluster()); + if (front_cluster) { + front_max_x = front_cluster->get_max_x(); + } + return front_max_x; +} - // back cluster case - auto* origin_back_cluster = this->findCluster(origin_back_cluster_name); - if (!back_cluster && !origin_back_cluster) { - // - } - else if (back_cluster && !origin_back_cluster) { - LOG_ERROR << "Back cluster is not recorded !!!"; - } - else if (!back_cluster && origin_back_cluster) { - auto* tmp_cluster = origin_back_cluster; - while (tmp_cluster) { - if (is_record_cluster) { - rollback_info.origin_clusters.push_back(*tmp_cluster); - } +int32_t Abacus::obtainBackMinX(AbacusCluster& cluster) +{ + int32_t back_min_x = cluster.get_belong_interval()->get_max_x(); + auto* back_cluster = this->findCluster(cluster.get_back_cluster()); + if (back_cluster) { + back_min_x = back_cluster->get_min_x(); + } + return back_min_x; +} - std::string delete_cluster_name = tmp_cluster->get_name(); - tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); - this->deleteCluster(delete_cluster_name); - } - } - else { - // from origin_back_cluster to back_cluster need to erase. - auto* tmp_cluster = origin_back_cluster; - while (tmp_cluster && (tmp_cluster->get_name() != back_cluster->get_name())) { - if (is_record_cluster) { - rollback_info.origin_clusters.push_back(*tmp_cluster); - } +bool Abacus::checkOverlapWithBox(int32_t min_x, int32_t max_x, int32_t box_min_x, int32_t box_max_x) +{ + if (max_x > box_min_x && min_x < box_max_x) { + return true; + } else { + return false; + } +} - std::string delete_cluster_name = tmp_cluster->get_name(); - tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); - this->deleteCluster(delete_cluster_name); - } +void Abacus::replaceClusterInfo(AbacusCluster& modify_cluster, bool is_record_cluster) +{ + auto* origin_interval = modify_cluster.get_belong_interval(); + int32_t coordi_y = origin_interval->get_belong_row()->get_coordinate().get_y(); + // record rollback info + RollbackInfo rollback_info; - } + auto* cluster_ptr = this->findCluster(modify_cluster.get_name()); + std::string origin_back_cluster_name = ""; + if (!cluster_ptr) { + AbacusCluster* new_cluster = new AbacusCluster(modify_cluster); + this->insertCluster(new_cluster->get_name(), new_cluster); + cluster_ptr = new_cluster; - if (front_cluster) { - front_cluster->set_back_cluster(cluster_ptr->get_name()); - } - if (back_cluster) { - back_cluster->set_front_cluster(cluster_ptr->get_name()); - } - - // update all inst info - int32_t coordi_x = cluster_ptr->get_min_x(); - for (auto* inst : cluster_ptr->get_inst_list()) { - _inst_belong_cluster[inst->get_index()] = cluster_ptr; - inst->updateCoordi(coordi_x, coordi_y); - coordi_x += inst->get_shape().get_width(); - } - - // record if (is_record_cluster) { - rollback_info.is_dirty = true; - _rollback_stack.push(rollback_info); + rollback_info.addition_clusters.push_back(modify_cluster); + } + } else { + if (is_record_cluster) { + rollback_info.origin_clusters.push_back(*cluster_ptr); + rollback_info.addition_clusters.push_back(modify_cluster); } + origin_back_cluster_name = cluster_ptr->get_back_cluster(); + *cluster_ptr = std::move(modify_cluster); } - // void Abacus::replaceClusterInfo(AbacusCluster& modify_cluster, bool is_record_cluster) - // { - // auto* origin_interval = modify_cluster.get_belong_interval(); - // int32_t coordi_y = origin_interval->get_belong_row()->get_coordinate().get_y(); + auto* origin_root = _interval_cluster_root[origin_interval->get_index()]; + std::string front_cluster_name = cluster_ptr->get_front_cluster(); + std::string back_cluster_name = cluster_ptr->get_back_cluster(); + auto* front_cluster = this->findCluster(front_cluster_name); + auto* back_cluster = this->findCluster(back_cluster_name); - // auto* cluster_ptr = this->findCluster(modify_cluster.get_name()); - // if (!cluster_ptr) { - // AbacusCluster* new_cluster = new AbacusCluster(std::move(modify_cluster)); - // auto inst_list = new_cluster->get_inst_list(); - // if (inst_list.size() > 1 || inst_list.size() == 0) { - // std::cout << "Cluster Inst is not correctly set" << std::endl; - // } + // front cluster case + if (!origin_root && !front_cluster) { + // cur cluster is root + _interval_cluster_root[origin_interval->get_index()] = cluster_ptr; + } else if (origin_root && !front_cluster) { + // from origin root to cur cluster need to erase. + auto* tmp_cluster = origin_root; + while (tmp_cluster->get_name() != cluster_ptr->get_name()) { + if (is_record_cluster) { + rollback_info.origin_clusters.push_back(*tmp_cluster); + } - // // cluster setting. - // _inst_belong_cluster[inst_list[0]->get_index()] = new_cluster; - // inst_list[0]->updateCoordi(new_cluster->get_min_x(), coordi_y); + std::string delete_cluster_name = tmp_cluster->get_name(); + tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); + this->deleteCluster(delete_cluster_name); + if (!tmp_cluster) { + break; + } + } + _interval_cluster_root[origin_interval->get_index()] = cluster_ptr; + } else if (!origin_root && front_cluster) { + LOG_ERROR << "Interval root is not recorded!!!"; + } else { + // from front cluster to cur cluster need to erase. + auto* tmp_cluster = this->findCluster(front_cluster->get_back_cluster()); + while (tmp_cluster && (tmp_cluster->get_name() != cluster_ptr->get_name())) { + if (is_record_cluster) { + rollback_info.origin_clusters.push_back(*tmp_cluster); + } - // this->insertCluster(new_cluster->get_name(), new_cluster); + std::string delete_cluster_name = tmp_cluster->get_name(); + tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); + this->deleteCluster(delete_cluster_name); + } + } - // // front cluster. - // std::string front_cluster_name = new_cluster->get_front_cluster(); - // std::string back_cluster_name = new_cluster->get_back_cluster(); - // auto* front_cluster = findCluster(front_cluster_name); - // auto* back_cluster = findCluster(back_cluster_name); - // if (front_cluster) { - // front_cluster->set_back_cluster(new_cluster->get_name()); + // back cluster case + auto* origin_back_cluster = this->findCluster(origin_back_cluster_name); + if (!back_cluster && !origin_back_cluster) { + // + } else if (back_cluster && !origin_back_cluster) { + LOG_ERROR << "Back cluster is not recorded !!!"; + } else if (!back_cluster && origin_back_cluster) { + auto* tmp_cluster = origin_back_cluster; + while (tmp_cluster) { + if (is_record_cluster) { + rollback_info.origin_clusters.push_back(*tmp_cluster); + } - // // assert - // if (back_cluster) { - // if (back_cluster_name != new_cluster->get_back_cluster()) { - // LOG_WARNING << "Unrecord back cluster!!!"; - // } - // } - // } - // else { - // if (_interval_cluster_root[origin_interval->get_index()]) { - // LOG_WARNING << "Unrecord front cluster!!!"; - // } - // else { - // _interval_cluster_root[origin_interval->get_index()] = new_cluster; - // } - // } + std::string delete_cluster_name = tmp_cluster->get_name(); + tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); + this->deleteCluster(delete_cluster_name); + } + } else { + // from origin_back_cluster to back_cluster need to erase. + auto* tmp_cluster = origin_back_cluster; + while (tmp_cluster && (tmp_cluster->get_name() != back_cluster->get_name())) { + if (is_record_cluster) { + rollback_info.origin_clusters.push_back(*tmp_cluster); + } - // if (back_cluster) { - // back_cluster->set_front_cluster(new_cluster->get_name()); - // } + std::string delete_cluster_name = tmp_cluster->get_name(); + tmp_cluster = this->findCluster(tmp_cluster->get_back_cluster()); + this->deleteCluster(delete_cluster_name); + } + } - // if (is_record_cluster) { - // RollbackInfo rollback_info; - // rollback_info.is_dirty = true; - // rollback_info.addition_clusters.push_back(*new_cluster); - // _rollback_stack.push(rollback_info); - // } - // return; - // } + if (front_cluster) { + front_cluster->set_back_cluster(cluster_ptr->get_name()); + } + if (back_cluster) { + back_cluster->set_front_cluster(cluster_ptr->get_name()); + } - // auto& origin_cluster = *(cluster_ptr); - // auto* origin_root = _interval_cluster_root[origin_interval->get_index()]; + // update all inst info + int32_t coordi_x = cluster_ptr->get_min_x(); + for (auto* inst : cluster_ptr->get_inst_list()) { + _inst_belong_cluster[inst->get_index()] = cluster_ptr; + inst->updateCoordi(coordi_x, coordi_y); + coordi_x += inst->get_shape().get_width(); + } - // // record rollback info - // RollbackInfo rollback_info; + // record + if (is_record_cluster) { + rollback_info.is_dirty = true; + _rollback_stack.push(rollback_info); + } +} - // // may be collapsing with front or back cluster - // AbacusCluster* front_origin = this->findCluster(origin_cluster.get_front_cluster()); - // AbacusCluster* front_modify = this->findCluster(modify_cluster.get_front_cluster()); - // while (front_origin != front_modify) { - // if (is_record_cluster && front_origin) { - // rollback_info.origin_clusters.push_back(*front_origin); - // } +// void Abacus::replaceClusterInfo(AbacusCluster& modify_cluster, bool is_record_cluster) +// { +// auto* origin_interval = modify_cluster.get_belong_interval(); +// int32_t coordi_y = origin_interval->get_belong_row()->get_coordinate().get_y(); - // if (front_origin == origin_root) { - // _interval_cluster_root[origin_interval->get_index()] = &origin_cluster; - // } +// auto* cluster_ptr = this->findCluster(modify_cluster.get_name()); +// if (!cluster_ptr) { +// AbacusCluster* new_cluster = new AbacusCluster(std::move(modify_cluster)); +// auto inst_list = new_cluster->get_inst_list(); +// if (inst_list.size() > 1 || inst_list.size() == 0) { +// std::cout << "Cluster Inst is not correctly set" << std::endl; +// } - // std::string delete_cluster = front_origin->get_name(); - // front_origin = this->findCluster(front_origin->get_front_cluster()); - // if (front_origin) { - // front_origin->set_back_cluster(origin_cluster.get_name()); - // } - // this->deleteCluster(delete_cluster); - // } +// // cluster setting. +// _inst_belong_cluster[inst_list[0]->get_index()] = new_cluster; +// inst_list[0]->updateCoordi(new_cluster->get_min_x(), coordi_y); - // // test - // if (is_record_cluster) { - // rollback_info.addition_clusters.push_back(modify_cluster); - // rollback_info.origin_clusters.push_back(origin_cluster); - // } +// this->insertCluster(new_cluster->get_name(), new_cluster); - // AbacusCluster* back_origin = this->findCluster(origin_cluster.get_back_cluster()); - // AbacusCluster* back_modify = this->findCluster(modify_cluster.get_back_cluster()); - // while (back_origin != back_modify) { - // if (is_record_cluster && back_origin) { - // rollback_info.origin_clusters.push_back(*back_origin); - // } +// // front cluster. +// std::string front_cluster_name = new_cluster->get_front_cluster(); +// std::string back_cluster_name = new_cluster->get_back_cluster(); +// auto* front_cluster = findCluster(front_cluster_name); +// auto* back_cluster = findCluster(back_cluster_name); +// if (front_cluster) { +// front_cluster->set_back_cluster(new_cluster->get_name()); - // std::string delete_cluster = back_origin->get_name(); +// // assert +// if (back_cluster) { +// if (back_cluster_name != new_cluster->get_back_cluster()) { +// LOG_WARNING << "Unrecord back cluster!!!"; +// } +// } +// } +// else { +// if (_interval_cluster_root[origin_interval->get_index()]) { +// LOG_WARNING << "Unrecord front cluster!!!"; +// } +// else { +// _interval_cluster_root[origin_interval->get_index()] = new_cluster; +// } +// } - // back_origin = this->findCluster(back_origin->get_back_cluster()); - // if (back_origin) { - // back_origin->set_front_cluster(origin_cluster.get_name()); - // } - // this->deleteCluster(delete_cluster); - // } +// if (back_cluster) { +// back_cluster->set_front_cluster(new_cluster->get_name()); +// } - // // update all inst info - // origin_cluster = std::move(modify_cluster); - // int32_t coordi_x = origin_cluster.get_min_x(); - // for (auto* inst : origin_cluster.get_inst_list()) { - // _inst_belong_cluster[inst->get_index()] = &origin_cluster; - // inst->updateCoordi(coordi_x, coordi_y); - // coordi_x += inst->get_shape().get_width(); - // } +// if (is_record_cluster) { +// RollbackInfo rollback_info; +// rollback_info.is_dirty = true; +// rollback_info.addition_clusters.push_back(*new_cluster); +// _rollback_stack.push(rollback_info); +// } +// return; +// } - // // final push rollback stack - // if (is_record_cluster) { - // rollback_info.is_dirty = true; - // _rollback_stack.push(rollback_info); - // } +// auto& origin_cluster = *(cluster_ptr); +// auto* origin_root = _interval_cluster_root[origin_interval->get_index()]; + +// // record rollback info +// RollbackInfo rollback_info; + +// // may be collapsing with front or back cluster +// AbacusCluster* front_origin = this->findCluster(origin_cluster.get_front_cluster()); +// AbacusCluster* front_modify = this->findCluster(modify_cluster.get_front_cluster()); +// while (front_origin != front_modify) { +// if (is_record_cluster && front_origin) { +// rollback_info.origin_clusters.push_back(*front_origin); +// } + +// if (front_origin == origin_root) { +// _interval_cluster_root[origin_interval->get_index()] = &origin_cluster; +// } + +// std::string delete_cluster = front_origin->get_name(); +// front_origin = this->findCluster(front_origin->get_front_cluster()); +// if (front_origin) { +// front_origin->set_back_cluster(origin_cluster.get_name()); +// } +// this->deleteCluster(delete_cluster); +// } + +// // test +// if (is_record_cluster) { +// rollback_info.addition_clusters.push_back(modify_cluster); +// rollback_info.origin_clusters.push_back(origin_cluster); +// } + +// AbacusCluster* back_origin = this->findCluster(origin_cluster.get_back_cluster()); +// AbacusCluster* back_modify = this->findCluster(modify_cluster.get_back_cluster()); +// while (back_origin != back_modify) { +// if (is_record_cluster && back_origin) { +// rollback_info.origin_clusters.push_back(*back_origin); +// } + +// std::string delete_cluster = back_origin->get_name(); + +// back_origin = this->findCluster(back_origin->get_back_cluster()); +// if (back_origin) { +// back_origin->set_front_cluster(origin_cluster.get_name()); +// } +// this->deleteCluster(delete_cluster); +// } + +// // update all inst info +// origin_cluster = std::move(modify_cluster); +// int32_t coordi_x = origin_cluster.get_min_x(); +// for (auto* inst : origin_cluster.get_inst_list()) { +// _inst_belong_cluster[inst->get_index()] = &origin_cluster; +// inst->updateCoordi(coordi_x, coordi_y); +// coordi_x += inst->get_shape().get_width(); +// } + +// // final push rollback stack +// if (is_record_cluster) { +// rollback_info.is_dirty = true; +// _rollback_stack.push(rollback_info); +// } +// } + +AbacusCluster* Abacus::findCluster(std::string cluster_name) +{ + if (cluster_name == "") { + return nullptr; + } + AbacusCluster* cluster = nullptr; + auto it = _cluster_map.find(cluster_name); + if (it != _cluster_map.end()) { + cluster = it->second; + } + + return cluster; +} + +void Abacus::insertCluster(std::string name, AbacusCluster* cluster) +{ + auto it = _cluster_map.find(name); + if (it != _cluster_map.end()) { + std::cout << "Cluster : " << name << " was added before" << std::endl; + } + _cluster_map.emplace(name, cluster); +} + +void Abacus::deleteCluster(std::string name) +{ + auto it = _cluster_map.find(name); + if (it != _cluster_map.end()) { + _cluster_map.erase(it); + } else { + std::cout << "Cluster: " << name << " has not been insert" << std::endl; + } +} + +void Abacus::updateRemainLength(ipl::LGInterval* interval, int32_t delta) +{ + int32_t cur_value = _interval_remain_length[interval->get_index()]; + _interval_remain_length[interval->get_index()] = cur_value + delta; +} + +void Abacus::splitTargetInst(ipl::LGInstance* inst, RollbackInfo& rollback_info) +{ + int32_t inst_width = inst->get_shape().get_width(); + auto* target_cluster = _inst_belong_cluster[inst->get_index()]; + ipl::LGInterval* target_interval = target_cluster->get_belong_interval(); + int32_t target_size = target_cluster->get_inst_list().size(); + + rollback_info.origin_clusters.push_back(*target_cluster); + + if (target_size == 1) { + auto* front_cluster = this->findCluster(target_cluster->get_front_cluster()); + auto* back_cluster = this->findCluster(target_cluster->get_back_cluster()); + if (!front_cluster && !back_cluster) { + // + } else if (!front_cluster && back_cluster) { + back_cluster->set_front_cluster(""); + } else if (front_cluster && !back_cluster) { + front_cluster->set_back_cluster(""); + } else { + front_cluster->set_back_cluster(back_cluster->get_name()); + back_cluster->set_front_cluster(front_cluster->get_name()); + } + + // move the root + if (_interval_cluster_root[target_interval->get_index()]->get_name() == target_cluster->get_name()) { + _interval_cluster_root[target_interval->get_index()] = back_cluster; + } + + deleteCluster(target_cluster->get_name()); + } else { + int32_t inst_idx = target_cluster->obtainInstIdx(inst); + if (inst_idx == -1) { + LOG_WARNING << "Inst is not in target cluster!!!"; + return; + } + + if ((inst_idx == 0) || (inst_idx == target_size - 1)) { + target_cluster->eraseTargetInstByIdx(inst_idx); + int32_t min_x = target_cluster->get_inst_list().front()->get_coordi().get_x(); + target_cluster->set_min_x(min_x); + target_cluster->updateAbacusInfo(); + } else if ((inst_idx > 0) && (inst_idx < target_size)) { + // split cluster + std::vector origin_inst_list = target_cluster->get_inst_list(); + std::vector new_inst_list(origin_inst_list.begin() + inst_idx + 1, origin_inst_list.end()); + target_cluster->eraseTargetInstByIdxPair(inst_idx, target_size - 1); + target_cluster->updateAbacusInfo(); + + // add new cluster + ipl::LGInstance* flag_inst = new_inst_list[0]; + + AbacusCluster* new_cluster; + std::string cluster_name = obtainUniqueClusterName(flag_inst->get_name()); + new_cluster = new AbacusCluster(cluster_name); + + // auto* exist_cluster = findCluster(flag_inst->get_name()); + // if (exist_cluster) { + // new_cluster = new AbacusCluster(exist_cluster->get_name() + "_2024"); + // } + // else { + // new_cluster = new AbacusCluster(flag_inst->get_name()); + // } + + new_cluster->appendInstList(new_inst_list); + new_cluster->set_min_x(flag_inst->get_coordi().get_x()); + // update inst to cluster + for (auto* inst : new_cluster->get_inst_list()) { + _inst_belong_cluster[inst->get_index()] = new_cluster; + } + + new_cluster->updateAbacusInfo(); + new_cluster->set_belong_interval(target_interval); + new_cluster->set_front_cluster(target_cluster->get_name()); + std::string back_cluster_name = target_cluster->get_back_cluster(); + auto* back_cluster = findCluster(back_cluster_name); + if (back_cluster) { + new_cluster->set_back_cluster(back_cluster_name); + back_cluster->set_front_cluster(new_cluster->get_name()); + } + target_cluster->set_back_cluster(new_cluster->get_name()); + + this->insertCluster(new_cluster->get_name(), new_cluster); + rollback_info.addition_clusters.push_back(*new_cluster); + } + rollback_info.addition_clusters.push_back(*target_cluster); + } + + _inst_belong_cluster[inst->get_index()] = nullptr; + _interval_remain_length[target_interval->get_index()] += inst_width; + + // debug + // if (target_interval->get_name() == "30_1") { + // LOG_INFO << "***Split***"; + // debugIntervalRemainLength(target_interval->get_name()); // } +} - AbacusCluster* Abacus::findCluster(std::string cluster_name) - { - if (cluster_name == "") { - return nullptr; - } - AbacusCluster* cluster = nullptr; - auto it = _cluster_map.find(cluster_name); - if (it != _cluster_map.end()) { - cluster = it->second; - } - - return cluster; - } - - void Abacus::insertCluster(std::string name, AbacusCluster* cluster) - { - auto it = _cluster_map.find(name); - if (it != _cluster_map.end()) { - std::cout << "Cluster : " << name << " was added before" << std::endl; - } - _cluster_map.emplace(name, cluster); - } - - void Abacus::deleteCluster(std::string name) - { - auto it = _cluster_map.find(name); - if (it != _cluster_map.end()) { - _cluster_map.erase(it); - } - else { - std::cout << "Cluster: " << name << " has not been insert" << std::endl; - } - } - - void Abacus::updateRemainLength(ipl::LGInterval* interval, int32_t delta) - { - int32_t cur_value = _interval_remain_length[interval->get_index()]; - _interval_remain_length[interval->get_index()] = cur_value + delta; - } - - void Abacus::splitTargetInst(ipl::LGInstance* inst, RollbackInfo& rollback_info) - { - int32_t inst_width = inst->get_shape().get_width(); - auto* target_cluster = _inst_belong_cluster[inst->get_index()]; - ipl::LGInterval* target_interval = target_cluster->get_belong_interval(); - int32_t target_size = target_cluster->get_inst_list().size(); - - rollback_info.origin_clusters.push_back(*target_cluster); - - if (target_size == 1) { - auto* front_cluster = this->findCluster(target_cluster->get_front_cluster()); - auto* back_cluster = this->findCluster(target_cluster->get_back_cluster()); - if (!front_cluster && !back_cluster) { - // - } - else if (!front_cluster && back_cluster) { - back_cluster->set_front_cluster(""); - } - else if (front_cluster && !back_cluster) { - front_cluster->set_back_cluster(""); - } - else { - front_cluster->set_back_cluster(back_cluster->get_name()); - back_cluster->set_front_cluster(front_cluster->get_name()); - } - - // move the root - if (_interval_cluster_root[target_interval->get_index()]->get_name() == target_cluster->get_name()) { - _interval_cluster_root[target_interval->get_index()] = back_cluster; - } - - deleteCluster(target_cluster->get_name()); - } - else { - int32_t inst_idx = target_cluster->obtainInstIdx(inst); - if (inst_idx == -1) { - LOG_WARNING << "Inst is not in target cluster!!!"; - return; - } - - if ((inst_idx == 0) || (inst_idx == target_size - 1)) { - target_cluster->eraseTargetInstByIdx(inst_idx); - int32_t min_x = target_cluster->get_inst_list().front()->get_coordi().get_x(); - target_cluster->set_min_x(min_x); - target_cluster->updateAbacusInfo(); - } - else if ((inst_idx > 0) && (inst_idx < target_size)) { - // split cluster - std::vector origin_inst_list = target_cluster->get_inst_list(); - std::vector new_inst_list(origin_inst_list.begin() + inst_idx + 1, origin_inst_list.end()); - target_cluster->eraseTargetInstByIdxPair(inst_idx, target_size - 1); - target_cluster->updateAbacusInfo(); - - // add new cluster - ipl::LGInstance* flag_inst = new_inst_list[0]; - - AbacusCluster* new_cluster; - std::string cluster_name = obtainUniqueClusterName(flag_inst->get_name()); - new_cluster = new AbacusCluster(cluster_name); - - // auto* exist_cluster = findCluster(flag_inst->get_name()); - // if (exist_cluster) { - // new_cluster = new AbacusCluster(exist_cluster->get_name() + "_2024"); - // } - // else { - // new_cluster = new AbacusCluster(flag_inst->get_name()); - // } - - new_cluster->appendInstList(new_inst_list); - new_cluster->set_min_x(flag_inst->get_coordi().get_x()); - // update inst to cluster - for(auto* inst : new_cluster->get_inst_list()){ - _inst_belong_cluster[inst->get_index()] = new_cluster; - } - - new_cluster->updateAbacusInfo(); - new_cluster->set_belong_interval(target_interval); - new_cluster->set_front_cluster(target_cluster->get_name()); - std::string back_cluster_name = target_cluster->get_back_cluster(); - auto* back_cluster = findCluster(back_cluster_name); - if (back_cluster) { - new_cluster->set_back_cluster(back_cluster_name); - back_cluster->set_front_cluster(new_cluster->get_name()); - } - target_cluster->set_back_cluster(new_cluster->get_name()); - - this->insertCluster(new_cluster->get_name(), new_cluster); - rollback_info.addition_clusters.push_back(*new_cluster); - } - rollback_info.addition_clusters.push_back(*target_cluster); - } - - _inst_belong_cluster[inst->get_index()] = nullptr; - _interval_remain_length[target_interval->get_index()] += inst_width; - - // debug - // if (target_interval->get_name() == "30_1") { - // LOG_INFO << "***Split***"; - // debugIntervalRemainLength(target_interval->get_name()); - // } - } - - bool Abacus::runRollback(bool clear_but_not_rollback) { - if (clear_but_not_rollback) { - // clear. - std::stack().swap(_rollback_stack); - return true; - } - - while (!_rollback_stack.empty()) { - auto& rollback_info = _rollback_stack.top(); - - if (!rollback_info.is_dirty) { - _rollback_stack.pop(); - continue; - } - - std::map> interval_to_clusters; - for (auto& cluster : rollback_info.addition_clusters) { - ipl::LGInterval* target_interval = cluster.get_belong_interval(); - auto it = interval_to_clusters.find(target_interval); - if (it != interval_to_clusters.end()) { - it->second.push_back(cluster); - } - else { - interval_to_clusters.emplace(target_interval, std::vector{cluster}); - } - } - - for (auto pair : interval_to_clusters) { - auto* target_interval = pair.first; - this->deleteTargetIntervalClusters(target_interval, pair.second); - - // interval to reset remain length. - this->reCalIntervalRemainLength(target_interval); - - // debug - // if (target_interval->get_name() == "30_1") { - // LOG_INFO << "***Rollback (delete) ***"; - // debugIntervalRemainLength(target_interval->get_name()); - // } - } - - interval_to_clusters.clear(); - - // sort the origin_clusters - std::sort(rollback_info.origin_clusters.begin(), rollback_info.origin_clusters.end(), - [](const AbacusCluster& a, const AbacusCluster& b) { - return a.get_min_x() < b.get_min_x(); - }); - - for (auto& cluster : rollback_info.origin_clusters) { - ipl::LGInterval* target_interval = cluster.get_belong_interval(); - auto it = interval_to_clusters.find(target_interval); - if (it != interval_to_clusters.end()) { - it->second.push_back(cluster); - } - else { - interval_to_clusters.emplace(target_interval, std::vector{cluster}); - } - } - - for (auto pair : interval_to_clusters) { - auto* target_interval = pair.first; - this->insertTargetIntervalClusters(target_interval, pair.second); - - // interval to reset remain length. - this->reCalIntervalRemainLength(target_interval); - - // debug - // if (target_interval->get_name() == "30_1") { - // LOG_INFO << "***Rollback (insert) ***"; - // debugIntervalRemainLength(target_interval->get_name()); - // } - } - - _rollback_stack.pop(); - } +bool Abacus::runRollback(bool clear_but_not_rollback) +{ + if (clear_but_not_rollback) { + // clear. + std::stack().swap(_rollback_stack); return true; } + while (!_rollback_stack.empty()) { + auto& rollback_info = _rollback_stack.top(); - void Abacus::deleteTargetIntervalClusters(ipl::LGInterval* interval, std::vector& cluster_list) { - int32_t interval_idx = interval->get_index(); - auto* interval_root = _interval_cluster_root[interval_idx]; + if (!rollback_info.is_dirty) { + _rollback_stack.pop(); + continue; + } - AbacusCluster* prev_cluster = nullptr; - AbacusCluster* cur_cluster = interval_root; - AbacusCluster* back_cluster = nullptr; - - while (cur_cluster) { - std::string back_cluster_name = cur_cluster->get_back_cluster(); - back_cluster = this->findCluster(back_cluster_name); - std::string prev_cluster_name = cur_cluster->get_front_cluster(); - prev_cluster = this->findCluster(prev_cluster_name); - - bool changed_flag = false; - for (auto& target_cluster : cluster_list) { - if (cur_cluster->get_name() == target_cluster.get_name()) { - // change topo of cur_cluster - if (!prev_cluster && !back_cluster) { - _interval_cluster_root[interval_idx] = nullptr; - } - else if (prev_cluster && !back_cluster) { - prev_cluster->set_back_cluster(""); - } - else if (!prev_cluster && back_cluster) { - _interval_cluster_root[interval_idx] = back_cluster; - back_cluster->set_front_cluster(""); - } - else { - prev_cluster->set_back_cluster(back_cluster_name); - back_cluster->set_front_cluster(prev_cluster_name); - } - changed_flag = true; - this->deleteCluster(cur_cluster->get_name()); - break; - } - } - - if (changed_flag) { - changed_flag = false; - cur_cluster = back_cluster; - } - else { - cur_cluster = back_cluster; + std::map> interval_to_clusters; + for (auto& cluster : rollback_info.addition_clusters) { + ipl::LGInterval* target_interval = cluster.get_belong_interval(); + auto it = interval_to_clusters.find(target_interval); + if (it != interval_to_clusters.end()) { + it->second.push_back(cluster); + } else { + interval_to_clusters.emplace(target_interval, std::vector{cluster}); } } + + for (auto pair : interval_to_clusters) { + auto* target_interval = pair.first; + this->deleteTargetIntervalClusters(target_interval, pair.second); + + // interval to reset remain length. + this->reCalIntervalRemainLength(target_interval); + + // debug + // if (target_interval->get_name() == "30_1") { + // LOG_INFO << "***Rollback (delete) ***"; + // debugIntervalRemainLength(target_interval->get_name()); + // } + } + + interval_to_clusters.clear(); + + // sort the origin_clusters + std::sort(rollback_info.origin_clusters.begin(), rollback_info.origin_clusters.end(), + [](const AbacusCluster& a, const AbacusCluster& b) { return a.get_min_x() < b.get_min_x(); }); + + for (auto& cluster : rollback_info.origin_clusters) { + ipl::LGInterval* target_interval = cluster.get_belong_interval(); + auto it = interval_to_clusters.find(target_interval); + if (it != interval_to_clusters.end()) { + it->second.push_back(cluster); + } else { + interval_to_clusters.emplace(target_interval, std::vector{cluster}); + } + } + + for (auto pair : interval_to_clusters) { + auto* target_interval = pair.first; + this->insertTargetIntervalClusters(target_interval, pair.second); + + // interval to reset remain length. + this->reCalIntervalRemainLength(target_interval); + + // debug + // if (target_interval->get_name() == "30_1") { + // LOG_INFO << "***Rollback (insert) ***"; + // debugIntervalRemainLength(target_interval->get_name()); + // } + } + + _rollback_stack.pop(); } + return true; +} +void Abacus::deleteTargetIntervalClusters(ipl::LGInterval* interval, std::vector& cluster_list) +{ + int32_t interval_idx = interval->get_index(); + auto* interval_root = _interval_cluster_root[interval_idx]; - void Abacus::insertTargetIntervalClusters(ipl::LGInterval* interval, std::vector& cluster_list) { - std::vector> chain_list; - // cluster_list -> chain_list, chain is ordered outside. - int chain_idx = 0; - chain_list.push_back(std::vector{cluster_list[0]}); - for (size_t i = 0, j = i + 1; i < cluster_list.size(); i++, j++) { - if (j >= cluster_list.size()) { - // + AbacusCluster* prev_cluster = nullptr; + AbacusCluster* cur_cluster = interval_root; + AbacusCluster* back_cluster = nullptr; + + while (cur_cluster) { + std::string back_cluster_name = cur_cluster->get_back_cluster(); + back_cluster = this->findCluster(back_cluster_name); + std::string prev_cluster_name = cur_cluster->get_front_cluster(); + prev_cluster = this->findCluster(prev_cluster_name); + + bool changed_flag = false; + for (auto& target_cluster : cluster_list) { + if (cur_cluster->get_name() == target_cluster.get_name()) { + // change topo of cur_cluster + if (!prev_cluster && !back_cluster) { + _interval_cluster_root[interval_idx] = nullptr; + } else if (prev_cluster && !back_cluster) { + prev_cluster->set_back_cluster(""); + } else if (!prev_cluster && back_cluster) { + _interval_cluster_root[interval_idx] = back_cluster; + back_cluster->set_front_cluster(""); + } else { + prev_cluster->set_back_cluster(back_cluster_name); + back_cluster->set_front_cluster(prev_cluster_name); + } + changed_flag = true; + this->deleteCluster(cur_cluster->get_name()); break; } - std::string back_name = cluster_list[i].get_back_cluster(); - if (back_name == cluster_list[j].get_name()) { - chain_list[chain_idx].push_back(cluster_list[j]); - } - else { - chain_list.push_back(std::vector{cluster_list[j]}); - chain_idx++; - } } - for (auto& chain : chain_list) { - std::vector cluster_chain; - for (auto& cluster : chain) { - AbacusCluster* c = new AbacusCluster(cluster.get_name()); - // need to set coordi - *c = cluster; - - // update inst coordi and change inst-cluster connection. - int32_t coordi_y = c->get_belong_interval()->get_belong_row()->get_coordinate().get_y(); - int32_t coordi_x = c->get_min_x(); - for (auto* inst : c->get_inst_list()) { - inst->updateCoordi(coordi_x, coordi_y); - coordi_x += inst->get_shape().get_width(); - _inst_belong_cluster[inst->get_index()] = c; - } - cluster_chain.push_back(c); - } - insertClusterChainIntoInterval(interval, cluster_chain); + if (changed_flag) { + changed_flag = false; + cur_cluster = back_cluster; + } else { + cur_cluster = back_cluster; } + } +} +void Abacus::insertTargetIntervalClusters(ipl::LGInterval* interval, std::vector& cluster_list) +{ + std::vector> chain_list; + // cluster_list -> chain_list, chain is ordered outside. + int chain_idx = 0; + chain_list.push_back(std::vector{cluster_list[0]}); + for (size_t i = 0, j = i + 1; i < cluster_list.size(); i++, j++) { + if (j >= cluster_list.size()) { + // + break; + } + std::string back_name = cluster_list[i].get_back_cluster(); + if (back_name == cluster_list[j].get_name()) { + chain_list[chain_idx].push_back(cluster_list[j]); + } else { + chain_list.push_back(std::vector{cluster_list[j]}); + chain_idx++; + } } - void Abacus::insertClusterChainIntoInterval(ipl::LGInterval* interval, std::vector& cluster_chain) { - int32_t interval_idx = interval->get_index(); - auto* interval_root = _interval_cluster_root[interval_idx]; + for (auto& chain : chain_list) { + std::vector cluster_chain; + for (auto& cluster : chain) { + AbacusCluster* c = new AbacusCluster(cluster.get_name()); + // need to set coordi + *c = cluster; - AbacusCluster* c_head = cluster_chain[0]; - AbacusCluster* c_tail = cluster_chain.back(); + // update inst coordi and change inst-cluster connection. + int32_t coordi_y = c->get_belong_interval()->get_belong_row()->get_coordinate().get_y(); + int32_t coordi_x = c->get_min_x(); + for (auto* inst : c->get_inst_list()) { + inst->updateCoordi(coordi_x, coordi_y); + coordi_x += inst->get_shape().get_width(); + _inst_belong_cluster[inst->get_index()] = c; + } + cluster_chain.push_back(c); + } + insertClusterChainIntoInterval(interval, cluster_chain); + } +} - auto* cur_cluster = interval_root; - if (!cur_cluster) { +void Abacus::insertClusterChainIntoInterval(ipl::LGInterval* interval, std::vector& cluster_chain) +{ + int32_t interval_idx = interval->get_index(); + auto* interval_root = _interval_cluster_root[interval_idx]; + + AbacusCluster* c_head = cluster_chain[0]; + AbacusCluster* c_tail = cluster_chain.back(); + + auto* cur_cluster = interval_root; + if (!cur_cluster) { + for (auto* c : cluster_chain) { + this->insertCluster(c->get_name(), c); + } + _interval_cluster_root[interval_idx] = c_head; + return; + } + + // front case + if (c_head->get_min_x() < cur_cluster->get_min_x()) { + for (auto* c : cluster_chain) { + this->insertCluster(c->get_name(), c); + } + _interval_cluster_root[interval_idx] = c_head; + cur_cluster->set_front_cluster(c_tail->get_name()); + return; + } + + while (cur_cluster) { + // not front case + std::string back_cluster_name = cur_cluster->get_back_cluster(); + auto* back_cluster = this->findCluster(back_cluster_name); + if (!back_cluster) { + // direct add chain list. + cur_cluster->set_back_cluster(c_head->get_name()); for (auto* c : cluster_chain) { this->insertCluster(c->get_name(), c); } - _interval_cluster_root[interval_idx] = c_head; - return; - } - - // front case - if (c_head->get_min_x() < cur_cluster->get_min_x()) { - for (auto* c : cluster_chain) { - this->insertCluster(c->get_name(), c); - } - _interval_cluster_root[interval_idx] = c_head; - cur_cluster->set_front_cluster(c_tail->get_name()); - return; - } - - while (cur_cluster) { - // not front case - std::string back_cluster_name = cur_cluster->get_back_cluster(); - auto* back_cluster = this->findCluster(back_cluster_name); - if (!back_cluster) { - // direct add chain list. + break; + } else { + if (c_head->get_min_x() >= cur_cluster->get_max_x() && c_head->get_max_x() <= back_cluster->get_min_x()) { + // insert chain list. cur_cluster->set_back_cluster(c_head->get_name()); + back_cluster->set_front_cluster(c_tail->get_name()); for (auto* c : cluster_chain) { this->insertCluster(c->get_name(), c); } break; } - else { - if (c_head->get_min_x() >= cur_cluster->get_max_x() && c_head->get_max_x() <= back_cluster->get_min_x()) { - // insert chain list. - cur_cluster->set_back_cluster(c_head->get_name()); - back_cluster->set_front_cluster(c_tail->get_name()); - for (auto* c : cluster_chain) { - this->insertCluster(c->get_name(), c); - } - break; - } - cur_cluster = back_cluster; - } - - } - return; - } - - void Abacus::reCalIntervalRemainLength(ipl::LGInterval* interval) { - int32_t interval_idx = interval->get_index(); - int32_t remain_length = (interval->get_max_x() - interval->get_min_x()); - - AbacusCluster* interval_root = _interval_cluster_root[interval_idx]; - AbacusCluster* cur_cluster = interval_root; - AbacusCluster* back_cluster = nullptr; - while (cur_cluster) { - std::string back_cluster_name = cur_cluster->get_back_cluster(); - back_cluster = this->findCluster(back_cluster_name); - - int32_t cluster_width = cur_cluster->get_total_width(); - remain_length -= cluster_width; cur_cluster = back_cluster; } - _interval_remain_length[interval_idx] = remain_length; + } + return; +} + +void Abacus::reCalIntervalRemainLength(ipl::LGInterval* interval) +{ + int32_t interval_idx = interval->get_index(); + int32_t remain_length = (interval->get_max_x() - interval->get_min_x()); + + AbacusCluster* interval_root = _interval_cluster_root[interval_idx]; + AbacusCluster* cur_cluster = interval_root; + AbacusCluster* back_cluster = nullptr; + while (cur_cluster) { + std::string back_cluster_name = cur_cluster->get_back_cluster(); + back_cluster = this->findCluster(back_cluster_name); + + int32_t cluster_width = cur_cluster->get_total_width(); + remain_length -= cluster_width; + cur_cluster = back_cluster; + } + _interval_remain_length[interval_idx] = remain_length; +} + +void Abacus::debugIntervalRemainLength(std::string interval_name) +{ + auto* interval = _database->get_lg_layout()->find_interval(interval_name); + int32_t interval_idx = interval->get_index(); + int32_t remain_length = (interval->get_max_x() - interval->get_min_x()); + + AbacusCluster* interval_root = _interval_cluster_root[interval_idx]; + AbacusCluster* cur_cluster = interval_root; + AbacusCluster* back_cluster = nullptr; + + std::stringstream info; + info << interval_name << " --- "; + while (cur_cluster) { + info << cur_cluster->get_name() << "(" << cur_cluster->get_inst_list().size() << "," << cur_cluster->get_total_width() << ")" + << " -> "; + + std::string back_cluster_name = cur_cluster->get_back_cluster(); + back_cluster = this->findCluster(back_cluster_name); + int32_t cluster_width = cur_cluster->get_total_width(); + remain_length -= cluster_width; + cur_cluster = back_cluster; } - void Abacus::debugIntervalRemainLength(std::string interval_name) { - auto* interval = _database->get_lg_layout()->find_interval(interval_name); - int32_t interval_idx = interval->get_index(); - int32_t remain_length = (interval->get_max_x() - interval->get_min_x()); + info << std::endl; + info << "Expect remain_length: " << remain_length << " ; " + << "Actual remain_length: " << _interval_remain_length[interval_idx] << std::endl; + LOG_INFO << info.str(); +} - AbacusCluster* interval_root = _interval_cluster_root[interval_idx]; - AbacusCluster* cur_cluster = interval_root; - AbacusCluster* back_cluster = nullptr; +std::string Abacus::obtainUniqueClusterName(std::string origin_name) +{ + std::string unique_name = origin_name; + auto* cluster = this->findCluster(unique_name); + while (cluster) { + unique_name += "_2024"; + cluster = this->findCluster(unique_name); + } + return unique_name; +} - std::stringstream info; - info << interval_name << " --- "; - while (cur_cluster) { - info << cur_cluster->get_name() << "(" << cur_cluster->get_inst_list().size() << "," << cur_cluster->get_total_width() << ")" << " -> "; - - std::string back_cluster_name = cur_cluster->get_back_cluster(); - back_cluster = this->findCluster(back_cluster_name); - int32_t cluster_width = cur_cluster->get_total_width(); - remain_length -= cluster_width; - cur_cluster = back_cluster; - } - - info << std::endl; - info << "Expect remain_length: " << remain_length << " ; " << "Actual remain_length: " << _interval_remain_length[interval_idx] << std::endl; - LOG_INFO << info.str(); +int Abacus::get_best_cost_row(ipl::LGInstance* inst) +{ + if (_database->get_lg_layout()->get_row_num() <= 0) { + return INT32_MAX; } - std::string Abacus::obtainUniqueClusterName(std::string origin_name){ - std::string unique_name = origin_name; - auto* cluster = this->findCluster(unique_name); - while(cluster){ - unique_name += "_2024"; - cluster = this->findCluster(unique_name); - } - return unique_name; + std::vector> row_costs(_database->get_lg_layout()->get_row_num()); +#pragma omp parallel for + for (int32_t row_idx = 0; row_idx < _database->get_lg_layout()->get_row_num(); row_idx++) { + int32_t cost = placeRow(inst, row_idx, true, false); + row_costs[row_idx] = std::make_pair(row_idx, cost); } + /// 升序排列 + std::sort(row_costs.begin(), row_costs.end(), [](std::pair& a, std::pair& b) { return a.second < b.second; }); + + /// best cost = 1st row_cost + return row_costs[0].first; +} + } // namespace ieda_solver \ No newline at end of file diff --git a/src/solver/legalization/method/abacus/Abacus.hh b/src/solver/legalization/method/abacus/Abacus.hh index 899b50168..675147ed8 100644 --- a/src/solver/legalization/method/abacus/Abacus.hh +++ b/src/solver/legalization/method/abacus/Abacus.hh @@ -18,8 +18,8 @@ #pragma once #include -#include #include +#include #include "AbacusCluster.hh" #include "LGMethodInterface.hh" @@ -70,7 +70,7 @@ class Abacus : public LGMethodInterface int32_t _row_height = -1; int32_t _site_width = -1; - + std::stack _rollback_stack; void pickAndSortMovableInstList(std::vector& movable_inst_list); @@ -102,6 +102,8 @@ class Abacus : public LGMethodInterface std::string obtainUniqueClusterName(std::string origin_name); void debugIntervalRemainLength(std::string interval_name); + + int get_best_cost_row(ipl::LGInstance* inst); }; } // namespace ieda_solver