diff --git a/src/core/app/load.cpp b/src/core/app/load.cpp index 2830144..1feeb60 100644 --- a/src/core/app/load.cpp +++ b/src/core/app/load.cpp @@ -36,7 +36,7 @@ LoadResult load_module(System *sys, const std::string &module_name, r.power = inf.power; r.gnd = inf.gnd; r.kept_other = inf.kept_other; - r.adjacent = inf.adjacent; + r.mgmt = inf.mgmt; r.ok = true; } catch (const std::exception &e) { r.error = e.what(); diff --git a/src/core/app/load.hpp b/src/core/app/load.hpp index 26420a7..d0b3f9d 100644 --- a/src/core/app/load.hpp +++ b/src/core/app/load.hpp @@ -23,7 +23,7 @@ struct LoadResult { int power = 0; ///< signals inferred Power (name + structure) int gnd = 0; ///< signals inferred GndShield (name) int kept_other = 0; ///< name said Power but evidence too weak → kept Other - int adjacent = 0; ///< rail + control token (SENSE/EN/PG/…) → Other, not suspect + int mgmt = 0; ///< power-management signal (rail + SENSE/EN/PG/… token) → Other, not suspect }; // Import a module from a netlist/pinout file into `sys`, drop singleton signals, diff --git a/src/core/app/script.cpp b/src/core/app/script.cpp index 27bde4b..6b954f3 100644 --- a/src/core/app/script.cpp +++ b/src/core/app/script.cpp @@ -190,8 +190,8 @@ private: emit(" types: " + std::to_string(r.power) + " power, " + std::to_string(r.gnd) + " gnd, " + std::to_string(r.kept_other) + " suspect Power (name only — kept as Other), " - + std::to_string(r.adjacent) - + " power-adjacent (control — kept as Other)"); + + std::to_string(r.mgmt) + + " power-management (control/measure — kept as Other)"); return true; } if (cmd == "connect" || cmd == "plug") { diff --git a/src/core/domain/analysis.cpp b/src/core/domain/analysis.cpp index 7d9550a..e526d54 100644 --- a/src/core/domain/analysis.cpp +++ b/src/core/domain/analysis.cpp @@ -282,12 +282,12 @@ SignalTypeInferenceStats infer_signal_types(System *sys) { ++st.gnd; continue; } - if (ncl.verdict == NameVerdict::PowerAdjacent) { + if (ncl.verdict == NameVerdict::PowerMgmt) { // A rail token next to a control token (SENSE, EN, PG, …): // a signal about a rail, confidently NOT the rail — never // suspect, whatever the fan-out. s->type = SignalType::Other; - ++st.adjacent; + ++st.mgmt; continue; } if (ncl.verdict == NameVerdict::Rail) { diff --git a/src/core/domain/analysis.hpp b/src/core/domain/analysis.hpp index 01ad450..e57c94d 100644 --- a/src/core/domain/analysis.hpp +++ b/src/core/domain/analysis.hpp @@ -62,8 +62,8 @@ struct SignalTypeInferenceStats { int power = 0; ///< Signals promoted to Power (name + structural). int gnd = 0; ///< Signals promoted to GndShield (name only). int kept_other = 0; ///< Name said Power but structural evidence too weak. - int adjacent = 0; ///< Rail token + control token (SENSE/EN/PG/…) → - ///< confidently Other, never suspect. + int mgmt = 0; ///< Power-management signal (rail + SENSE/EN/PG/… + ///< token) → confidently Other, never suspect. }; // Thresholds used by `infer_signal_types` (re-exposed so the analyze screen diff --git a/src/core/domain/signal_type.hpp b/src/core/domain/signal_type.hpp index 135575f..44dcda2 100644 --- a/src/core/domain/signal_type.hpp +++ b/src/core/domain/signal_type.hpp @@ -5,16 +5,17 @@ enum class SignalType { Power, GndShield, Other }; -// Name-level verdict, richer than SignalType. `PowerAdjacent` is the key +// Name-level verdict, richer than SignalType. `PowerMgmt` is the key // addition: a name holding BOTH a rail token (VCC/VDD/PWR/…) and a control -// token (SENSE/EN/PG/FB/…) is a signal *about* a rail — measurement, enable, -// power-good — not the rail itself. Its non-Power classification is therefore -// confident, where a bare rail name without structural evidence stays suspect. -enum class NameVerdict { Rail, GndShield, PowerAdjacent, Other }; +// token (SENSE/EN/PG/FB/…) is a power-management signal — measurement, +// enable, power-good — not the rail itself. Its non-Power classification is +// therefore confident, where a bare rail name without structural evidence +// stays suspect. +enum class NameVerdict { Rail, GndShield, PowerMgmt, Other }; struct NameClassification { NameVerdict verdict = NameVerdict::Other; - std::string token; ///< PowerAdjacent only: the control token that decided it. + std::string token; ///< PowerMgmt only: the control token that decided it. }; NameClassification classify_signal_name(const std::string &signal_name); @@ -22,7 +23,7 @@ NameClassification classify_signal_name(const std::string &signal_name); const char *signal_type_name(SignalType t); bool signal_type_from_name(const std::string &s, SignalType &out); // Thin wrapper over classify_signal_name: Rail → Power, GndShield → GndShield, -// PowerAdjacent/Other → Other. +// PowerMgmt/Other → Other. SignalType infer_signal_type(const std::string &signal_name); SignalType next_signal_type(SignalType t); // Power → GndShield → Other → Power diff --git a/src/core/domain/signals.cpp b/src/core/domain/signals.cpp index 13fb00b..6166cdd 100644 --- a/src/core/domain/signals.cpp +++ b/src/core/domain/signals.cpp @@ -101,7 +101,7 @@ std::vector alnum_tokens(const std::string &u) { // reliable there — left out of the control-token logic on purpose). Names // containing PWR/POWER/VCC/VDD/VEE/VSS, or starting with VS_/VBAT/+/− → rail // candidates; a rail candidate whose tokens include a control word (SENSE, -// EN, PG, …) is downgraded to PowerAdjacent. Else Other. +// EN, PG, …) is downgraded to PowerMgmt. Else Other. NameClassification classify_signal_name(const std::string &name) { NameClassification out; if (name.empty()) return out; @@ -133,7 +133,7 @@ NameClassification classify_signal_name(const std::string &name) { || starts_with("+") || starts_with("-")) { for (const std::string &tok : alnum_tokens(u)) { if (is_power_control_token(tok)) { - out.verdict = NameVerdict::PowerAdjacent; + out.verdict = NameVerdict::PowerMgmt; out.token = tok; return out; } @@ -148,7 +148,7 @@ SignalType infer_signal_type(const std::string &name) { switch (classify_signal_name(name).verdict) { case NameVerdict::Rail: return SignalType::Power; case NameVerdict::GndShield: return SignalType::GndShield; - case NameVerdict::PowerAdjacent: + case NameVerdict::PowerMgmt: case NameVerdict::Other: break; } return SignalType::Other; diff --git a/src/frontends/tui/commands.cpp b/src/frontends/tui/commands.cpp index c80dab4..4eaa224 100644 --- a/src/frontends/tui/commands.cpp +++ b/src/frontends/tui/commands.cpp @@ -153,8 +153,8 @@ void Tui::RegisterCommands() { + std::to_string(r.gnd) + " gnd, " + std::to_string(r.kept_other) + " suspect Power (name only — kept as Other), " - + std::to_string(r.adjacent) - + " power-adjacent (control — kept as Other)"); + + std::to_string(r.mgmt) + + " power-management (control/measure — kept as Other)"); }, /*prompt_for_missing=*/ true, "load a module from a netlist / pinout file (mentor, altium, ods)", diff --git a/src/frontends/tui/screen_analyze.cpp b/src/frontends/tui/screen_analyze.cpp index c2f6407..d9a9eba 100644 --- a/src/frontends/tui/screen_analyze.cpp +++ b/src/frontends/tui/screen_analyze.cpp @@ -131,7 +131,7 @@ Component Tui::BuildAnalyzeScreen() { // ============================================================= Types // Power decisions (confirmed / refuted) and NC orphan breakdown. analyze_types.clear(); - int conf_pwr = 0, ref_pwr = 0, adj = 0, gnd = 0; + int conf_pwr = 0, ref_pwr = 0, mgmt = 0, gnd = 0; struct Row { char kind; std::string mod, sig; int fanout; bool voltage; std::string token; }; std::vector rows; @@ -148,8 +148,8 @@ Component Tui::BuildAnalyzeScreen() { kind = 'P'; ++conf_pwr; } else if (ncl.verdict == NameVerdict::Rail && s->type == SignalType::Other) { kind = 'R'; ++ref_pwr; - } else if (ncl.verdict == NameVerdict::PowerAdjacent) { - kind = 'A'; ++adj; token = ncl.token; + } else if (ncl.verdict == NameVerdict::PowerMgmt) { + kind = 'M'; ++mgmt; token = ncl.token; } else continue; rows.push_back({kind, mod->name, s->name, (int)s->size(), has_voltage_pattern(s->name), @@ -157,9 +157,9 @@ Component Tui::BuildAnalyzeScreen() { } } // Deliberate display order: confirmed rails, then the suspects (the - // actionable residue), then the power-adjacent controls, gnd last. + // actionable residue), then the power-management signals, gnd last. auto rank = [](char k) { - return k == 'P' ? 0 : k == 'R' ? 1 : k == 'A' ? 2 : 3; + return k == 'P' ? 0 : k == 'R' ? 1 : k == 'M' ? 2 : 3; }; std::sort(rows.begin(), rows.end(), [&](const Row &a, const Row &b) { @@ -191,8 +191,8 @@ Component Tui::BuildAnalyzeScreen() { else reason = "name only — fan-out " + std::to_string(r.fanout) + ", no voltage"; - } else if (r.kind == 'A') { - tag = "[Pwr-adjacent] "; + } else if (r.kind == 'M') { + tag = "[Power mgmt] "; reason = "control token '" + r.token + "' in name — kept as Other"; } else { @@ -214,8 +214,8 @@ Component Tui::BuildAnalyzeScreen() { std::string types_header = "Types: " + std::to_string(conf_pwr) + " Power, " + std::to_string(ref_pwr) - + " Suspect, " + std::to_string(adj) - + " Adjacent, " + std::to_string(gnd) + + " Suspect, " + std::to_string(mgmt) + + " Pwr-mgmt, " + std::to_string(gnd) + " Gnd"; // Tab bar — horizontal headers, active one inverted. @@ -258,10 +258,11 @@ Component Tui::BuildAnalyzeScreen() { "Name suggests Power, no control token explains it, but the " "structural check failed — fan-out too low and no voltage " "in the name."), - term("Pwr-adjacent", + term("Power mgmt", "Name holds a rail token AND a control token (SENSE, EN, PG, " - "FB, …): a signal about a rail — measurement or control — " - "not the rail itself. Confidently Other, never suspect."), + "FB, …): a power-management signal — measurement or control " + "of a rail — not the rail itself. Confidently Other, never " + "suspect."), term("Hard floor", "Fan-out below 3 pins forces Other regardless of the name. " "A real rail physically cannot live on 1-2 pads."), diff --git a/src/frontends/wx/wx_frame.cpp b/src/frontends/wx/wx_frame.cpp index 4cf067e..062d75a 100644 --- a/src/frontends/wx/wx_frame.cpp +++ b/src/frontends/wx/wx_frame.cpp @@ -352,9 +352,9 @@ void EssimFrame::OnLoad(wxCommandEvent &) { } Log(wxString::Format( "loaded '%s' from %s — %d part(s), %d signal(s)" - " (dropped %d; types: %d power / %d gnd / %d suspect / %d pwr-adjacent)", + " (dropped %d; types: %d power / %d gnd / %d suspect / %d pwr-mgmt)", modname, path, r.parts, r.signals, r.dropped, r.power, r.gnd, - r.kept_other, r.adjacent)); + r.kept_other, r.mgmt)); RebuildModelView(); } diff --git a/tests/test_analysis.cpp b/tests/test_analysis.cpp index 4810ccc..2d14a9b 100644 --- a/tests/test_analysis.cpp +++ b/tests/test_analysis.cpp @@ -235,7 +235,7 @@ TEST_CASE("infer_signal_types: Power requires name+structural agreement") { Signal *p_3v3 = m->signals->merge("PWR_3V3"); fan_out(p_3v3, 3); // voltage + ≥ floor → Power Signal *vcc = m->signals->merge("VCC"); fan_out(vcc, 5); // fan-out ≥ 4 → Power - Signal *pwr_ok = m->signals->merge("PWR_OK"); fan_out(pwr_ok, 1); // control token → adjacent + Signal *pwr_ok = m->signals->merge("PWR_OK"); fan_out(pwr_ok, 1); // control token → pwr-mgmt Signal *pwr_2 = m->signals->merge("PWR_2"); fan_out(pwr_2, 2); // < 3 → hard floor → Other Signal *gnd = m->signals->merge("GND"); fan_out(gnd, 1); // gnd: name alone Signal *clk = m->signals->merge("CLK_50MHZ"); fan_out(clk, 3); // not power-ish → Other @@ -244,7 +244,7 @@ TEST_CASE("infer_signal_types: Power requires name+structural agreement") { CHECK(st.power == 2); // PWR_3V3, VCC CHECK(st.gnd == 1); // GND (name alone) CHECK(st.kept_other == 1); // PWR_2 below the hard floor - CHECK(st.adjacent == 1); // PWR_OK: power-good control, not suspect + CHECK(st.mgmt == 1); // PWR_OK: power-good control, not suspect CHECK(p_3v3->type == SignalType::Power); CHECK(vcc->type == SignalType::Power); @@ -254,14 +254,14 @@ TEST_CASE("infer_signal_types: Power requires name+structural agreement") { CHECK(clk->type == SignalType::Other); } -TEST_CASE("infer_signal_types: power-adjacent beats fan-out — a big sense net is still Other") { +TEST_CASE("infer_signal_types: power-management beats fan-out — a big sense net is still Other") { auto sys = std::make_unique(); Module *m = sys->modules()->merge("M"); Part *p = new Part("U1"); m->add(p); // VDD_CORE_SENSE with fan-out 5: structure alone would confirm Power, // but the control token settles it as a measurement net → Other, - // counted adjacent (not suspect, not power). + // counted mgmt (not suspect, not power). Signal *s = m->signals->merge("VDD_CORE_SENSE"); for (int i = 0; i < 5; ++i) { Pin *pin = new Pin("p" + std::to_string(i)); @@ -271,7 +271,7 @@ TEST_CASE("infer_signal_types: power-adjacent beats fan-out — a big sense net auto st = infer_signal_types(sys.get()); CHECK(st.power == 0); CHECK(st.kept_other == 0); - CHECK(st.adjacent == 1); + CHECK(st.mgmt == 1); CHECK(s->type == SignalType::Other); } diff --git a/tests/test_signal_type.cpp b/tests/test_signal_type.cpp index 01aa352..c8c5497 100644 --- a/tests/test_signal_type.cpp +++ b/tests/test_signal_type.cpp @@ -51,40 +51,40 @@ TEST_CASE("infer_signal_type: power family") { CHECK(infer_signal_type("VS3_5V0") == SignalType::Power); CHECK(infer_signal_type("+5V") == SignalType::Power); CHECK(infer_signal_type("-12V") == SignalType::Power); - // Rail token + control token → power-adjacent, mapped to Other by the + // Rail token + control token → power-management, mapped to Other by the // wrapper (it is a sense line ABOUT VBAT, not the rail). CHECK(infer_signal_type("VBAT_SENSE") == SignalType::Other); } -TEST_CASE("classify_signal_name: rail vs power-adjacent control signals") { +TEST_CASE("classify_signal_name: rail vs power-management signals") { CHECK(classify_signal_name("VCC").verdict == NameVerdict::Rail); CHECK(classify_signal_name("VDD_3V3").verdict == NameVerdict::Rail); CHECK(classify_signal_name("+5V").verdict == NameVerdict::Rail); NameClassification c = classify_signal_name("VDD_CORE_SENSE"); - CHECK(c.verdict == NameVerdict::PowerAdjacent); + CHECK(c.verdict == NameVerdict::PowerMgmt); CHECK(c.token == "SENSE"); - CHECK(classify_signal_name("VBAT_SENSE").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VCC_EN").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VCC_EN1").verdict == NameVerdict::PowerAdjacent); // trailing digit - CHECK(classify_signal_name("VDD_FB").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("PWR_GOOD").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("PWR_OK").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VBUS_DET").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("POWER_FAIL").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VDD_VSENSE").verdict == NameVerdict::PowerAdjacent); // fused suffix - CHECK(classify_signal_name("PWR_NFAULT").verdict == NameVerdict::PowerAdjacent); // active-low - CHECK(classify_signal_name("VDD_ADJ").verdict == NameVerdict::PowerAdjacent); // regulator adjust - CHECK(classify_signal_name("VCC_TRIM").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VDD_VTRIM").verdict == NameVerdict::PowerAdjacent); // fused suffix - CHECK(classify_signal_name("VCC_VSET").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("VCC_FBK").verdict == NameVerdict::PowerAdjacent); // feedback variants - CHECK(classify_signal_name("VDD_FDB").verdict == NameVerdict::PowerAdjacent); - CHECK(classify_signal_name("PWR_CMD").verdict == NameVerdict::PowerAdjacent); // command - CHECK(classify_signal_name("PWR_LED").verdict == NameVerdict::PowerAdjacent); // indicator - CHECK(classify_signal_name("VDD_REF").verdict == NameVerdict::PowerAdjacent); // reference - CHECK(classify_signal_name("VCC_VREF").verdict == NameVerdict::PowerAdjacent); + CHECK(classify_signal_name("VBAT_SENSE").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VCC_EN").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VCC_EN1").verdict == NameVerdict::PowerMgmt); // trailing digit + CHECK(classify_signal_name("VDD_FB").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("PWR_GOOD").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("PWR_OK").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VBUS_DET").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("POWER_FAIL").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VDD_VSENSE").verdict == NameVerdict::PowerMgmt); // fused suffix + CHECK(classify_signal_name("PWR_NFAULT").verdict == NameVerdict::PowerMgmt); // active-low + CHECK(classify_signal_name("VDD_ADJ").verdict == NameVerdict::PowerMgmt); // regulator adjust + CHECK(classify_signal_name("VCC_TRIM").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VDD_VTRIM").verdict == NameVerdict::PowerMgmt); // fused suffix + CHECK(classify_signal_name("VCC_VSET").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("VCC_FBK").verdict == NameVerdict::PowerMgmt); // feedback variants + CHECK(classify_signal_name("VDD_FDB").verdict == NameVerdict::PowerMgmt); + CHECK(classify_signal_name("PWR_CMD").verdict == NameVerdict::PowerMgmt); // command + CHECK(classify_signal_name("PWR_LED").verdict == NameVerdict::PowerMgmt); // indicator + CHECK(classify_signal_name("VDD_REF").verdict == NameVerdict::PowerMgmt); // reference + CHECK(classify_signal_name("VCC_VREF").verdict == NameVerdict::PowerMgmt); // Whole-token matching: SENSOR is not SENSE, GREEN is not EN — // these stay genuine rails.