From d47cbeb76bf6cfbb9ab4f63d53294e1914de84ef Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Thu, 2 Apr 2026 00:56:38 +0000 Subject: [PATCH] fix to exclude bias pins from timing graph Signed-off-by: dsengupta0628 --- include/sta/PortDirection.hh | 5 ++++- liberty/LibertyReader.cc | 6 ++++++ liberty/LibertyWriter.cc | 3 ++- network/PortDirection.cc | 11 ++++++++--- network/test/cpp/TestNetwork.cc | 20 +++++++++++++++++++- verilog/VerilogWriter.cc | 2 ++ verilog/test/CMakeLists.txt | 1 + verilog/test/verilog_bias_pins.ok | 2 ++ verilog/test/verilog_bias_pins.tcl | 25 +++++++++++++++++++++++++ verilog/test/verilog_bias_pins.v | 20 ++++++++++++++++++++ verilog/test/verilog_bias_pins_out.vok | 26 ++++++++++++++++++++++++++ 11 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 verilog/test/verilog_bias_pins.ok create mode 100644 verilog/test/verilog_bias_pins.tcl create mode 100644 verilog/test/verilog_bias_pins.v create mode 100644 verilog/test/verilog_bias_pins_out.vok diff --git a/include/sta/PortDirection.hh b/include/sta/PortDirection.hh index 0b8186f9..1a21bbd2 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 *bias() { return bias_; } static PortDirection *unknown() { return unknown_; } static PortDirection *find(const char *dir_name); std::string_view name() const { return name_; } @@ -57,7 +58,8 @@ public: bool isAnyTristate() const; bool isGround() const { return this == ground_; } bool isPower() const { return this == power_; } - // Ground or power. + bool isBias() const { return this == bias_; } + // Ground, power, or bias. bool isPowerGround() const; bool isInternal() const { return this == internal_; } bool isUnknown() const { return this == unknown_; } @@ -76,6 +78,7 @@ private: static PortDirection *internal_; static PortDirection *ground_; static PortDirection *power_; + static PortDirection *bias_; static PortDirection *unknown_; }; diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index b91c10e6..8489f6f8 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -1217,6 +1217,12 @@ LibertyReader::makePgPinPort(LibertyCell *cell, case PwrGndType::internal_power: dir = PortDirection::power(); break; + case PwrGndType::nwell: + case PwrGndType::pwell: + case PwrGndType::deepnwell: + case PwrGndType::deeppwell: + dir = PortDirection::bias(); + break; case PwrGndType::none: error(1291, pg_pin_group, "unknown pg_type."); break; diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index a27490fb..d38774e8 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -569,7 +569,8 @@ LibertyWriter::asString(const PortDirection *dir) return "internal"; else if (dir == PortDirection::bidirect()) return "inout"; - else if (dir == PortDirection::ground() || dir == PortDirection::power()) + else if (dir == PortDirection::ground() || dir == PortDirection::power() + || dir == PortDirection::bias()) return "input"; return "unknown"; } diff --git a/network/PortDirection.cc b/network/PortDirection.cc index 5a6aaae5..2ade330d 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::bias_; 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); + bias_ = new PortDirection("bias", 7); + unknown_ = new PortDirection("unknown", 8); } void @@ -67,6 +69,8 @@ PortDirection::destroy() ground_ = nullptr; delete power_; power_ = nullptr; + delete bias_; + bias_ = 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, "bias")) + return bias_; else return nullptr; } @@ -124,8 +130,7 @@ PortDirection::isAnyTristate() const bool PortDirection::isPowerGround() const { - return this == ground_ - || this == power_; + return this == ground_ || this == power_ || this == bias_; } } // namespace diff --git a/network/test/cpp/TestNetwork.cc b/network/test/cpp/TestNetwork.cc index f95223f1..06e4b178 100644 --- a/network/test/cpp/TestNetwork.cc +++ b/network/test/cpp/TestNetwork.cc @@ -161,11 +161,20 @@ TEST_F(PortDirectionTest, PowerSingleton) { EXPECT_TRUE(dir->isPower()); } +TEST_F(PortDirectionTest, BiasSingleton) +{ + PortDirection *dir = PortDirection::bias(); + EXPECT_NE(dir, nullptr); + EXPECT_EQ(dir->name(), "bias"); + EXPECT_EQ(dir->index(), 7); + EXPECT_TRUE(dir->isBias()); +} + TEST_F(PortDirectionTest, UnknownSingleton) { PortDirection *dir = PortDirection::unknown(); EXPECT_NE(dir, nullptr); EXPECT_EQ(dir->name(), "unknown"); - EXPECT_EQ(dir->index(), 7); + EXPECT_EQ(dir->index(), 8); EXPECT_TRUE(dir->isUnknown()); } @@ -177,6 +186,7 @@ TEST_F(PortDirectionTest, FindByName) { EXPECT_EQ(PortDirection::find("internal"), PortDirection::internal()); EXPECT_EQ(PortDirection::find("ground"), PortDirection::ground()); EXPECT_EQ(PortDirection::find("power"), PortDirection::power()); + EXPECT_EQ(PortDirection::find("bias"), PortDirection::bias()); EXPECT_EQ(PortDirection::find("nonexistent"), nullptr); } @@ -188,6 +198,7 @@ TEST_F(PortDirectionTest, IsAnyInput) { EXPECT_FALSE(PortDirection::internal()->isAnyInput()); EXPECT_FALSE(PortDirection::ground()->isAnyInput()); EXPECT_FALSE(PortDirection::power()->isAnyInput()); + EXPECT_FALSE(PortDirection::bias()->isAnyInput()); EXPECT_FALSE(PortDirection::unknown()->isAnyInput()); } @@ -199,6 +210,7 @@ TEST_F(PortDirectionTest, IsAnyOutput) { EXPECT_FALSE(PortDirection::internal()->isAnyOutput()); EXPECT_FALSE(PortDirection::ground()->isAnyOutput()); EXPECT_FALSE(PortDirection::power()->isAnyOutput()); + EXPECT_FALSE(PortDirection::bias()->isAnyOutput()); EXPECT_FALSE(PortDirection::unknown()->isAnyOutput()); } @@ -210,12 +222,14 @@ TEST_F(PortDirectionTest, IsAnyTristate) { EXPECT_FALSE(PortDirection::internal()->isAnyTristate()); EXPECT_FALSE(PortDirection::ground()->isAnyTristate()); EXPECT_FALSE(PortDirection::power()->isAnyTristate()); + EXPECT_FALSE(PortDirection::bias()->isAnyTristate()); EXPECT_FALSE(PortDirection::unknown()->isAnyTristate()); } TEST_F(PortDirectionTest, IsPowerGround) { EXPECT_TRUE(PortDirection::power()->isPowerGround()); EXPECT_TRUE(PortDirection::ground()->isPowerGround()); + EXPECT_TRUE(PortDirection::bias()->isPowerGround()); EXPECT_FALSE(PortDirection::input()->isPowerGround()); EXPECT_FALSE(PortDirection::output()->isPowerGround()); EXPECT_FALSE(PortDirection::tristate()->isPowerGround()); @@ -851,6 +865,7 @@ TEST(PortDirectionExtraTest, AllDirections) { EXPECT_NE(PortDirection::internal(), nullptr); EXPECT_NE(PortDirection::ground(), nullptr); EXPECT_NE(PortDirection::power(), nullptr); + EXPECT_NE(PortDirection::bias(), nullptr); EXPECT_NE(PortDirection::unknown(), nullptr); } @@ -873,6 +888,7 @@ TEST(PortDirectionExtraTest, DirectionProperties) { EXPECT_TRUE(PortDirection::ground()->isPowerGround()); EXPECT_TRUE(PortDirection::power()->isPowerGround()); + EXPECT_TRUE(PortDirection::bias()->isPowerGround()); } TEST(PortDirectionExtraTest, DirectionNames) { @@ -886,6 +902,7 @@ TEST(PortDirectionExtraTest, DirectionNames) { EXPECT_EQ(PortDirection::internal()->name(), "internal"); EXPECT_EQ(PortDirection::ground()->name(), "ground"); EXPECT_EQ(PortDirection::power()->name(), "power"); + EXPECT_EQ(PortDirection::bias()->name(), "bias"); EXPECT_EQ(PortDirection::unknown()->name(), "unknown"); } @@ -900,6 +917,7 @@ TEST(PortDirectionExtraTest, FindAllByName) { EXPECT_EQ(PortDirection::find("internal"), PortDirection::internal()); EXPECT_EQ(PortDirection::find("ground"), PortDirection::ground()); EXPECT_EQ(PortDirection::find("power"), PortDirection::power()); + EXPECT_EQ(PortDirection::find("bias"), PortDirection::bias()); // "unknown" is not findable by name, returns nullptr EXPECT_EQ(PortDirection::find("nonexistent"), nullptr); } diff --git a/verilog/VerilogWriter.cc b/verilog/VerilogWriter.cc index 8edaf699..114051c8 100644 --- a/verilog/VerilogWriter.cc +++ b/verilog/VerilogWriter.cc @@ -253,6 +253,8 @@ VerilogWriter::verilogPortDir(PortDirection *dir) return "inout"; else if (dir == PortDirection::ground()) return "inout"; + else if (dir == PortDirection::bias()) + return "inout"; else if (dir == PortDirection::internal() || dir == PortDirection::unknown()) return "inout"; diff --git a/verilog/test/CMakeLists.txt b/verilog/test/CMakeLists.txt index e6a9235f..bedd7fbc 100644 --- a/verilog/test/CMakeLists.txt +++ b/verilog/test/CMakeLists.txt @@ -1,5 +1,6 @@ sta_module_tests("verilog" TESTS + bias_pins bus ) diff --git a/verilog/test/verilog_bias_pins.ok b/verilog/test/verilog_bias_pins.ok new file mode 100644 index 00000000..1fe88107 --- /dev/null +++ b/verilog/test/verilog_bias_pins.ok @@ -0,0 +1,2 @@ +--- write_verilog bias pins --- +No differences found. diff --git a/verilog/test/verilog_bias_pins.tcl b/verilog/test/verilog_bias_pins.tcl new file mode 100644 index 00000000..2375fa1c --- /dev/null +++ b/verilog/test/verilog_bias_pins.tcl @@ -0,0 +1,25 @@ +# Test write_verilog should omit bias pins the same way it omits power/ground. + +source ../../test/helpers.tcl + +puts "--- write_verilog bias pins ---" +read_liberty ../../test/sky130hd/sky130_fd_sc_hd__ss_n40C_1v40.lib +read_verilog verilog_bias_pins.v +link_design top + +set outfile [make_result_file verilog_bias_pins_out.v] +write_verilog $outfile + +set outfile_pwr [make_result_file verilog_bias_pins_pwr.v] +write_verilog -include_pwr_gnd $outfile_pwr + +set combined_out [make_result_file verilog_bias_pins_combined.v] +set out_stream [open $combined_out w] +foreach file [list $outfile $outfile_pwr] { + set in_stream [open $file r] + puts -nonewline $out_stream [read $in_stream] + close $in_stream +} +close $out_stream + +diff_files verilog_bias_pins_out.vok $combined_out diff --git a/verilog/test/verilog_bias_pins.v b/verilog/test/verilog_bias_pins.v new file mode 100644 index 00000000..1abd47db --- /dev/null +++ b/verilog/test/verilog_bias_pins.v @@ -0,0 +1,20 @@ +module top ( + output y, + input a +); + + supply1 VPWR; + supply0 VGND; + supply1 VPB; + supply0 VNB; + + sky130_fd_sc_hd__buf_1 u1 ( + .X(y), + .A(a), + .VPWR(VPWR), + .VGND(VGND), + .VPB(VPB), + .VNB(VNB) + ); + +endmodule diff --git a/verilog/test/verilog_bias_pins_out.vok b/verilog/test/verilog_bias_pins_out.vok new file mode 100644 index 00000000..41b72482 --- /dev/null +++ b/verilog/test/verilog_bias_pins_out.vok @@ -0,0 +1,26 @@ +module top (y, + a); + output y; + input a; + + + sky130_fd_sc_hd__buf_1 u1 (.A(a), + .X(y)); +endmodule +module top (y, + a); + output y; + input a; + + wire VGND; + wire VNB; + wire VPB; + wire VPWR; + + sky130_fd_sc_hd__buf_1 u1 (.VGND(VGND), + .VNB(VNB), + .VPB(VPB), + .VPWR(VPWR), + .A(a), + .X(y)); +endmodule