P3.3: surface model anomalies in analyze + dashboard
The analyze screen's Issues pane now lists the model-driven checks (check_pin_specs / check_jtag_chain / check_source_conflicts) alongside the pin-role, net-mix and structural ones, with an "N model" count in the header; the dashboard gains a "model:" health row. check_pin_specs/check_jtag_chain take an optional precomputed net list, so verify, analyze and the dashboard each compute the nets once and reuse them across checks instead of redoing the transitive closure per check. Unit tests (75) green; verify output unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,13 +39,16 @@ std::string join_labels(const std::vector<Pin *> &pins)
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<Anomaly> check_pin_specs(System *sys)
|
||||
std::vector<Anomaly> check_pin_specs(System *sys, const std::vector<Net> *nets)
|
||||
{
|
||||
std::vector<Anomaly> out;
|
||||
if (!sys)
|
||||
return out;
|
||||
|
||||
for (const Net &net : compute_all_nets(sys)) {
|
||||
std::vector<Net> local;
|
||||
if (!nets)
|
||||
local = compute_all_nets(sys);
|
||||
for (const Net &net : (nets ? *nets : local)) {
|
||||
std::vector<Pin *> pins;
|
||||
std::vector<Signal *> sigs;
|
||||
Module *mod = nullptr;
|
||||
@@ -123,14 +126,17 @@ std::vector<Anomaly> check_pin_specs(System *sys)
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<Anomaly> check_jtag_chain(System *sys)
|
||||
std::vector<Anomaly> check_jtag_chain(System *sys, const std::vector<Net> *nets_in)
|
||||
{
|
||||
std::vector<Anomaly> out;
|
||||
if (!sys)
|
||||
return out;
|
||||
|
||||
// Map every pin to the index of the net it sits on.
|
||||
std::vector<Net> nets = compute_all_nets(sys);
|
||||
std::vector<Net> local;
|
||||
if (!nets_in)
|
||||
local = compute_all_nets(sys);
|
||||
const std::vector<Net> &nets = nets_in ? *nets_in : local;
|
||||
std::unordered_map<Pin *, int> net_of;
|
||||
for (size_t i = 0; i < nets.size(); ++i)
|
||||
for (auto &mp : nets[i].members)
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
#define _BSDL_CHECK_HPP_
|
||||
|
||||
#include "analysis.hpp" // Anomaly, AnomalyKind
|
||||
#include "nets.hpp" // Net
|
||||
|
||||
#include <vector>
|
||||
|
||||
class System;
|
||||
|
||||
// The net checks below accept an optional precomputed net list: callers that
|
||||
// already have one (verify, the analyze screen, the dashboard) pass it so the
|
||||
// transitive-closure pass isn't redone. Pass nullptr to compute it internally.
|
||||
|
||||
// Model-driven pin checks over the system's nets, using the PinSpec
|
||||
// direction/function populated by connector or BSDL models. Emits:
|
||||
// - DriveContention : a net with ≥2 push-pull output drivers;
|
||||
@@ -14,7 +19,7 @@ class System;
|
||||
// - NcWired : a no-connect pin wired onto a multi-pin net.
|
||||
// Read-only; nets with no direction data are skipped (no false positives on
|
||||
// un-modelled parts).
|
||||
std::vector<Anomaly> check_pin_specs(System *sys);
|
||||
std::vector<Anomaly> check_pin_specs(System *sys, const std::vector<Net> *nets = nullptr);
|
||||
|
||||
// JTAG boundary-scan chain integrity, using pins whose PinSpec.function is a TAP
|
||||
// role (JtagTdi/Tdo/Tms/Tck/Trst). Resolves each TAP pin to its net and checks:
|
||||
@@ -23,7 +28,7 @@ std::vector<Anomaly> check_pin_specs(System *sys);
|
||||
// - JtagChainBreak : the TDO→TDI daisy chain dangles, fans out, or is not a
|
||||
// single path (≠1 head / ≠1 tail).
|
||||
// Empty when the system has no TAP pins.
|
||||
std::vector<Anomaly> check_jtag_chain(System *sys);
|
||||
std::vector<Anomaly> check_jtag_chain(System *sys, const std::vector<Net> *nets = nullptr);
|
||||
|
||||
// Conflicts between a device model and the netlist's own view of a pin. Today:
|
||||
// a pin the BSDL declares power/ground (a must-connect rail) that the netlist
|
||||
|
||||
@@ -300,14 +300,14 @@ void Tui::RegisterCommands() {
|
||||
|
||||
// Model-driven pin checks (drive contention / undriven net / NC-wired)
|
||||
// from the PinSpec direction/function populated by connector/BSDL models.
|
||||
auto pin_anoms = check_pin_specs(sys.get());
|
||||
auto pin_anoms = check_pin_specs(sys.get(), &nets);
|
||||
for (const auto &a : pin_anoms)
|
||||
Print(" [" + std::string(anomaly_kind_name(a.kind)) + "] " + a.message);
|
||||
Print("verify: " + std::to_string(pin_anoms.size())
|
||||
+ " model-driven pin anomaly(ies).");
|
||||
|
||||
// JTAG boundary-scan chain integrity (TAP pins → nets).
|
||||
auto jtag_anoms = check_jtag_chain(sys.get());
|
||||
auto jtag_anoms = check_jtag_chain(sys.get(), &nets);
|
||||
for (const auto &a : jtag_anoms)
|
||||
Print(" [" + std::string(anomaly_kind_name(a.kind)) + "] " + a.message);
|
||||
Print("verify: " + std::to_string(jtag_anoms.size())
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "tui/tui_helpers.hpp"
|
||||
|
||||
#include "system/analysis.hpp"
|
||||
#include "system/bsdl_check.hpp"
|
||||
#include "system/connect.hpp"
|
||||
#include "system/modules.hpp"
|
||||
#include "system/nets.hpp"
|
||||
@@ -99,16 +100,33 @@ Component Tui::BuildAnalyzeScreen() {
|
||||
+ anomaly_kind_name(a.kind) + "] "
|
||||
+ a.message);
|
||||
|
||||
// Model-driven checks (same as `verify`), reusing the nets above.
|
||||
std::vector<Anomaly> model_anoms;
|
||||
{
|
||||
auto a1 = check_pin_specs(sys.get(), &nets);
|
||||
auto a2 = check_jtag_chain(sys.get(), &nets);
|
||||
auto a3 = check_source_conflicts(sys.get());
|
||||
model_anoms.insert(model_anoms.end(), a1.begin(), a1.end());
|
||||
model_anoms.insert(model_anoms.end(), a2.begin(), a2.end());
|
||||
model_anoms.insert(model_anoms.end(), a3.begin(), a3.end());
|
||||
}
|
||||
for (const auto &a : model_anoms)
|
||||
analyze_issues.push_back(std::string("[")
|
||||
+ anomaly_kind_name(a.kind) + "] "
|
||||
+ a.message);
|
||||
int n_model = (int)model_anoms.size();
|
||||
|
||||
if (analyze_issues.empty()) analyze_issues.push_back("(no issue found)");
|
||||
if (analyze_issue_idx >= (int)analyze_issues.size())
|
||||
analyze_issue_idx = (int)analyze_issues.size() - 1;
|
||||
|
||||
std::string issues_header = "Issues ("
|
||||
+ std::to_string(n_role_mismatches + n_inconsistent
|
||||
+ (int)rep.anomalies.size())
|
||||
+ (int)rep.anomalies.size() + n_model)
|
||||
+ ": " + std::to_string(n_role_mismatches) + " pin-role, "
|
||||
+ std::to_string(n_inconsistent) + " net-mix, "
|
||||
+ std::to_string(rep.anomalies.size()) + " struct.)";
|
||||
+ std::to_string(rep.anomalies.size()) + " struct, "
|
||||
+ std::to_string(n_model) + " model)";
|
||||
|
||||
// ============================================================ Groups
|
||||
analyze_groups.clear();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "tui/tui_helpers.hpp"
|
||||
|
||||
#include "system/analysis.hpp"
|
||||
#include "system/bsdl_check.hpp"
|
||||
#include "system/connect.hpp"
|
||||
#include "system/modules.hpp"
|
||||
#include "system/nets.hpp"
|
||||
@@ -149,6 +150,14 @@ Component Tui::BuildDashboardScreen() {
|
||||
+ std::to_string(orph_imported) + " imported, "
|
||||
+ std::to_string(orph_dropped) + " dropped)"));
|
||||
|
||||
// Model-driven checks (BSDL pin specs, JTAG chain, source conflicts),
|
||||
// reusing the nets computed above.
|
||||
int n_model = (int)(check_pin_specs(sys.get(), &nets).size()
|
||||
+ check_jtag_chain(sys.get(), &nets).size()
|
||||
+ check_source_conflicts(sys.get()).size());
|
||||
health_rows.push_back(health_line(n_model == 0,
|
||||
"model: " + std::to_string(n_model) + " BSDL/JTAG anomaly(ies)"));
|
||||
|
||||
// ---- analysis summary ----
|
||||
AnalysisReport rep = analyze_system(sys.get());
|
||||
int n_diff = 0, n_diff_bus = 0, n_bus = 0;
|
||||
|
||||
Reference in New Issue
Block a user