diff --git a/src/operation/iIR/api/CMakeLists.txt b/src/operation/iIR/api/CMakeLists.txt index 65d696844..4d492ec48 100644 --- a/src/operation/iIR/api/CMakeLists.txt +++ b/src/operation/iIR/api/CMakeLists.txt @@ -13,4 +13,4 @@ include_directories(${EIGEN3_INCLUDE_DIRS}) aux_source_directory(./ SRC) add_library(iir-api ${SRC} ) -target_link_libraries(iir-api ir_solver ir-matrix Eigen3::Eigen pg-netlist) +target_link_libraries(iir-api ir_solver ir-matrix Eigen3::Eigen pg-netlist spef) diff --git a/src/operation/iIR/api/iIR.cc b/src/operation/iIR/api/iIR.cc index 8bd9ba33b..b61ce3399 100644 --- a/src/operation/iIR/api/iIR.cc +++ b/src/operation/iIR/api/iIR.cc @@ -24,15 +24,98 @@ */ #include "iIR.hh" +#include #include #include +#include #include +#include +#include "SpefParser.hh" +#include "iir-rust/IRRustC.hh" #include "ir-solver/IRSolver.hh" #include "log/Log.hh" #include "matrix/IRMatrix.hh" #include "usage/usage.hh" +namespace { + +template +RustVec MakeRustVec(std::vector& values) { + RustVec rust_vec; + rust_vec.data = values.data(); + rust_vec.len = values.size(); + rust_vec.cap = values.capacity(); + rust_vec.type_size = sizeof(T); + return rust_vec; +} + +struct RustSpefNetStorage { + std::vector conns; + std::vector caps; + std::vector ress; +}; + +const void* CreateRcDataFromSpefExchange(const ista::spef::Exchange& exchange) { + std::vector storage; + storage.reserve(exchange.nets.size()); + + std::vector rust_nets; + rust_nets.reserve(exchange.nets.size()); + + for (const auto& spef_net : exchange.nets) { + auto& net_storage = storage.emplace_back(); + net_storage.conns.reserve(spef_net.conns.size()); + net_storage.caps.reserve(spef_net.caps.size()); + net_storage.ress.reserve(spef_net.ress.size()); + + for (const auto& conn : spef_net.conns) { + net_storage.conns.push_back( + RustSpefConn{conn.pin_port_name.c_str(), + conn.conn_type == ista::spef::ConnectionType::kExternal}); + } + + for (const auto& cap : spef_net.caps) { + net_storage.caps.push_back( + RustSpefResCap{cap.node1.c_str(), cap.node2.c_str(), + cap.res_or_cap}); + } + + for (const auto& res : spef_net.ress) { + net_storage.ress.push_back( + RustSpefResCap{res.node1.c_str(), res.node2.c_str(), + res.res_or_cap}); + } + + rust_nets.push_back(RustSpefNet{spef_net.name.c_str(), + MakeRustVec(net_storage.conns), + MakeRustVec(net_storage.caps), + MakeRustVec(net_storage.ress)}); + } + + return create_rc_data_from_spef(MakeRustVec(rust_nets)); +} + +const void* ReadSpefRcData(std::string_view spef_file_path) { + ista::spef::SpefReader spef_parser; + const std::string spef_path(spef_file_path); + if (!spef_parser.read(spef_path)) { + LOG_ERROR << "read spef file " << spef_path << " failed"; + return nullptr; + } + + spef_parser.expandName(); + auto* spef_file = spef_parser.getSpefFile(); + if (spef_file == nullptr) { + LOG_ERROR << "read spef file " << spef_path << " produced no SPEF data"; + return nullptr; + } + + return CreateRcDataFromSpefExchange(*spef_file); +} + +} // namespace + namespace iir { /** @@ -53,10 +136,19 @@ unsigned iIR::init() { * @return */ unsigned iIR::readSpef(std::string_view spef_file_path) { - _rc_data = read_spef(spef_file_path.data()); - return 1; + _rc_data = ReadSpefRcData(spef_file_path); + return _rc_data == nullptr ? 0 : 1; }; +void BuildMatrixFromRawData(const char* c_inst_power_path, + const char* c_power_net_spef) { + auto* rc_data = ReadSpefRcData(c_power_net_spef); + if (rc_data == nullptr) { + return; + } + build_matrices_from_rc_data(c_inst_power_path, rc_data); +} + /** * @brief read instance power db file to build current vector. * diff --git a/src/operation/iIR/source/iir-rust/IRRustC.cc b/src/operation/iIR/source/iir-rust/IRRustC.cc index b72b52f5c..b41e3aede 100644 --- a/src/operation/iIR/source/iir-rust/IRRustC.cc +++ b/src/operation/iIR/source/iir-rust/IRRustC.cc @@ -9,15 +9,3 @@ * */ #include "IRRustC.hh" - -namespace iir { - -void BuildMatrixFromRawData(const char *c_inst_power_path, - const char *c_power_net_spef) { - // auto matrix_data = build_matrix_from_raw_data(c_inst_power_path, c_power_net_spef); - // fix warning: variable 'matrix_data' set but not used [-Wunused-but-set-variable] - build_matrix_from_raw_data(c_inst_power_path, c_power_net_spef); - -} - -} // namespace iir diff --git a/src/operation/iIR/source/iir-rust/IRRustC.hh b/src/operation/iIR/source/iir-rust/IRRustC.hh index 6a52c301f..c025a01a7 100644 --- a/src/operation/iIR/source/iir-rust/IRRustC.hh +++ b/src/operation/iIR/source/iir-rust/IRRustC.hh @@ -26,6 +26,24 @@ typedef struct RustNetConductanceData { const void *ir_net_raw_ptr; } RustNetConductanceData; +typedef struct RustSpefConn { + const char *name; + bool is_external; +} RustSpefConn; + +typedef struct RustSpefResCap { + const char *node1; + const char *node2; + double value; +} RustSpefResCap; + +typedef struct RustSpefNet { + const char *name; + struct RustVec conns; + struct RustVec caps; + struct RustVec ress; +} RustSpefNet; + // iterator for access hash map void *create_hashmap_iterator(void *hashmap); bool hashmap_iterator_next(void *iterator, uintptr_t *out_key, double *out_value); @@ -33,7 +51,7 @@ void destroy_hashmap_iterator(void *iterator); void init_iir(void); -const void *read_spef(const char *c_power_net_spef); +const void *create_rc_data_from_spef(struct RustVec spef_nets); const void *create_pg_node(const void *c_pg_netlist, const void *c_pg_node); @@ -61,11 +79,8 @@ double get_sum_resistance(const void *c_rc_data, const char *c_net_name); struct RustNetConductanceData build_one_net_conductance_matrix_data( const void *c_rc_data, const char *c_net_name); -/** - * Build RC matrix and current vector data. - */ -struct RustVec build_matrix_from_raw_data(const char *c_inst_power_path, - const char *c_power_net_spef); +void build_matrices_from_rc_data(const char *c_inst_power_path, + const void *c_rc_data); /** * Build one net instance current vector. @@ -85,4 +100,4 @@ namespace iir { void BuildMatrixFromRawData(const char *c_inst_power_path, const char *c_power_net_spef); -} \ No newline at end of file +} diff --git a/src/operation/iIR/source/iir-rust/iir/Cargo.lock b/src/operation/iIR/source/iir-rust/iir/Cargo.lock index a872f0f18..e8f0e0a6e 100644 --- a/src/operation/iIR/source/iir-rust/iir/Cargo.lock +++ b/src/operation/iIR/source/iir-rust/iir/Cargo.lock @@ -37,12 +37,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - [[package]] name = "approx" version = "0.3.2" @@ -81,15 +75,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "bumpalo" version = "3.15.4" @@ -171,15 +156,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -205,16 +181,6 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "csv" version = "1.3.0" @@ -236,16 +202,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "either" version = "1.10.0" @@ -281,16 +237,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -357,7 +303,6 @@ dependencies = [ "env_logger", "log", "serde", - "spef-parser", "sprs", ] @@ -511,51 +456,6 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" -[[package]] -name = "pest" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "pest_meta" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "proc-macro2" version = "1.0.70" @@ -688,35 +588,12 @@ dependencies = [ "serde", ] -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "spef-parser" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cdeb2bb95a11430078d214647d2c0117b53142bd8febc92032c9f133923b15" -dependencies = [ - "anyhow", - "cbindgen", - "pest", - "pest_derive", -] - [[package]] name = "sprs" version = "0.11.1" @@ -788,26 +665,6 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "toml" version = "0.5.11" @@ -817,30 +674,12 @@ dependencies = [ "serde", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "wasm-bindgen" version = "0.2.92" diff --git a/src/operation/iIR/source/iir-rust/iir/Cargo.toml b/src/operation/iIR/source/iir-rust/iir/Cargo.toml index 024519678..9f7c57d14 100644 --- a/src/operation/iIR/source/iir-rust/iir/Cargo.toml +++ b/src/operation/iIR/source/iir-rust/iir/Cargo.toml @@ -23,11 +23,9 @@ rustflags = ["-Z", "threads=8"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -spef = { package = "spef-parser", version = "0.2.5" } csv = "1.1.6" serde = { version = "1.0.193", features = ["derive"] } env_logger = "0.10.0" log = "0.4.14" chrono = "0.4.19" sprs = "0.11.1" - diff --git a/src/operation/iIR/source/iir-rust/iir/dist/iIR-Rust.h b/src/operation/iIR/source/iir-rust/iir/dist/iIR-Rust.h index 51022a0c5..d8a69a4fa 100644 --- a/src/operation/iIR/source/iir-rust/iir/dist/iIR-Rust.h +++ b/src/operation/iIR/source/iir-rust/iir/dist/iIR-Rust.h @@ -67,8 +67,6 @@ bool hashmap_iterator_next(struct HashMapIterator *iterator, uintptr_t *out_key, void destroy_hashmap_iterator(struct HashMapIterator *iterator); -const void *read_spef(const char *c_power_net_spef); - /** * create power ground node. */ @@ -89,6 +87,8 @@ const void *create_pg_netlist(const char *c_power_net_name); */ const void *create_rc_data(const void *c_pg_netlist_ptr, uintptr_t len); +const void *create_rc_data_from_spef(struct RustVec c_spef_nets); + double get_sum_resistance(const void *c_rc_data, const char *c_net_name); struct RustNetConductanceData build_one_net_conductance_matrix_data(const void *c_rc_data, @@ -117,8 +117,4 @@ struct RustVec get_instance_node_ids(const void *c_rc_data, const char *c_net_na const char *get_instance_name(const void *c_rc_data, const char *c_net_name, uintptr_t node_id); -/** - * Build RC matrix and current vector data. - */ -struct RustVec build_matrix_from_raw_data(const char *c_inst_power_path, - const char *c_power_net_spef); +void build_matrices_from_rc_data(const char *c_inst_power_path, const void *c_rc_data); diff --git a/src/operation/iIR/source/iir-rust/iir/src/main.rs b/src/operation/iIR/source/iir-rust/iir/src/main.rs index 180f5ec05..188ed74d8 100644 --- a/src/operation/iIR/source/iir-rust/iir/src/main.rs +++ b/src/operation/iIR/source/iir-rust/iir/src/main.rs @@ -5,8 +5,4 @@ fn main() { app::init_ir(); log::info!("start iIR"); - let spef_file_path = "/home/taosimin/T28/spef/asic_top.spef_vdd_vss_1212.rcworst.0c.spef"; - let _instance_power_path = "/home/shaozheqing/iEDA/bin/report_instance.csv"; - - matrix::ir_rc::read_rc_data_from_spef(spef_file_path); } diff --git a/src/operation/iIR/source/iir-rust/iir/src/matrix/ir_rc.rs b/src/operation/iIR/source/iir-rust/iir/src/matrix/ir_rc.rs index f84d4453a..3af56386c 100644 --- a/src/operation/iIR/source/iir-rust/iir/src/matrix/ir_rc.rs +++ b/src/operation/iIR/source/iir-rust/iir/src/matrix/ir_rc.rs @@ -1,5 +1,4 @@ use log; -use spef::spef_parser; use sprs::TriMat; use sprs::TriMatI; use std::cell::RefCell; @@ -12,6 +11,24 @@ use super::RustIRPGNetlist; pub const POWER_INNER_RESISTANCE: f64 = 1e-3; pub const RC_COEFF: f64 = 3.0; // RC coefficient, used to scale the resistance value from SPEF. +pub struct SpefConnInput { + pub name: String, + pub is_external: bool, +} + +pub struct SpefResCapInput { + pub node1: String, + pub node2: String, + pub value: f64, +} + +pub struct SpefNetInput { + pub name: String, + pub conns: Vec, + pub caps: Vec, + pub ress: Vec, +} + /// RC node of the spef network. pub struct RCNode { name: String, @@ -161,132 +178,59 @@ impl RCData { } } -pub fn split_spef_index_str(index_name: &str) -> (&str, &str) { - let v: Vec<&str> = index_name.split(':').collect(); - let index_str = v.first().unwrap(); - let node_str = v.last().unwrap(); - if v.len() == 2 { - (&index_str[1..], *node_str) - } else { - (&index_str[1..], "") - } -} - -/// Read rc data from spef file. -pub fn read_rc_data_from_spef(spef_file_path: &str) -> RCData { - log::info!("read spef file {} start", spef_file_path); - let spef_file = spef_parser::parse_spef_file(spef_file_path); - log::info!("read spef file {} finish", spef_file_path); - - let node_name_map = &spef_file.index_to_name_map; - let spef_data_nets = spef_file.get_nets(); +pub fn create_rc_data_from_spef_nets(nets: &[SpefNetInput]) -> RCData { let mut rc_data = RCData::default(); - let spef_index_to_string = |index_str: &str| { - let split_names = split_spef_index_str(index_str); - let index = split_names.0.parse::().unwrap(); - let node_name = node_name_map.get(&index); - if !split_names.1.is_empty() { - let expand_node1_name = node_name.unwrap().clone() + ":" + split_names.1; - return expand_node1_name; - } - String::from(node_name.unwrap()) - }; - - log::info!("build net rc data start"); - - // from the spef connection build bump port node and inst pin node. - for spef_net in spef_data_nets { - // println!("{:?}", spef_net); - let spef_net_name = &spef_net.name; - let net_name_str = spef_index_to_string(spef_net_name); - log::info!("build net {} rc data", net_name_str); - let mut one_net_data = RCOneNetData::new(net_name_str.clone()); - - // build the bump and inst pin node. - for conn_entry in spef_net.get_conns() { - let conn_type = conn_entry.get_conn_type(); - let pin_port_name_index = conn_entry.get_pin_port_name(); - let pin_port_name = spef_index_to_string(pin_port_name_index); - match conn_type { - spef_parser::spef_data::ConnectionType::EXTERNAL => { - // bump port - let mut rc_node = RCNode::new(pin_port_name); - rc_node.set_is_bump(); - - one_net_data.add_node(rc_node); - } - spef_parser::spef_data::ConnectionType::INTERNAL => { - // inst pin - let mut rc_node = RCNode::new(pin_port_name); - rc_node.set_is_inst_pin(); - - one_net_data.add_node(rc_node); - } - _ => println!("TODO"), + for spef_net in nets { + let mut one_net_data = RCOneNetData::new(spef_net.name.clone()); + + for conn in &spef_net.conns { + let mut rc_node = RCNode::new(conn.name.clone()); + if conn.is_external { + rc_node.set_is_bump(); + } else { + rc_node.set_is_inst_pin(); } + one_net_data.add_node(rc_node); } - // build the cap node. - for cap_entry in spef_net.get_caps() { - if !cap_entry.node2.is_empty() { + for cap in &spef_net.caps { + if !cap.node2.is_empty() { continue; } - let name_index = &cap_entry.node1; - let node_name = spef_index_to_string(name_index); - let cap_value = cap_entry.res_or_cap; - - let node_id = one_net_data.get_node_id(&node_name); - if node_id.is_none() { - let mut rc_node = RCNode::new(node_name); - rc_node.set_cap(cap_value); - one_net_data.add_node(rc_node); + let node_id = one_net_data.get_node_id(&cap.node1); + if let Some(node_id) = node_id { + one_net_data.set_node_cap(node_id, cap.value); } else { - one_net_data.set_node_cap(node_id.unwrap(), cap_value); + let mut rc_node = RCNode::new(cap.node1.clone()); + rc_node.set_cap(cap.value); + one_net_data.add_node(rc_node); } } - // build the internal node. - for one_resistance in spef_net.get_ress() { - let node1_name_index: &str = &one_resistance.node1; - let node1_name = spef_index_to_string(node1_name_index); - let node2_name_index: &str = &one_resistance.node2; - let node2_name = spef_index_to_string(node2_name_index); - let mut resistance_val = one_resistance.res_or_cap; - - resistance_val *= RC_COEFF; // scale the resistance value. - - let mut node_id = one_net_data.get_node_id(&node1_name); - - let node1_id = if node_id.is_none() { - let rc_node = RCNode::new(node1_name); - one_net_data.add_node(rc_node) + for resistance in &spef_net.ress { + let node1_id = if let Some(node_id) = one_net_data.get_node_id(&resistance.node1) { + node_id } else { - node_id.unwrap() + let rc_node = RCNode::new(resistance.node1.clone()); + one_net_data.add_node(rc_node) }; - node_id = one_net_data.get_node_id(&node2_name); - - let node2_id = if node_id.is_none() { - let rc_node2 = RCNode::new(node2_name); - one_net_data.add_node(rc_node2) + let node2_id = if let Some(node_id) = one_net_data.get_node_id(&resistance.node2) { + node_id } else { - node_id.unwrap() + let rc_node = RCNode::new(resistance.node2.clone()); + one_net_data.add_node(rc_node) }; let mut rc_resistance = RCResistance::default(); rc_resistance.from_node_id = node1_id; rc_resistance.to_node_id = node2_id; - rc_resistance.resistance = resistance_val; - + rc_resistance.resistance = resistance.value * RC_COEFF; one_net_data.add_resistance(rc_resistance); } - // if net_name_str == "VDD" { - // one_net_data.print_to_yaml("/home/taosimin/ir_example/aes/pg_netlist/rc_data.yaml"); - // } - rc_data.add_one_net_data(one_net_data); } @@ -367,3 +311,53 @@ pub fn build_conductance_matrix(rc_one_net_data: &RCOneNetData) -> TriMatI *const c_void { - let power_net_spef = c_str_to_r_str(c_power_net_spef); - let rc_data = ir_rc::read_rc_data_from_spef(&power_net_spef); - let mv_rc_data = Box::new(rc_data); - Box::into_raw(mv_rc_data) as *const c_void -} /// create power ground node. #[no_mangle] pub extern "C" fn create_pg_node(c_pg_netlist: *mut c_void, c_pg_node: *const RustIRPGNode) -> *const c_void { @@ -231,6 +247,51 @@ pub extern "C" fn create_rc_data(c_pg_netlist_ptr: *const c_void, len: usize) -> Box::into_raw(mv_rc_data) as *const c_void } +fn rust_spef_conns_to_inputs(c_conns: &RustVec) -> Vec { + let mut conns = Vec::with_capacity(c_conns.len); + let c_conn_ptr = c_conns.data as *const RustSpefConn; + for i in 0..c_conns.len { + let c_conn = unsafe { &*c_conn_ptr.add(i) }; + conns.push(SpefConnInput { + name: c_str_to_r_str(c_conn.name), + is_external: c_conn.is_external, + }); + } + conns +} + +fn rust_spef_res_caps_to_inputs(c_res_caps: &RustVec) -> Vec { + let mut res_caps = Vec::with_capacity(c_res_caps.len); + let c_res_cap_ptr = c_res_caps.data as *const RustSpefResCap; + for i in 0..c_res_caps.len { + let c_res_cap = unsafe { &*c_res_cap_ptr.add(i) }; + res_caps.push(SpefResCapInput { + node1: c_str_to_r_str(c_res_cap.node1), + node2: c_str_to_r_str(c_res_cap.node2), + value: c_res_cap.value, + }); + } + res_caps +} + +#[no_mangle] +pub extern "C" fn create_rc_data_from_spef(c_spef_nets: RustVec) -> *const c_void { + let mut nets = Vec::with_capacity(c_spef_nets.len); + let c_net_ptr = c_spef_nets.data as *const RustSpefNet; + for i in 0..c_spef_nets.len { + let c_net = unsafe { &*c_net_ptr.add(i) }; + nets.push(SpefNetInput { + name: c_str_to_r_str(c_net.name), + conns: rust_spef_conns_to_inputs(&c_net.conns), + caps: rust_spef_res_caps_to_inputs(&c_net.caps), + ress: rust_spef_res_caps_to_inputs(&c_net.ress), + }); + } + + let mv_rc_data = Box::new(ir_rc::create_rc_data_from_spef_nets(&nets)); + Box::into_raw(mv_rc_data) as *const c_void +} + #[no_mangle] pub extern "C" fn get_sum_resistance(c_rc_data: *const c_void, c_net_name: *const c_char) -> f64 { @@ -392,67 +453,117 @@ pub extern "C" fn get_instance_name( (string_to_c_char(instance_name.unwrap())) as _ } -/// Build RC matrix and current vector data. #[no_mangle] -pub extern "C" fn build_matrix_from_raw_data( +pub extern "C" fn build_matrices_from_rc_data( c_inst_power_path: *const c_char, - c_power_net_spef: *const c_char, -) -> RustVec { - // Firstly, read spef. - let power_net_spef = c_str_to_r_str(c_power_net_spef); + c_rc_data: *const c_void, +) { let inst_power_path = c_str_to_r_str(c_inst_power_path); + let rc_data = unsafe { &*(c_rc_data as *const RCData) }; - let rc_data = ir_rc::read_rc_data_from_spef(&power_net_spef); let instance_power_data = ir_inst_power::read_instance_pwr_csv(&inst_power_path).expect("error reading instance power csv file"); - let mut net_matrix_data: Vec = Vec::new(); - // Secondly, construct matrix data. for (net_name, one_net_data) in rc_data.get_nets_data() { log::info!("construct power net {} matrix start", net_name); - // Build rc matrix let conductance_matrix_triplet = ir_rc::build_conductance_matrix(one_net_data); - let rust_matrix = rust_convert_rc_matrix(&conductance_matrix_triplet); + let _rust_matrix = rust_convert_rc_matrix(&conductance_matrix_triplet); - // Read instance power data. let current_vector_result = ir_inst_power::build_instance_current_vector(&instance_power_data, one_net_data); - if let Ok(current_vector) = current_vector_result { - // Construct net matrix(rc matrix and current vector) data. - let mut current_vec: Vec = Vec::new(); - for (index, val) in current_vector { - current_vec.push(RustVector { data: val, index }); - } - let rust_matrix_vec = rust_vec_to_c_array(&rust_matrix); - let rust_current_vec = rust_vec_to_c_array(¤t_vec); - net_matrix_data.push(RustNetEquationData { - net_name: string_to_c_char(net_name), - g_matrix_vec: rust_matrix_vec, - j_vec: rust_current_vec, - }); - } else { + if current_vector_result.is_err() { panic!("current vector is none"); } log::info!("construct power net {} matrix finish", net_name); } - - // Finaly, return data to C. - - rust_vec_to_c_array(&net_matrix_data) } #[cfg(test)] mod tests { use super::ir_rc; use crate::matrix::{ - rust_convert_rc_matrix, rust_vec_to_c_array, string_to_c_char, RustNetEquationData, RustVector, + create_rc_data_from_spef, rust_convert_rc_matrix, rust_vec_to_c_array, string_to_c_char, + RustNetEquationData, RustSpefConn, RustSpefNet, RustSpefResCap, RustVec, RustVector, }; + use std::ffi::{c_void, CString}; + + fn rust_vec_from_mut_vec(vec: &mut Vec) -> RustVec { + RustVec { + data: vec.as_mut_ptr() as *mut c_void, + len: vec.len(), + cap: vec.capacity(), + type_size: std::mem::size_of::(), + } + } #[test] - fn test_build_matrix() { - let spef_file_path = "/home/taosimin/T28/spef/asic_top.spef_vdd_vss_1212.rcworst.0c.spef"; + fn create_rc_data_from_spef_copies_c_abi_inputs() { + let rc_data_ptr = { + let net_name = CString::new("VDD").unwrap(); + let bump_name = CString::new("VDD").unwrap(); + let inst_name = CString::new("U1/VDD").unwrap(); + let empty_name = CString::new("").unwrap(); + let cap_node_name = CString::new("VDD:3").unwrap(); + + let mut conns = vec![ + RustSpefConn { name: bump_name.as_ptr(), is_external: true }, + RustSpefConn { name: inst_name.as_ptr(), is_external: false }, + ]; + let mut caps = vec![RustSpefResCap { + node1: cap_node_name.as_ptr(), + node2: empty_name.as_ptr(), + value: 0.5, + }]; + let mut ress = vec![RustSpefResCap { + node1: bump_name.as_ptr(), + node2: inst_name.as_ptr(), + value: 2.0, + }]; + + let mut nets = vec![RustSpefNet { + name: net_name.as_ptr(), + conns: rust_vec_from_mut_vec(&mut conns), + caps: rust_vec_from_mut_vec(&mut caps), + ress: rust_vec_from_mut_vec(&mut ress), + }]; + + create_rc_data_from_spef(rust_vec_from_mut_vec(&mut nets)) + }; + + let rc_data = unsafe { Box::from_raw(rc_data_ptr as *mut ir_rc::RCData) }; + let one_net = rc_data.get_one_net_data("VDD"); + let bump = "VDD".to_string(); + let inst = "U1/VDD".to_string(); + let cap_node = "VDD:3".to_string(); + + let bump_id = one_net.get_node_id(&bump).unwrap(); + let inst_id = one_net.get_node_id(&inst).unwrap(); + let cap_id = one_net.get_node_id(&cap_node).unwrap(); + + let nodes = one_net.get_nodes().borrow(); + assert!(nodes[bump_id].get_is_bump()); + assert!(nodes[inst_id].get_is_inst_pin()); + assert_eq!(nodes[cap_id].get_cap(), 0.5); + assert_eq!(one_net.get_resistances()[0].resistance, 2.0 * ir_rc::RC_COEFF); + } - let rc_data = ir_rc::read_rc_data_from_spef(spef_file_path); + #[test] + fn test_build_matrix() { + let nets = vec![ir_rc::SpefNetInput { + name: "VDD".to_string(), + conns: vec![ + ir_rc::SpefConnInput { name: "VDD".to_string(), is_external: true }, + ir_rc::SpefConnInput { name: "U1/VDD".to_string(), is_external: false }, + ], + caps: vec![], + ress: vec![ir_rc::SpefResCapInput { + node1: "VDD".to_string(), + node2: "U1/VDD".to_string(), + value: 2.0, + }], + }]; + + let rc_data = ir_rc::create_rc_data_from_spef_nets(&nets); for (net_name, one_net_data) in rc_data.get_nets_data() { log::info!("construct power net {} matrix start", net_name); diff --git a/src/operation/iIR/test/BuildMatrixTest.cc b/src/operation/iIR/test/BuildMatrixTest.cc index 20a12be09..757c4f8ce 100644 --- a/src/operation/iIR/test/BuildMatrixTest.cc +++ b/src/operation/iIR/test/BuildMatrixTest.cc @@ -18,6 +18,7 @@ // #include #include "gtest/gtest.h" +#include "api/iIR.hh" #include "iir-rust/IRRustC.hh" #include "log/Log.hh" #include "string/Str.hh" @@ -50,7 +51,9 @@ TEST_F(BuildMatrixTest, build_matrix) { const char* spef_file_path = "/home/taosimin/T28/spef/asic_top.spef_vdd_vss_1212.rcworst.0c.spef"; - auto* rc_data = read_spef(spef_file_path); + iIR ir_analysis; + ir_analysis.readSpef(spef_file_path); + auto* rc_data = ir_analysis.get_rc_data(); auto one_net_matrix_data = build_one_net_conductance_matrix_data(rc_data, "VDD");