Extract verify into core (app::verify); thin the TUI command.
Move the 7-pass verify orchestration out of the TUI command lambda and
into core/app/verify.{hpp,cpp}: app::verify(System*) returns a structured
VerifyReport (role mismatches, net inconsistencies, orphan counts, the four
model-driven anomaly vectors) with no Print/dialog/FTXUI. The nets are
computed once and fed to the net-based checks.
The verify command is now a thin renderer over the report, byte-identical
output. Prune the now-dead nets.hpp / bsdl_check.hpp / <unordered_set>
includes from commands.cpp.
Add tests/test_verify.cpp: builds small systems by hand and asserts the
report (empty system, Power/GndShield bridged-net inconsistency, orphan
counts by import origin) — pure core, no UI.
This is the structuring extraction: the same VerifyReport can now back the
analyze screen's Issues pane and the dashboard health rows, removing the
triple duplication of passes 1-3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
98
src/core/app/verify.cpp
Normal file
98
src/core/app/verify.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "core/app/verify.hpp"
|
||||
|
||||
#include "core/domain/bsdl_check.hpp"
|
||||
#include "core/domain/connect.hpp"
|
||||
#include "core/domain/modules.hpp"
|
||||
#include "core/domain/nets.hpp"
|
||||
#include "core/domain/parts.hpp"
|
||||
#include "core/domain/pins.hpp"
|
||||
#include "core/domain/signals.hpp"
|
||||
#include "core/domain/system.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace app {
|
||||
|
||||
VerifyReport verify(System *sys)
|
||||
{
|
||||
VerifyReport r;
|
||||
if (!sys)
|
||||
return r;
|
||||
|
||||
// Pass 1 — typed pins: expected (model) vs actual (net) signal type.
|
||||
for (auto &mkv : *sys->modules()) {
|
||||
Module *mod = mkv.second;
|
||||
for (auto &pkv : *mod) {
|
||||
Part *prt = pkv.second;
|
||||
if (prt->connector_type.empty())
|
||||
continue;
|
||||
for (auto &nkv : *prt) {
|
||||
Pin *pin = nkv.second;
|
||||
++r.typed_pins;
|
||||
SignalType expected = pin->expected_signal_type();
|
||||
if (expected == SignalType::Other)
|
||||
continue;
|
||||
Signal *s = pin->signal();
|
||||
SignalType actual = s ? s->type : SignalType::Other;
|
||||
if (actual == expected)
|
||||
continue;
|
||||
RoleMismatch m;
|
||||
m.module = mod->name;
|
||||
m.part = prt->name;
|
||||
m.pin = pin->name;
|
||||
m.signal = s ? s->name : std::string("(NC)");
|
||||
m.expected = expected;
|
||||
m.actual = actual;
|
||||
r.role_mismatches.push_back(std::move(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2 — bridged nets: flag Power/GndShield mixing. Compute the nets once
|
||||
// here and reuse them for the model checks below.
|
||||
std::vector<Net> nets = compute_all_nets(sys);
|
||||
r.total_nets = (int)nets.size();
|
||||
for (const Net &n : nets) {
|
||||
if (n.members.size() < 2)
|
||||
continue;
|
||||
++r.bridged_nets;
|
||||
SignalType dom;
|
||||
if (net_type_consistent(n, dom))
|
||||
continue;
|
||||
NetInconsistency ni;
|
||||
for (const auto &mp : n.members)
|
||||
ni.members.push_back({mp.first->name, mp.second->name, mp.second->type});
|
||||
r.net_inconsistencies.push_back(std::move(ni));
|
||||
}
|
||||
|
||||
// Pass 3 — orphans: pins with no signal and not bridged via a connection.
|
||||
std::unordered_set<Pin *> bridged_pins;
|
||||
for (auto &ckv : *sys->connections())
|
||||
for (auto &wp : ckv.second->pin_map) {
|
||||
if (wp.first) bridged_pins.insert(wp.first);
|
||||
if (wp.second) bridged_pins.insert(wp.second);
|
||||
}
|
||||
for (auto &mkv : *sys->modules())
|
||||
for (auto &pkv : *mkv.second)
|
||||
for (auto &nkv : *pkv.second) {
|
||||
Pin *pin = nkv.second;
|
||||
if (pin->signal() || bridged_pins.count(pin))
|
||||
continue;
|
||||
if (pin->nc_origin == NcOrigin::ImportedUnconnected)
|
||||
++r.orphan_imported;
|
||||
else if (pin->nc_origin == NcOrigin::DroppedSingleton)
|
||||
++r.orphan_dropped;
|
||||
}
|
||||
|
||||
// Passes 4-7 — model-driven checks (reuse the nets from pass 2).
|
||||
r.pin_anomalies = check_pin_specs(sys, &nets);
|
||||
r.jtag_anomalies = check_jtag_chain(sys, &nets);
|
||||
r.conflict_anomalies = check_source_conflicts(sys);
|
||||
r.completeness_anomalies = check_bsdl_completeness(sys);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
61
src/core/app/verify.hpp
Normal file
61
src/core/app/verify.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef _APP_VERIFY_HPP_
|
||||
#define _APP_VERIFY_HPP_
|
||||
|
||||
#include "core/domain/analysis.hpp" // Anomaly
|
||||
#include "core/domain/signal_type.hpp" // SignalType
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class System;
|
||||
|
||||
namespace app {
|
||||
|
||||
// One typed-pin role mismatch: the connector/BSDL expectation disagrees with
|
||||
// the actual net type.
|
||||
struct RoleMismatch {
|
||||
std::string module, part, pin;
|
||||
std::string signal; ///< signal name, or "(NC)"
|
||||
SignalType expected = SignalType::Other;
|
||||
SignalType actual = SignalType::Other;
|
||||
};
|
||||
|
||||
// One bridged net mixing Power and GndShield, with its members for display.
|
||||
struct NetInconsistency {
|
||||
struct Member { std::string module, signal; SignalType type; };
|
||||
std::vector<Member> members;
|
||||
};
|
||||
|
||||
// The full result of `verify`: structured data only — no strings beyond the
|
||||
// names, no formatting. Frontends (the verify command, the analyze screen, the
|
||||
// dashboard) render it however they like.
|
||||
struct VerifyReport {
|
||||
int typed_pins = 0; ///< pins with a non-Other expectation considered
|
||||
std::vector<RoleMismatch> role_mismatches;
|
||||
|
||||
int total_nets = 0;
|
||||
int bridged_nets = 0;
|
||||
std::vector<NetInconsistency> net_inconsistencies;
|
||||
|
||||
int orphan_imported = 0;
|
||||
int orphan_dropped = 0;
|
||||
|
||||
std::vector<Anomaly> pin_anomalies; ///< check_pin_specs
|
||||
std::vector<Anomaly> jtag_anomalies; ///< check_jtag_chain
|
||||
std::vector<Anomaly> conflict_anomalies; ///< check_source_conflicts
|
||||
std::vector<Anomaly> completeness_anomalies; ///< check_bsdl_completeness
|
||||
|
||||
int orphan_total() const { return orphan_imported + orphan_dropped; }
|
||||
int model_total() const {
|
||||
return (int)(pin_anomalies.size() + jtag_anomalies.size()
|
||||
+ conflict_anomalies.size() + completeness_anomalies.size());
|
||||
}
|
||||
};
|
||||
|
||||
// Run every verify pass over the system and return the findings. Pure core —
|
||||
// computes the nets once and feeds them to the net-based checks.
|
||||
VerifyReport verify(System *sys);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif // _APP_VERIFY_HPP_
|
||||
Reference in New Issue
Block a user