From 23bee036c9016da94920db65bd70aaa4da4c3e1f Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Mon, 10 Nov 2025 04:10:03 -0800 Subject: [PATCH 1/2] Add support for "well" direction type (nwell, pwell, etc.), and fix isBuffer (+ other functions) to accommodate wells --- include/sta/PortDirection.hh | 4 ++++ liberty/Liberty.cc | 3 ++- liberty/LibertyReader.cc | 6 ++++++ network/PortDirection.cc | 8 +++++++- power/Power.cc | 2 ++ power/VcdReader.cc | 1 + test/get_is_buffer.ok | 1 + test/get_is_buffer.tcl | 5 +++++ test/get_is_buffer.v | 11 +++++++++++ test/regression_vars.tcl | 1 + 10 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test/get_is_buffer.ok create mode 100644 test/get_is_buffer.tcl create mode 100644 test/get_is_buffer.v diff --git a/include/sta/PortDirection.hh b/include/sta/PortDirection.hh index 186914a9..0b528a0e 100644 --- a/include/sta/PortDirection.hh +++ b/include/sta/PortDirection.hh @@ -41,6 +41,7 @@ public: static PortDirection *internal() { return internal_; } static PortDirection *ground() { return ground_; } static PortDirection *power() { return power_; } + static PortDirection *well() { return well_; } static PortDirection *unknown() { return unknown_; } static PortDirection *find(const char *dir_name); const char *name() const { return name_; } @@ -59,6 +60,8 @@ public: bool isPower() const { return this == power_; } // Ground or power. bool isPowerGround() const; + // Nwell, pwell, deepnwell, or deeppwell. + bool isWell() const { return this == well_; } bool isInternal() const { return this == internal_; } bool isUnknown() const { return this == unknown_; } @@ -76,6 +79,7 @@ private: static PortDirection *internal_; static PortDirection *ground_; static PortDirection *power_; + static PortDirection *well_; static PortDirection *unknown_; }; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index c4d9fdd3..0130645d 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -1226,7 +1226,8 @@ LibertyCell::bufferPorts(// Return values. } output = port; } - else if (!dir->isPowerGround()) { + else if (!dir->isPowerGround() && !dir->isWell()) { + // Invalid direction. input = nullptr; output = nullptr; break; diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 3fc2ffdf..ba8cae49 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -5700,6 +5700,12 @@ LibertyReader::visitPgType(LibertyAttr *attr) case PwrGndType::internal_power: dir = PortDirection::power(); break; + case PwrGndType::nwell: + case PwrGndType::pwell: + case PwrGndType::deepnwell: + case PwrGndType::deeppwell: + dir = PortDirection::well(); + break; case PwrGndType::none: libError(1291, attr, "unknown pg_type."); break; diff --git a/network/PortDirection.cc b/network/PortDirection.cc index 693f6908..43aeb2d8 100644 --- a/network/PortDirection.cc +++ b/network/PortDirection.cc @@ -35,6 +35,7 @@ PortDirection *PortDirection::bidirect_; PortDirection *PortDirection::internal_; PortDirection *PortDirection::ground_; PortDirection *PortDirection::power_; +PortDirection *PortDirection::well_; PortDirection *PortDirection::unknown_; void @@ -47,7 +48,8 @@ PortDirection::init() internal_ = new PortDirection("internal", 4); ground_ = new PortDirection("ground", 5); power_ = new PortDirection("power", 6); - unknown_ = new PortDirection("unknown", 7); + well_ = new PortDirection("well", 7); + unknown_ = new PortDirection("unknown", 8); } void @@ -67,6 +69,8 @@ PortDirection::destroy() ground_ = nullptr; delete power_; power_ = nullptr; + delete well_; + well_ = nullptr; delete unknown_; unknown_ = nullptr; } @@ -95,6 +99,8 @@ PortDirection::find(const char *dir_name) return ground_; else if (stringEqual(dir_name, "power")) return power_; + else if (stringEqual(dir_name, "well")) + return well_; else return nullptr; } diff --git a/power/Power.cc b/power/Power.cc index cc596820..8cc5d409 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1506,6 +1506,7 @@ Power::findUnannotatedPins(const Instance *inst, LibertyPort *liberty_port = sdc_network_->libertyPort(pin); if (!network_->direction(pin)->isInternal() && !network_->direction(pin)->isPowerGround() + && !network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd()) && user_activity_map_.find(pin) == user_activity_map_.end()) unannotated_pins.push_back(pin); @@ -1527,6 +1528,7 @@ Power::pinCount() LibertyPort *liberty_port = sdc_network_->libertyPort(pin); if (!network_->direction(pin)->isInternal() && !network_->direction(pin)->isPowerGround() + && !network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd())) count++; } diff --git a/power/VcdReader.cc b/power/VcdReader.cc index 77059615..0703c06a 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -290,6 +290,7 @@ VcdCountReader::addVarPin(const string &pin_name, && !sdc_network_->isHierarchical(pin) && !sdc_network_->direction(pin)->isInternal() && !sdc_network_->direction(pin)->isPowerGround() + && !sdc_network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd())) { VcdCounts &vcd_counts = vcd_count_map_[id]; vcd_counts.resize(width); diff --git a/test/get_is_buffer.ok b/test/get_is_buffer.ok new file mode 100644 index 00000000..655d42ed --- /dev/null +++ b/test/get_is_buffer.ok @@ -0,0 +1 @@ +buf_inst diff --git a/test/get_is_buffer.tcl b/test/get_is_buffer.tcl new file mode 100644 index 00000000..c02f682e --- /dev/null +++ b/test/get_is_buffer.tcl @@ -0,0 +1,5 @@ +# is_buffer property +read_liberty ../examples/sky130hd_tt.lib.gz +read_verilog get_is_buffer.v +link_design dut +report_object_full_names [get_cells -filter is_buffer] diff --git a/test/get_is_buffer.v b/test/get_is_buffer.v new file mode 100644 index 00000000..91f8afea --- /dev/null +++ b/test/get_is_buffer.v @@ -0,0 +1,11 @@ +module dut ( + input A, + output Y +); + + sky130_fd_sc_hd__buf_2 buf_inst ( + .A(A), + .X(Y) + ); + +endmodule diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index d7a46617..52314276 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -139,6 +139,7 @@ record_example_tests { record_sta_tests { get_filter + get_is_buffer get_is_memory get_lib_pins_of_objects get_noargs From a4137902e0359f839a4ddfd2463db23af2ee3975 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Sat, 15 Nov 2025 21:19:37 -0800 Subject: [PATCH 2/2] Just fix isBuffer issue --- include/sta/PortDirection.hh | 4 ---- liberty/Liberty.cc | 2 +- liberty/LibertyReader.cc | 6 ------ network/PortDirection.cc | 8 +------- power/Power.cc | 2 -- power/VcdReader.cc | 1 - 6 files changed, 2 insertions(+), 21 deletions(-) diff --git a/include/sta/PortDirection.hh b/include/sta/PortDirection.hh index 0b528a0e..186914a9 100644 --- a/include/sta/PortDirection.hh +++ b/include/sta/PortDirection.hh @@ -41,7 +41,6 @@ public: static PortDirection *internal() { return internal_; } static PortDirection *ground() { return ground_; } static PortDirection *power() { return power_; } - static PortDirection *well() { return well_; } static PortDirection *unknown() { return unknown_; } static PortDirection *find(const char *dir_name); const char *name() const { return name_; } @@ -60,8 +59,6 @@ public: bool isPower() const { return this == power_; } // Ground or power. bool isPowerGround() const; - // Nwell, pwell, deepnwell, or deeppwell. - bool isWell() const { return this == well_; } bool isInternal() const { return this == internal_; } bool isUnknown() const { return this == unknown_; } @@ -79,7 +76,6 @@ private: static PortDirection *internal_; static PortDirection *ground_; static PortDirection *power_; - static PortDirection *well_; static PortDirection *unknown_; }; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 0130645d..3cf867f2 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -1226,7 +1226,7 @@ LibertyCell::bufferPorts(// Return values. } output = port; } - else if (!dir->isPowerGround() && !dir->isWell()) { + else if (!port->isPwrGnd()) { // Invalid direction. input = nullptr; output = nullptr; diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index ba8cae49..3fc2ffdf 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -5700,12 +5700,6 @@ LibertyReader::visitPgType(LibertyAttr *attr) case PwrGndType::internal_power: dir = PortDirection::power(); break; - case PwrGndType::nwell: - case PwrGndType::pwell: - case PwrGndType::deepnwell: - case PwrGndType::deeppwell: - dir = PortDirection::well(); - break; case PwrGndType::none: libError(1291, attr, "unknown pg_type."); break; diff --git a/network/PortDirection.cc b/network/PortDirection.cc index 43aeb2d8..693f6908 100644 --- a/network/PortDirection.cc +++ b/network/PortDirection.cc @@ -35,7 +35,6 @@ PortDirection *PortDirection::bidirect_; PortDirection *PortDirection::internal_; PortDirection *PortDirection::ground_; PortDirection *PortDirection::power_; -PortDirection *PortDirection::well_; PortDirection *PortDirection::unknown_; void @@ -48,8 +47,7 @@ PortDirection::init() internal_ = new PortDirection("internal", 4); ground_ = new PortDirection("ground", 5); power_ = new PortDirection("power", 6); - well_ = new PortDirection("well", 7); - unknown_ = new PortDirection("unknown", 8); + unknown_ = new PortDirection("unknown", 7); } void @@ -69,8 +67,6 @@ PortDirection::destroy() ground_ = nullptr; delete power_; power_ = nullptr; - delete well_; - well_ = nullptr; delete unknown_; unknown_ = nullptr; } @@ -99,8 +95,6 @@ PortDirection::find(const char *dir_name) return ground_; else if (stringEqual(dir_name, "power")) return power_; - else if (stringEqual(dir_name, "well")) - return well_; else return nullptr; } diff --git a/power/Power.cc b/power/Power.cc index 8cc5d409..cc596820 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1506,7 +1506,6 @@ Power::findUnannotatedPins(const Instance *inst, LibertyPort *liberty_port = sdc_network_->libertyPort(pin); if (!network_->direction(pin)->isInternal() && !network_->direction(pin)->isPowerGround() - && !network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd()) && user_activity_map_.find(pin) == user_activity_map_.end()) unannotated_pins.push_back(pin); @@ -1528,7 +1527,6 @@ Power::pinCount() LibertyPort *liberty_port = sdc_network_->libertyPort(pin); if (!network_->direction(pin)->isInternal() && !network_->direction(pin)->isPowerGround() - && !network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd())) count++; } diff --git a/power/VcdReader.cc b/power/VcdReader.cc index 0703c06a..77059615 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -290,7 +290,6 @@ VcdCountReader::addVarPin(const string &pin_name, && !sdc_network_->isHierarchical(pin) && !sdc_network_->direction(pin)->isInternal() && !sdc_network_->direction(pin)->isPowerGround() - && !sdc_network_->direction(pin)->isWell() && !(liberty_port && liberty_port->isPwrGnd())) { VcdCounts &vcd_counts = vcd_count_map_[id]; vcd_counts.resize(width);