From b58ff962d617a01a96f206c4a6c76b2eabd91fa4 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 11 Jan 2026 15:01:04 -0800 Subject: [PATCH 1/7] msg id conflict Signed-off-by: James Cherry --- power/VcdReader.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power/VcdReader.cc b/power/VcdReader.cc index 6712a9b2..2adebfda 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -469,7 +469,7 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin, double clk_period = clk->period(); if (abs((clk_period - sim_period) / clk_period) > sim_clk_period_tolerance_) // Warn if sim clock period differs from SDC by more than 10%. - report_->warn(1452, "clock %s vcd period %s differs from SDC clock period %s", + report_->warn(1453, "clock %s vcd period %s differs from SDC clock period %s", clk->name(), delayAsString(sim_period, this), delayAsString(clk_period, this)); From 7f65853afa043ccf4c49e75ea1c3b066a36eea6c Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 11 Jan 2026 19:52:55 -0800 Subject: [PATCH 2/7] WriteSpice rm dead code Signed-off-by: James Cherry --- spice/WriteSpice.cc | 101 +------------------------------------------- 1 file changed, 1 insertion(+), 100 deletions(-) diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index a0623c53..f336bc8f 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -43,6 +43,7 @@ #include "Path.hh" #include "DcalcAnalysisPt.hh" #include "Bdd.hh" +#include "cudd.h" namespace sta { @@ -850,8 +851,6 @@ WriteSpice::gatePortValues(const Pin *input_pin, } } -#if CUDD - void WriteSpice::gatePortValues(const Instance *, const FuncExpr *expr, @@ -895,104 +894,6 @@ WriteSpice::gatePortValues(const Instance *, bdd_.clearVarMap(); } -#else - -void -WriteSpice::gatePortValues(const Instance *inst, - const FuncExpr *expr, - const LibertyPort *input_port, - // Return values. - LibertyPortLogicValues &port_values) -{ - FuncExpr *left = expr->left(); - FuncExpr *right = expr->right(); - switch (expr->op()) { - case FuncExpr::op_port: - break; - case FuncExpr::op_not: - gatePortValues(inst, left, input_port, port_values); - break; - case FuncExpr::op_or: - if (left->hasPort(input_port) - && right->op() == FuncExpr::op_port) { - gatePortValues(inst, left, input_port, port_values); - port_values[right->port()] = LogicValue::zero; - } - else if (left->hasPort(input_port) - && right->op() == FuncExpr::op_not - && right->left()->op() == FuncExpr::op_port) { - // input_port + !right_port - gatePortValues(inst, left, input_port, port_values); - port_values[right->left()->port()] = LogicValue::one; - } - else if (right->hasPort(input_port) - && left->op() == FuncExpr::op_port) { - gatePortValues(inst, right, input_port, port_values); - port_values[left->port()] = LogicValue::zero; - } - else if (right->hasPort(input_port) - && left->op() == FuncExpr::op_not - && left->left()->op() == FuncExpr::op_port) { - // input_port + !left_port - gatePortValues(inst, right, input_port, port_values); - port_values[left->left()->port()] = LogicValue::one; - } - else { - gatePortValues(inst, left, input_port, port_values); - gatePortValues(inst, right, input_port, port_values); - } - break; - case FuncExpr::op_and: - if (left->hasPort(input_port) - && right->op() == FuncExpr::op_port) { - gatePortValues(inst, left, input_port, port_values); - port_values[right->port()] = LogicValue::one; - } - else if (left->hasPort(input_port) - && right->op() == FuncExpr::op_not - && right->left()->op() == FuncExpr::op_port) { - // input_port * !right_port - gatePortValues(inst, left, input_port, port_values); - port_values[right->left()->port()] = LogicValue::zero; - } - else if (right->hasPort(input_port) - && left->op() == FuncExpr::op_port) { - gatePortValues(inst, right, input_port, port_values); - port_values[left->port()] = LogicValue::one; - } - else if (right->hasPort(input_port) - && left->op() == FuncExpr::op_not - && left->left()->op() == FuncExpr::op_port) { - // input_port * !left_port - gatePortValues(inst, right, input_port, port_values); - port_values[left->left()->port()] = LogicValue::zero; - } - else { - gatePortValues(inst, left, input_port, port_values); - gatePortValues(inst, right, input_port, port_values); - } - break; - case FuncExpr::op_xor: - // Need to know timing arc sense to get this right. - if (left->port() == input_port - && right->op() == FuncExpr::op_port) - port_values[right->port()] = LogicValue::zero; - else if (right->port() == input_port - && left->op() == FuncExpr::op_port) - port_values[left->port()] = LogicValue::zero; - else { - gatePortValues(inst, left, input_port, port_values); - gatePortValues(inst, right, input_port, port_values); - } - break; - case FuncExpr::op_one: - case FuncExpr::op_zero: - break; - } -} - -#endif - void WriteSpice::regPortValues(const Pin *input_pin, const RiseFall *drvr_rf, From 0429ac324b2cd4a12783e053b9c85f5d40f4cde8 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 15 Jan 2026 15:00:48 -0700 Subject: [PATCH 3/7] rm dbg print Signed-off-by: James Cherry --- power/VcdParse.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/power/VcdParse.cc b/power/VcdParse.cc index d84ee6cb..93d6625c 100644 --- a/power/VcdParse.cc +++ b/power/VcdParse.cc @@ -245,8 +245,6 @@ VcdParse::parseVarValues() reader_->varAppendValue(id, time_, char0); } else if (char0 == 'B') { - if (file_line_ == 148904) - printf("luse\n"); string bus_value = token.substr(1); string id = getToken(); if (!reader_->varIdValid(id)) From dda887bc6e5160fd7c15489cc5845eaff72b5252 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 17 Jan 2026 11:45:40 -0700 Subject: [PATCH 4/7] report_checks -unique_edges resolves #354 Signed-off-by: James Cherry --- search/PathEnum.cc | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/search/PathEnum.cc b/search/PathEnum.cc index c3a1189a..c8763ed4 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -415,7 +415,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, { // These paths fanin to before_div_ so we know to_vertex matches. if ((!unique_pins_ || from_vertex != prev_vertex_) - && (!unique_edges_ || from_rf != prev_arc_->fromEdge()->asRiseFall()) + && (!unique_edges_ + || from_vertex != prev_vertex_ + || from_rf != prev_arc_->fromEdge()->asRiseFall()) && arc != prev_arc_ && Tag::matchNoCrpr(to_tag, before_div_tag_) // Ignore paths that only differ by crpr from same vertex/edge. @@ -440,10 +442,26 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, if (crpr_active_) visited_fanins_.emplace(from_vertex, arc); } - else - debugPrint(debug_, "path_enum", 3, " pruned %s %s", - edge->to_string(this).c_str(), - arc->to_string().c_str()); + else { + if (debug_->check("path_enum", 3)) { + bool unique_pins = !(!unique_pins_ || from_vertex != prev_vertex_); + bool unique_edges = !(!unique_edges_ + || from_rf != prev_arc_->fromEdge()->asRiseFall()); + bool same_arc = !(arc != prev_arc_); + bool tag_march = !Tag::matchNoCrpr(to_tag, before_div_tag_); + bool crpr = !(!crpr_active_ + || visited_fanins_.find({from_vertex, arc}) + == visited_fanins_.end()); + debugPrint(debug_, "path_enum", 3, " pruned %s%s%s%s%s %s %s", + unique_pins ? "unique_pins " : "", + unique_edges ? "unique_edges " : "", + same_arc ? "same_arc " : "", + tag_march ? "tag_march " : "", + crpr ? "crpr " : "", + edge->to_string(this).c_str(), + arc->to_string().c_str()); + } + } return true; } From 117e4094bc38a910653f8bd50bde0ae3b3e8c92c Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Fri, 23 Jan 2026 11:39:56 -0800 Subject: [PATCH 5/7] Fix for invalid operator error handling (#366) * Fix for invalid operator error handling * Revisions --- sdc/Sdc.tcl | 25 +++++++++++++++++-------- test/get_filter.ok | 2 ++ test/get_filter.tcl | 5 +++++ test/prima3.ok | 10 ---------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 112ea504..e22645f2 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -306,11 +306,18 @@ proc current_design { {design ""} } { # Generic get_* filter. proc filter_objs { filter objects filter_function object_type } { - set filter_regexp1 {@?([a-zA-Z_]+) *((==|!=|=~|!~) *([0-9a-zA-Z_\*]+))?} - set filter_or_regexp "($filter_regexp1) *\\|\\| *($filter_regexp1)" - set filter_and_regexp "($filter_regexp1) *&& *($filter_regexp1)" + # Regexp for attr op arg (e.g., full_name =~ *blk*) + set filter_regexp_op {@?([a-zA-Z_]+) *(==|!=|=~|!~) *([0-9a-zA-Z_\*]+)} + # Regexp for bool attr (e.g., is_hierarchical) - anchored for standalone use + set filter_regexp_bool {^@?([a-zA-Z_]+)$} + # Regexp for wildcard attr (e.g., full_name *blk*) + set filter_regexp_wild_op {@?([a-zA-Z_]+) *(.+) *([0-9a-zA-Z_\*]+)} + # Regexp for term in compound expression (no anchors) + set filter_regexp_term {@?([a-zA-Z_]+)( *(==|!=|=~|!~) *([0-9a-zA-Z_\*]+))?} + set filter_or_regexp "($filter_regexp_term) *\\|\\| *($filter_regexp_term)" + set filter_and_regexp "($filter_regexp_term) *&& *($filter_regexp_term)" set filtered_objects {} - # Ignore sub-exprs in filter_regexp1 for expr2 match var. + # Ignore sub-exprs in filter_regexp for expr2 match var. if { [regexp $filter_or_regexp $filter ignore expr1 ignore ignore ignore ignore expr2] } { set filtered_objects1 [filter_objs $expr1 $objects $filter_function $object_type] set filtered_objects2 [filter_objs $expr2 $objects $filter_function $object_type] @@ -318,11 +325,13 @@ proc filter_objs { filter objects filter_function object_type } { } elseif { [regexp $filter_and_regexp $filter ignore expr1 ignore ignore ignore ignore expr2] } { set filtered_objects [filter_objs $expr1 $objects $filter_function $object_type] set filtered_objects [filter_objs $expr2 $filtered_objects $filter_function $object_type] - } elseif { [regexp $filter_regexp1 $filter ignore attr_name ignore op arg] } { - # If no op/arg, use ==1 by default. - set op [expr {($op == "") ? "==" : $op}] - set arg [expr {($arg == "") ? "1" : $arg}] + } elseif { [regexp $filter_regexp_op $filter ignore attr_name op arg] } { set filtered_objects [$filter_function $attr_name $op $arg $objects] + } elseif { [regexp $filter_regexp_bool $filter ignore attr_name] } { + # Bool property: use ==1 by default. + set filtered_objects [$filter_function $attr_name "==" "1" $objects] + } elseif { [regexp $filter_regexp_wild_op $filter ignore attr_name op arg] } { + sta_error 336 "unknown filter operand." } else { sta_error 350 "unsupported $object_type -filter expression." } diff --git a/test/get_filter.ok b/test/get_filter.ok index 8e98cdba..deaa54f3 100644 --- a/test/get_filter.ok +++ b/test/get_filter.ok @@ -52,3 +52,5 @@ in1 in2 [get_ports -filter direction==output *] out +[get_cells -filter {name ~= *r1*} *] +Error: get_filter.tcl line 48, unknown filter operand. diff --git a/test/get_filter.tcl b/test/get_filter.tcl index ea17f599..7263811e 100644 --- a/test/get_filter.tcl +++ b/test/get_filter.tcl @@ -42,3 +42,8 @@ puts {[get_ports -filter direction==input *]} report_object_full_names [get_ports -filter direction==input *] puts {[get_ports -filter direction==output *]} report_object_full_names [get_ports -filter direction==output *] + +# Test invalid operator ~= (should be =~) +puts {[get_cells -filter {name ~= *r1*} *]} +catch {get_cells -filter {name ~= *r1*} *} result +puts $result diff --git a/test/prima3.ok b/test/prima3.ok index 98c9c3cd..a4ac1d9c 100644 --- a/test/prima3.ok +++ b/test/prima3.ok @@ -1,13 +1,3 @@ -Warning: asap7_simple.lib.gz line 71029, timing group from output port. -Warning: asap7_simple.lib.gz line 71505, timing group from output port. -Warning: asap7_simple.lib.gz line 71981, timing group from output port. -Warning: asap7_simple.lib.gz line 72457, timing group from output port. -Warning: asap7_simple.lib.gz line 72933, timing group from output port. -Warning: asap7_simple.lib.gz line 73409, timing group from output port. -Warning: asap7_simple.lib.gz line 73885, timing group from output port. -Warning: asap7_simple.lib.gz line 81795, timing group from output port. -Warning: asap7_simple.lib.gz line 82271, timing group from output port. -Warning: asap7_simple.lib.gz line 82747, timing group from output port. Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk From 08acc67c058191b33b7a0a679523fe59bd7d8dc3 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 28 Jan 2026 11:56:40 -0700 Subject: [PATCH 6/7] Sta::networkChanged() comment Signed-off-by: James Cherry --- include/sta/Sta.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index cdf67203..4404eedf 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1153,7 +1153,9 @@ public: virtual void disconnectPin(Pin *pin); virtual void makePortPin(const char *port_name, PortDirection *dir); - // Notify STA of network change. + // Notify STA that the network has changed without using the network + // editing API. For example, reading a netlist without using the + // builtin network readers. void networkChanged(); void deleteLeafInstanceBefore(const Instance *inst); void deleteInstancePinsBefore(const Instance *inst); From 25ea7a3795f44fac4202edb501e27e8c590b5ee9 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 28 Jan 2026 12:06:40 -0700 Subject: [PATCH 7/7] network edits invalidate power resolves #371 Signed-off-by: James Cherry --- power/Power.cc | 10 +--------- power/Power.hh | 3 +-- search/Sta.cc | 13 +++++++++---- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/power/Power.cc b/power/Power.cc index 3265fe96..c5297b33 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1595,15 +1595,7 @@ Power::clockMinPeriod() } void -Power::deleteInstanceBefore(const Instance *) -{ - activities_valid_ = false; - instance_powers_.clear(); - corner_ = nullptr; -} - -void -Power::deletePinBefore(const Pin *) +Power::powerInvalid() { activities_valid_ = false; instance_powers_.clear(); diff --git a/power/Power.hh b/power/Power.hh index abed2f40..82ad01f2 100644 --- a/power/Power.hh +++ b/power/Power.hh @@ -108,8 +108,7 @@ public: float clockMinPeriod(); InstanceSeq highestPowerInstances(size_t count, const Corner *corner); - void deleteInstanceBefore(const Instance *inst); - void deletePinBefore(const Pin *pin); + void powerInvalid(); protected: PwrActivity &activity(const Pin *pin); diff --git a/search/Sta.cc b/search/Sta.cc index eb389646..7b9a3123 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4245,6 +4245,7 @@ Sta::makeInstanceAfter(const Instance *inst) } } graph_->makeInstanceEdges(inst); + power_->powerInvalid(); } } } @@ -4311,6 +4312,8 @@ Sta::replaceEquivCellAfter(const Instance *inst) parasitics_->loadPinCapacitanceChanged(pin); } delete pin_iter; + clk_skews_->clear(); + power_->powerInvalid(); } } @@ -4381,7 +4384,6 @@ Sta::replaceCellBefore(const Instance *inst, } } delete pin_iter; - clk_skews_->clear(); } } @@ -4447,6 +4449,7 @@ Sta::connectPinAfter(const Pin *pin) sdc_->connectPinAfter(pin); sim_->connectPinAfter(pin); clk_skews_->clear(); + power_->powerInvalid(); } void @@ -4538,6 +4541,7 @@ Sta::disconnectPinBefore(const Pin *pin) } } clk_skews_->clear(); + power_->powerInvalid(); } } @@ -4582,6 +4586,8 @@ Sta::deleteNetBefore(const Net *net) delete pin_iter; } sdc_->deleteNetBefore(net); + clk_skews_->clear(); + power_->powerInvalid(); } void @@ -4609,7 +4615,8 @@ Sta::deleteLeafInstanceBefore(const Instance *inst) { sim_->deleteInstanceBefore(inst); sdc_->deleteInstanceBefore(inst); - power_->deleteInstanceBefore(inst); + clk_skews_->clear(); + power_->powerInvalid(); } void @@ -4687,8 +4694,6 @@ Sta::deletePinBefore(const Pin *pin) sdc_->deletePinBefore(pin); sim_->deletePinBefore(pin); clk_network_->deletePinBefore(pin); - power_->deletePinBefore(pin); - clk_skews_->clear(); } void