feat(sim): P2 wiring ERC slice 2 — VCC-to-GND short + shorted-out parts
- Power short (blocking error): a wire joining a VCC-type pin directly to a GND-type pin shorts the supply to ground. The current-based short-circuit rule only inspects battery/signal-generator/power-supply sources, so it misses a board-rail-to-GND short with no such source -> name it structurally. - Shorted-out part (warning): a 2-terminal part with both terminals on the same node has no effect on the circuit. Both graph-based, run before the solve. Zero false positives across the 69 gallery examples; gallery pre-flight tests still pass (no spurious blocking).
This commit is contained in:
parent
8683c1ecf0
commit
6f3603d88b
|
|
@ -426,6 +426,41 @@ describe('verifyCircuit — wiring ERC (bad connections)', () => {
|
|||
expect(mc, JSON.stringify(result.warnings)).toBeDefined();
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'errors when a VCC pin is wired directly to a GND pin',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
const input: BuildNetlistInput = {
|
||||
components: [{ id: 'o1', metadataId: 'ssd1306', properties: {} }],
|
||||
wires: [w('w1', ['o1', '3V3'], ['o1', 'GND'])], // VCC tied straight to GND
|
||||
boards: [],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
const codes = result.errors.map((e) => e.code);
|
||||
expect(codes, JSON.stringify(result.errors)).toContain('power-short');
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'warns when a part has both terminals on the same node (shorted out)',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
const input: BuildNetlistInput = {
|
||||
components: [pwr('src', 5), res('r1', '1k')],
|
||||
wires: [
|
||||
w('w1', ['src', 'SIG'], ['r1', '1']),
|
||||
w('w2', ['src', 'SIG'], ['r1', '2']), // both terminals on the SIG net
|
||||
],
|
||||
boards: [],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
const sc = result.warnings.find((x) => x.code === 'shorted-component' && x.componentId === 'r1');
|
||||
expect(sc, JSON.stringify(result.warnings)).toBeDefined();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// ── Sanity: shipping examples never trigger errors ─────────────────────────
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ export type WarningCode =
|
|||
| 'over-voltage'
|
||||
| 'reverse-polarity'
|
||||
| 'missing-connection'
|
||||
| 'power-short'
|
||||
| 'shorted-component'
|
||||
| 'resistor-overpower'
|
||||
| 'led-no-current';
|
||||
|
||||
|
|
@ -211,6 +213,45 @@ export async function verifyCircuit(
|
|||
}
|
||||
}
|
||||
|
||||
// Power rail tied to ground: a wire directly joining a VCC-type pin and a
|
||||
// GND-type pin shorts the supply to ground. When a board drives the rail and
|
||||
// no battery/signal-generator source is present, the current-based
|
||||
// short-circuit rule (which only inspects those sources) misses it — so name
|
||||
// it structurally here. Blocking error.
|
||||
const VCC_PIN_RE = /^(vcc|vdd|vcc_rail|5v|3v3|3\.3v)$/i;
|
||||
const GND_PIN_RE = /^(gnd|vss|vee|ground|gnd\.\d+)$/i;
|
||||
let powerShortReported = false;
|
||||
for (const wire of input.wires) {
|
||||
const a = wire.start.pinName;
|
||||
const b = wire.end.pinName;
|
||||
const shorted = (VCC_PIN_RE.test(a) && GND_PIN_RE.test(b)) || (GND_PIN_RE.test(a) && VCC_PIN_RE.test(b));
|
||||
if (shorted && !powerShortReported) {
|
||||
powerShortReported = true;
|
||||
errors.push({
|
||||
severity: 'error',
|
||||
code: 'power-short',
|
||||
message: `Power is shorted to ground — a wire connects a VCC pin (${a}) directly to a ground pin (${b}). Remove that connection; it would dump the full supply current through the wire.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Two-terminal part shorted across itself: both terminals on the same net, so
|
||||
// it carries no voltage and has no effect on the circuit. Non-blocking hint.
|
||||
for (const comp of input.components) {
|
||||
const pins = twoTerminalPins(comp.metadataId);
|
||||
if (!pins) continue;
|
||||
const n0 = pinNetMap.get(`${comp.id}:${pins[0]}`) ?? (pins[0] === '−' ? pinNetMap.get(`${comp.id}:-`) : undefined);
|
||||
const n1 = pinNetMap.get(`${comp.id}:${pins[1]}`) ?? (pins[1] === '−' ? pinNetMap.get(`${comp.id}:-`) : undefined);
|
||||
if (n0 !== undefined && n1 !== undefined && n0 === n1) {
|
||||
warnings.push({
|
||||
severity: 'warning',
|
||||
code: 'shorted-component',
|
||||
componentId: comp.id,
|
||||
message: `${comp.metadataId} ${comp.id} has both terminals on the same node — it is shorted out and has no effect on the circuit.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let solve: ElectricalSolveResult | undefined;
|
||||
try {
|
||||
const cooked = await runSpice(netlist);
|
||||
|
|
|
|||
Loading…
Reference in New Issue