P3: BSDL completeness check (missing device power/ground pins)
check_bsdl_completeness(System*): for each BSDL-attached part, re-parse the .bsd and report the device power/ground ports with no matching pin on the netlist part (matched by port name or physical pad) — a rail the schematic symbol is missing. One aggregated BsdlPinMissing per part; restricted to power/ground so unused I/O balls don't create noise. Surfaced as a 7th verify pass and in the analyze/dashboard model counts. 76 cases / 327 assertions green; the real 8-card system reports 0 (all FPGA rails present). This closes out P3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ const char *anomaly_kind_name(AnomalyKind k) {
|
||||
case AnomalyKind::JtagChainBreak: return "jtag-chain-break";
|
||||
case AnomalyKind::JtagBusUnbridged: return "jtag-bus-unbridged";
|
||||
case AnomalyKind::SourceConflict: return "source-conflict";
|
||||
case AnomalyKind::BsdlPinMissing: return "bsdl-pin-missing";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ enum class AnomalyKind {
|
||||
JtagChainBreak, ///< The TDO→TDI daisy chain is broken / not a single path.
|
||||
JtagBusUnbridged, ///< TMS or TCK is not common to all TAP devices.
|
||||
SourceConflict, ///< A model contradicts the netlist (e.g. BSDL power pin left NC).
|
||||
BsdlPinMissing, ///< A BSDL power/ground port has no pin on the netlist part.
|
||||
};
|
||||
|
||||
struct Anomaly {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "bsdl_check.hpp"
|
||||
|
||||
#include "bsdl_model.hpp"
|
||||
#include "connect.hpp"
|
||||
#include "modules.hpp"
|
||||
#include "nets.hpp"
|
||||
@@ -325,3 +326,54 @@ std::vector<Anomaly> check_source_conflicts(System *sys)
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<Anomaly> check_bsdl_completeness(System *sys)
|
||||
{
|
||||
std::vector<Anomaly> out;
|
||||
if (!sys)
|
||||
return out;
|
||||
|
||||
for (auto &mkv : *sys->modules())
|
||||
for (auto &pkv : *mkv.second) {
|
||||
Part *part = pkv.second;
|
||||
if (part->bsdl_path.empty())
|
||||
continue;
|
||||
BsdlModel model = BsdlModel::from_file(part->bsdl_path);
|
||||
if (!model.valid())
|
||||
continue;
|
||||
|
||||
std::vector<std::string> missing; // absent power/ground ports
|
||||
for (const auto &port : model.ports()) {
|
||||
if (port.function != PinFunction::Power &&
|
||||
port.function != PinFunction::Ground)
|
||||
continue; // only must-have rails — unused I/O may be absent
|
||||
bool present = (!port.name.empty() && part->exists(port.name)) ||
|
||||
(!port.pad.empty() && part->exists(port.pad));
|
||||
if (!present) {
|
||||
std::string lbl = port.name;
|
||||
if (!port.pad.empty())
|
||||
lbl += "@" + port.pad;
|
||||
missing.push_back(lbl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!missing.empty()) {
|
||||
std::string examples;
|
||||
for (size_t i = 0; i < missing.size() && i < 5; ++i)
|
||||
examples += (examples.empty() ? "" : ", ") + missing[i];
|
||||
if (missing.size() > 5)
|
||||
examples += ", …";
|
||||
|
||||
Anomaly a;
|
||||
a.kind = AnomalyKind::BsdlPinMissing;
|
||||
a.module = part->prnt;
|
||||
a.message = mkv.first + "/" + part->name + ": "
|
||||
+ std::to_string(missing.size())
|
||||
+ " device power/ground pin(s) absent from the netlist ("
|
||||
+ examples + ")";
|
||||
out.push_back(std::move(a));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -36,4 +36,11 @@ std::vector<Anomaly> check_jtag_chain(System *sys, const std::vector<Net> *nets
|
||||
// schematic. The reverse (BSDL no-connect wired in the netlist) is `NcWired`.
|
||||
std::vector<Anomaly> check_source_conflicts(System *sys);
|
||||
|
||||
// Completeness: for every part with an attached BSDL, the device's power/ground
|
||||
// ports that have no matching pin on the netlist part (matched by port name or
|
||||
// physical pad) — i.e. a power/ground pin the schematic symbol is missing. One
|
||||
// aggregated anomaly per part. Re-parses each attached `.bsd` (no model cache on
|
||||
// Part yet), so it's bounded by the number of BSDL-attached parts.
|
||||
std::vector<Anomaly> check_bsdl_completeness(System *sys);
|
||||
|
||||
#endif // _BSDL_CHECK_HPP_
|
||||
|
||||
@@ -319,6 +319,13 @@ void Tui::RegisterCommands() {
|
||||
Print(" [" + std::string(anomaly_kind_name(a.kind)) + "] " + a.message);
|
||||
Print("verify: " + std::to_string(conflict_anoms.size())
|
||||
+ " source-conflict(s).");
|
||||
|
||||
// BSDL completeness: device power/ground pins missing from the netlist.
|
||||
auto missing_anoms = check_bsdl_completeness(sys.get());
|
||||
for (const auto &a : missing_anoms)
|
||||
Print(" [" + std::string(anomaly_kind_name(a.kind)) + "] " + a.message);
|
||||
Print("verify: " + std::to_string(missing_anoms.size())
|
||||
+ " BSDL completeness issue(s).");
|
||||
}, true,
|
||||
"check pin roles, bridged-net consistency, and model-driven pin specs (contention/undriven/NC)" };
|
||||
|
||||
|
||||
@@ -106,9 +106,11 @@ Component Tui::BuildAnalyzeScreen() {
|
||||
auto a1 = check_pin_specs(sys.get(), &nets);
|
||||
auto a2 = check_jtag_chain(sys.get(), &nets);
|
||||
auto a3 = check_source_conflicts(sys.get());
|
||||
auto a4 = check_bsdl_completeness(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());
|
||||
model_anoms.insert(model_anoms.end(), a4.begin(), a4.end());
|
||||
}
|
||||
for (const auto &a : model_anoms)
|
||||
analyze_issues.push_back(std::string("[")
|
||||
|
||||
@@ -154,7 +154,8 @@ Component Tui::BuildDashboardScreen() {
|
||||
// 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());
|
||||
+ check_source_conflicts(sys.get()).size()
|
||||
+ check_bsdl_completeness(sys.get()).size());
|
||||
health_rows.push_back(health_line(n_model == 0,
|
||||
"model: " + std::to_string(n_model) + " BSDL/JTAG anomaly(ies)"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user