Signal-type popup, NC pin tagging, interactive viewer hygiene.
- Enter on a signal entry (net / explore) opens a modal popup to pick power / gnd / other. Recording is deduped: a sequence of toggles on the same signal collapses to a single `set-signal-type` line; no-op selections record nothing. - Bare interactive commands (the ones that open a full-screen mode) are no longer recorded by `script-save`. Their inline forms still are. Mutating actions inside a screen record their own canonical line. - Mentor importer treats signals whose name starts with `unconnected` as no-connect — the pin is kept on the part without a signal and tagged `ImportedUnconnected`. - `drop_singleton_signals` runs at the end of `load`: any signal with exactly one pin is detached (singletons are NC by definition); the pin is tagged `DroppedSingleton`. Count is reported inline. - `verify` gains a one-line orphan summary (imported NC / dropped singleton totals). Pins materialised by `FillIdentityNCs` are excluded via a `pin_map` filter — they are bridged to a real signal on the peer module and are not real NCs at system level. - NcOrigin tag is serialized in save snapshots as an optional 4th field on N records (backward-compatible). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
void Tui::RegisterCommands() {
|
||||
@@ -132,9 +133,12 @@ void Tui::RegisterCommands() {
|
||||
try {
|
||||
sys->Load(args[0], args[1], t);
|
||||
Module *mod = sys->modules()->get(args[0]);
|
||||
int dropped = drop_singleton_signals(mod->signals);
|
||||
Print("loaded '" + args[0] + "' from " + args[1]);
|
||||
Print(" parts: " + std::to_string(mod->size()));
|
||||
Print(" signals: " + std::to_string(mod->signals->size()));
|
||||
Print(" signals: " + std::to_string(mod->signals->size())
|
||||
+ (dropped ? " (dropped " + std::to_string(dropped)
|
||||
+ " singleton/NC signal(s))" : ""));
|
||||
} catch (const std::exception &e) {
|
||||
Print(std::string("load failed: ") + e.what());
|
||||
}
|
||||
@@ -249,6 +253,30 @@ void Tui::RegisterCommands() {
|
||||
Print("verify: " + std::to_string(inconsistent) + " inconsistent net(s) over "
|
||||
+ std::to_string(bridged) + " bridged net(s) ("
|
||||
+ std::to_string(nets.size()) + " total).");
|
||||
|
||||
// Orphan pin report. A pin is "orphan" if it came out of import (or
|
||||
// post-import drop) with no signal, and is still not bridged to a
|
||||
// real signal via any Connection::pin_map. Use `nc-export` for the
|
||||
// per-pin list.
|
||||
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);
|
||||
}
|
||||
int orph_imported = 0, orph_dropped = 0;
|
||||
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) ++orph_imported;
|
||||
else if (pin->nc_origin == NcOrigin::DroppedSingleton) ++orph_dropped;
|
||||
}
|
||||
Print("verify: " + std::to_string(orph_imported + orph_dropped)
|
||||
+ " orphan pin(s) at import ("
|
||||
+ std::to_string(orph_imported) + " imported NC, "
|
||||
+ std::to_string(orph_dropped) + " dropped singleton).");
|
||||
}, true,
|
||||
"check pin roles locally and signal-type consistency across bridged nets" };
|
||||
|
||||
@@ -653,6 +681,7 @@ void Tui::RegisterCommands() {
|
||||
Pin *sn = nkv.second;
|
||||
Pin *dn = new Pin(sn->name);
|
||||
dn->expected_signal_type = sn->expected_signal_type;
|
||||
dn->nc_origin = sn->nc_origin;
|
||||
dp->add(dn);
|
||||
if (sn->signal()) {
|
||||
Signal *ds = dst->signals->get(sn->signal()->name);
|
||||
|
||||
Reference in New Issue
Block a user