easyeda-mcp-pro 0.3.2 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +369 -52
- package/dist/bom-quality/adapter.d.ts +90 -0
- package/dist/bom-quality/adapter.js +295 -0
- package/dist/bom-quality/adapter.js.map +1 -0
- package/dist/bom-quality/index.d.ts +10 -0
- package/dist/bom-quality/index.js +9 -0
- package/dist/bom-quality/index.js.map +1 -0
- package/dist/bom-quality/quality.d.ts +28 -0
- package/dist/bom-quality/quality.js +179 -0
- package/dist/bom-quality/quality.js.map +1 -0
- package/dist/bom-quality/types.d.ts +94 -0
- package/dist/bom-quality/types.js +12 -0
- package/dist/bom-quality/types.js.map +1 -0
- package/dist/bridge/manager.d.ts +41 -0
- package/dist/bridge/manager.js +334 -47
- package/dist/bridge/manager.js.map +1 -1
- package/dist/bridge/protocol.d.ts +48 -1
- package/dist/bridge/protocol.js +43 -1
- package/dist/bridge/protocol.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -0
- package/dist/bridge/types.js +6 -0
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog/errors.d.ts +49 -0
- package/dist/catalog/errors.js +60 -0
- package/dist/catalog/errors.js.map +1 -0
- package/dist/catalog/index.d.ts +15 -0
- package/dist/catalog/index.js +17 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/schema.d.ts +268 -0
- package/dist/catalog/schema.js +245 -0
- package/dist/catalog/schema.js.map +1 -0
- package/dist/catalog/starter.d.ts +159 -0
- package/dist/catalog/starter.js +579 -0
- package/dist/catalog/starter.js.map +1 -0
- package/dist/catalog/validation.d.ts +48 -0
- package/dist/catalog/validation.js +263 -0
- package/dist/catalog/validation.js.map +1 -0
- package/dist/circuit/circuit-ir.d.ts +460 -0
- package/dist/circuit/circuit-ir.js +292 -0
- package/dist/circuit/circuit-ir.js.map +1 -0
- package/dist/circuit/compiler.d.ts +55 -0
- package/dist/circuit/compiler.js +197 -0
- package/dist/circuit/compiler.js.map +1 -0
- package/dist/circuit/design-intent.d.ts +94 -0
- package/dist/circuit/design-intent.js +118 -0
- package/dist/circuit/design-intent.js.map +1 -0
- package/dist/circuit/errors.d.ts +50 -0
- package/dist/circuit/errors.js +61 -0
- package/dist/circuit/errors.js.map +1 -0
- package/dist/circuit/index.d.ts +17 -0
- package/dist/circuit/index.js +18 -0
- package/dist/circuit/index.js.map +1 -0
- package/dist/circuit/types.d.ts +186 -0
- package/dist/circuit/types.js +123 -0
- package/dist/circuit/types.js.map +1 -0
- package/dist/cli/auto-setup.d.ts +5 -0
- package/dist/cli/auto-setup.js +355 -0
- package/dist/cli/auto-setup.js.map +1 -0
- package/dist/cli/client-definitions.d.ts +34 -0
- package/dist/cli/client-definitions.js +194 -0
- package/dist/cli/client-definitions.js.map +1 -0
- package/dist/cli/local-setup.d.ts +5 -1
- package/dist/cli/local-setup.js +40 -6
- package/dist/cli/local-setup.js.map +1 -1
- package/dist/config/env.d.ts +6 -1
- package/dist/config/env.js +93 -5
- package/dist/config/env.js.map +1 -1
- package/dist/config/profiles.js +4 -4
- package/dist/config/version.d.ts +1 -1
- package/dist/config/version.js +1 -1
- package/dist/export-manifest/errors.d.ts +55 -0
- package/dist/export-manifest/errors.js +69 -0
- package/dist/export-manifest/errors.js.map +1 -0
- package/dist/export-manifest/index.d.ts +10 -0
- package/dist/export-manifest/index.js +9 -0
- package/dist/export-manifest/index.js.map +1 -0
- package/dist/export-manifest/types.d.ts +170 -0
- package/dist/export-manifest/types.js +36 -0
- package/dist/export-manifest/types.js.map +1 -0
- package/dist/export-manifest/validation.d.ts +39 -0
- package/dist/export-manifest/validation.js +298 -0
- package/dist/export-manifest/validation.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/net-validation/errors.d.ts +89 -0
- package/dist/net-validation/errors.js +69 -0
- package/dist/net-validation/errors.js.map +1 -0
- package/dist/net-validation/fixtures.d.ts +38 -0
- package/dist/net-validation/fixtures.js +215 -0
- package/dist/net-validation/fixtures.js.map +1 -0
- package/dist/net-validation/index.d.ts +10 -0
- package/dist/net-validation/index.js +9 -0
- package/dist/net-validation/index.js.map +1 -0
- package/dist/net-validation/schema.d.ts +118 -0
- package/dist/net-validation/schema.js +140 -0
- package/dist/net-validation/schema.js.map +1 -0
- package/dist/net-validation/validation.d.ts +45 -0
- package/dist/net-validation/validation.js +369 -0
- package/dist/net-validation/validation.js.map +1 -0
- package/dist/pcb-constraints/errors.d.ts +39 -0
- package/dist/pcb-constraints/errors.js +133 -0
- package/dist/pcb-constraints/errors.js.map +1 -0
- package/dist/pcb-constraints/index.d.ts +9 -0
- package/dist/pcb-constraints/index.js +9 -0
- package/dist/pcb-constraints/index.js.map +1 -0
- package/dist/pcb-constraints/types.d.ts +102 -0
- package/dist/pcb-constraints/types.js +7 -0
- package/dist/pcb-constraints/types.js.map +1 -0
- package/dist/pcb-constraints/validation.d.ts +70 -0
- package/dist/pcb-constraints/validation.js +309 -0
- package/dist/pcb-constraints/validation.js.map +1 -0
- package/dist/server/factory.js +2 -0
- package/dist/server/factory.js.map +1 -1
- package/dist/server/transports/http.d.ts +20 -1
- package/dist/server/transports/http.js +156 -34
- package/dist/server/transports/http.js.map +1 -1
- package/dist/storage/database.d.ts +25 -0
- package/dist/storage/database.js +126 -51
- package/dist/storage/database.js.map +1 -1
- package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
- package/dist/tools/L0_diagnostics_api.js +152 -0
- package/dist/tools/L0_diagnostics_api.js.map +1 -0
- package/dist/tools/L0_diagnostics_core.d.ts +6 -0
- package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
- package/dist/tools/L0_diagnostics_core.js.map +1 -0
- package/dist/tools/L1_board.js +20 -4
- package/dist/tools/L1_board.js.map +1 -1
- package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
- package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
- package/dist/tools/L1_bom_core.js.map +1 -0
- package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
- package/dist/tools/L1_bom_sourcing.js +265 -0
- package/dist/tools/L1_bom_sourcing.js.map +1 -0
- package/dist/tools/L1_drc_erc.js +15 -3
- package/dist/tools/L1_drc_erc.js.map +1 -1
- package/dist/tools/L1_export.js +20 -4
- package/dist/tools/L1_export.js.map +1 -1
- package/dist/tools/L1_pcb_constraints.d.ts +6 -0
- package/dist/tools/L1_pcb_constraints.js +234 -0
- package/dist/tools/L1_pcb_constraints.js.map +1 -0
- package/dist/tools/L1_pcb_write.js +26 -12
- package/dist/tools/L1_pcb_write.js.map +1 -1
- package/dist/tools/L1_schematic_read.d.ts +6 -0
- package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -190
- package/dist/tools/L1_schematic_read.js.map +1 -0
- package/dist/tools/L1_schematic_write.d.ts +6 -0
- package/dist/tools/L1_schematic_write.js +516 -0
- package/dist/tools/L1_schematic_write.js.map +1 -0
- package/dist/tools/register.js +15 -7
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/registry.d.ts +41 -7
- package/dist/tools/registry.js +111 -12
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/types.d.ts +16 -0
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/vendors/base-http-client.d.ts +48 -0
- package/dist/vendors/base-http-client.js +75 -0
- package/dist/vendors/base-http-client.js.map +1 -0
- package/dist/vendors/digikey/client.js +10 -19
- package/dist/vendors/digikey/client.js.map +1 -1
- package/dist/vendors/jlcpcb/client.js +41 -70
- package/dist/vendors/jlcpcb/client.js.map +1 -1
- package/dist/vendors/lcsc/client.js +5 -18
- package/dist/vendors/lcsc/client.js.map +1 -1
- package/dist/vendors/mouser/client.js +4 -12
- package/dist/vendors/mouser/client.js.map +1 -1
- package/easyeda-bridge-extension.eext +0 -0
- package/package.json +41 -26
- package/dist/tools/L0_diagnostics.js.map +0 -1
- package/dist/tools/L1_bom.js.map +0 -1
- package/dist/tools/L1_schematic.js.map +0 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Net validation — schema types and naming convention definitions.
|
|
3
|
+
*
|
|
4
|
+
* Defines the input contract for net validation functions and the
|
|
5
|
+
* convention sets used to classify net names into analog, digital,
|
|
6
|
+
* power, ground, and high-voltage domains.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Electrical domain inferred from a net name.
|
|
12
|
+
*
|
|
13
|
+
* Used by naming-convention rules to detect misclassifications
|
|
14
|
+
* (e.g. an analog signal connected to a digital rail).
|
|
15
|
+
*/
|
|
16
|
+
export declare enum NetDomain {
|
|
17
|
+
/** General-purpose analogue signal (e.g. "SENSE", "FB", "VREF"). */
|
|
18
|
+
Analog = "analog",
|
|
19
|
+
/** Digital signal, bus, or protocol (e.g. "I2C_SCL", "UART_TXD"). */
|
|
20
|
+
Digital = "digital",
|
|
21
|
+
/** Power rail or voltage supply (e.g. "3V3", "VIN", "VCC"). */
|
|
22
|
+
Power = "power",
|
|
23
|
+
/** Ground or return (e.g. "GND", "AGND", "DGND", "PGND"). */
|
|
24
|
+
Ground = "ground",
|
|
25
|
+
/** AC mains or high-voltage domain (e.g. "L", "N", "HV_BULK"). */
|
|
26
|
+
HighVoltage = "high-voltage",
|
|
27
|
+
/** Clock or timing signal (e.g. "CLK_32K", "MCO"). */
|
|
28
|
+
Clock = "clock",
|
|
29
|
+
/** Reset or control signal (e.g. "nRST", "EN", "PWR_ON"). */
|
|
30
|
+
Control = "control",
|
|
31
|
+
/** Unclassified or custom. */
|
|
32
|
+
Other = "other"
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Naming convention pattern sets used to classify a net name into a domain.
|
|
36
|
+
*
|
|
37
|
+
* Each entry is a list of **case-insensitive** substrings / regex patterns
|
|
38
|
+
* that, when matched against a net name, assign it to the corresponding
|
|
39
|
+
* {@link NetDomain}.
|
|
40
|
+
*/
|
|
41
|
+
export declare const NET_DOMAIN_PATTERNS: Record<Exclude<NetDomain, NetDomain.Other>, RegExp[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Net names that are reserved for specific purposes and should not be
|
|
44
|
+
* reassigned to other signal types.
|
|
45
|
+
*/
|
|
46
|
+
export declare const RESERVED_NET_NAMES: Set<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Minimum set of power nets that a complete design should contain
|
|
49
|
+
* (case-insensitive matching).
|
|
50
|
+
*/
|
|
51
|
+
export declare const REQUIRED_POWER_NETS: Set<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Minimum set of ground nets that a complete design should contain.
|
|
54
|
+
*/
|
|
55
|
+
export declare const REQUIRED_GROUND_NETS: Set<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Map from NetType to expected naming convention domain.
|
|
58
|
+
* A net with a given NetType should have a name matching the
|
|
59
|
+
* corresponding domain(s).
|
|
60
|
+
*/
|
|
61
|
+
export declare const NET_TYPE_EXPECTED_DOMAIN: Record<string, NetDomain[]>;
|
|
62
|
+
/**
|
|
63
|
+
* A minimal net representation for validation purposes.
|
|
64
|
+
*
|
|
65
|
+
* This is intentionally decoupled from the full CircuitIR NetSchema
|
|
66
|
+
* so that validation can operate on net data from any source
|
|
67
|
+
* (CircuitIR, EasyEDA bridge, hand-authored test data).
|
|
68
|
+
*/
|
|
69
|
+
export interface NetValidationEntry {
|
|
70
|
+
/** Unique net identifier. */
|
|
71
|
+
id: string;
|
|
72
|
+
/** Human-readable net name (e.g. "3V3", "I2C_SCL", "GND"). */
|
|
73
|
+
name: string;
|
|
74
|
+
/** Net type classification. */
|
|
75
|
+
type: 'power' | 'signal' | 'ground';
|
|
76
|
+
/** Connected device pins, may be empty for floating nets. */
|
|
77
|
+
nodes: Array<{
|
|
78
|
+
deviceRef: string;
|
|
79
|
+
pin: string;
|
|
80
|
+
}>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A minimal device representation for validation.
|
|
84
|
+
*/
|
|
85
|
+
export interface DeviceValidationEntry {
|
|
86
|
+
/** Device identifier (matches deviceRef in net nodes). */
|
|
87
|
+
id: string;
|
|
88
|
+
/** Reference designator (e.g. "U1", "R3"). */
|
|
89
|
+
ref: string;
|
|
90
|
+
/** Functional category for determining required pins. */
|
|
91
|
+
category?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A hierarchical port / interface for cross-sheet validation.
|
|
95
|
+
*/
|
|
96
|
+
export interface InterfaceValidationEntry {
|
|
97
|
+
/** Interface identifier. */
|
|
98
|
+
id: string;
|
|
99
|
+
/** Interface / port name. */
|
|
100
|
+
name: string;
|
|
101
|
+
/** Pins on this interface. */
|
|
102
|
+
pinout: Array<{
|
|
103
|
+
pin: string;
|
|
104
|
+
signal: string;
|
|
105
|
+
type?: string;
|
|
106
|
+
}>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Complete input to the net validation function.
|
|
110
|
+
*/
|
|
111
|
+
export interface NetValidationInput {
|
|
112
|
+
/** Nets to validate. */
|
|
113
|
+
nets: NetValidationEntry[];
|
|
114
|
+
/** Optional device list for unconnected-pin checks. */
|
|
115
|
+
devices?: DeviceValidationEntry[];
|
|
116
|
+
/** Optional interface list for cross-sheet checks. */
|
|
117
|
+
interfaces?: InterfaceValidationEntry[];
|
|
118
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Net validation — schema types and naming convention definitions.
|
|
3
|
+
*
|
|
4
|
+
* Defines the input contract for net validation functions and the
|
|
5
|
+
* convention sets used to classify net names into analog, digital,
|
|
6
|
+
* power, ground, and high-voltage domains.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
// ── Naming convention categories ──────────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Electrical domain inferred from a net name.
|
|
13
|
+
*
|
|
14
|
+
* Used by naming-convention rules to detect misclassifications
|
|
15
|
+
* (e.g. an analog signal connected to a digital rail).
|
|
16
|
+
*/
|
|
17
|
+
export var NetDomain;
|
|
18
|
+
(function (NetDomain) {
|
|
19
|
+
/** General-purpose analogue signal (e.g. "SENSE", "FB", "VREF"). */
|
|
20
|
+
NetDomain["Analog"] = "analog";
|
|
21
|
+
/** Digital signal, bus, or protocol (e.g. "I2C_SCL", "UART_TXD"). */
|
|
22
|
+
NetDomain["Digital"] = "digital";
|
|
23
|
+
/** Power rail or voltage supply (e.g. "3V3", "VIN", "VCC"). */
|
|
24
|
+
NetDomain["Power"] = "power";
|
|
25
|
+
/** Ground or return (e.g. "GND", "AGND", "DGND", "PGND"). */
|
|
26
|
+
NetDomain["Ground"] = "ground";
|
|
27
|
+
/** AC mains or high-voltage domain (e.g. "L", "N", "HV_BULK"). */
|
|
28
|
+
NetDomain["HighVoltage"] = "high-voltage";
|
|
29
|
+
/** Clock or timing signal (e.g. "CLK_32K", "MCO"). */
|
|
30
|
+
NetDomain["Clock"] = "clock";
|
|
31
|
+
/** Reset or control signal (e.g. "nRST", "EN", "PWR_ON"). */
|
|
32
|
+
NetDomain["Control"] = "control";
|
|
33
|
+
/** Unclassified or custom. */
|
|
34
|
+
NetDomain["Other"] = "other";
|
|
35
|
+
})(NetDomain || (NetDomain = {}));
|
|
36
|
+
/**
|
|
37
|
+
* Naming convention pattern sets used to classify a net name into a domain.
|
|
38
|
+
*
|
|
39
|
+
* Each entry is a list of **case-insensitive** substrings / regex patterns
|
|
40
|
+
* that, when matched against a net name, assign it to the corresponding
|
|
41
|
+
* {@link NetDomain}.
|
|
42
|
+
*/
|
|
43
|
+
export const NET_DOMAIN_PATTERNS = {
|
|
44
|
+
[NetDomain.Power]: [
|
|
45
|
+
/^[0-9]+V[0-9]*/, // 3V3, 5V, 12V, 1V8
|
|
46
|
+
/^V(CC|DD|EE|SS|IN|OUT|BAT|REF|PP|DRV)/i, // VCC, VDD, VIN, VOUT, VBAT
|
|
47
|
+
/_V(CC|DD|EE|SS|IN|OUT)\b/i, // AVCC, DVDD
|
|
48
|
+
/PWR/i,
|
|
49
|
+
/POWER/i,
|
|
50
|
+
/VSUPPLY/i,
|
|
51
|
+
],
|
|
52
|
+
[NetDomain.Ground]: [
|
|
53
|
+
/^GND$/i,
|
|
54
|
+
/GND\b/i, // AGND, DGND, PGND, GNDD, GNDA
|
|
55
|
+
/^VSS$/i,
|
|
56
|
+
/GROUND/i,
|
|
57
|
+
/^RETURN$/i,
|
|
58
|
+
],
|
|
59
|
+
[NetDomain.Analog]: [
|
|
60
|
+
/SENSE/i,
|
|
61
|
+
/FB\b/i, // feedback
|
|
62
|
+
/VREF/i,
|
|
63
|
+
/REFIN/i,
|
|
64
|
+
/REFOUT/i,
|
|
65
|
+
/COMP/i, // comparator output
|
|
66
|
+
/OSC/i,
|
|
67
|
+
/FILTER/i,
|
|
68
|
+
/AGND\b/i, // analog ground reference
|
|
69
|
+
],
|
|
70
|
+
[NetDomain.Digital]: [
|
|
71
|
+
/^(I2C|SPI|UART|CAN|USB|ETH|MII|RMII|SDIO|I2S|PCM)_/i,
|
|
72
|
+
/_(SCL|SDA|MOSI|MISO|CS|SCK|TXD|RXD|RTS|CTS|TX|RX)\b/i,
|
|
73
|
+
/^[A-Z]+_[A-Z]+(_[A-Z]+)*$/, // SHOUTING_CASE signals like DATA_READY, INT_OUT
|
|
74
|
+
],
|
|
75
|
+
[NetDomain.Clock]: [/CLK/i, /_MCO\b/i, /XTAL/i, /OSC/i, /TIM/i, /PWM/i],
|
|
76
|
+
[NetDomain.Control]: [
|
|
77
|
+
/^n?(RST|RESET|EN|ENABLE|CS|CE|SHDN|PWR_UP|PWR_DN|WAKE|SLEEP)\b/i,
|
|
78
|
+
/_EN\b/i,
|
|
79
|
+
/_nRST\b/i,
|
|
80
|
+
/_OE\b/i,
|
|
81
|
+
],
|
|
82
|
+
[NetDomain.HighVoltage]: [
|
|
83
|
+
/^HV/i,
|
|
84
|
+
/^AC_/i,
|
|
85
|
+
/^L\b/i, // Live (mains)
|
|
86
|
+
/^N\b/i, // Neutral (mains)
|
|
87
|
+
/_HV\b/i,
|
|
88
|
+
/MAINS/i,
|
|
89
|
+
/BULK/i,
|
|
90
|
+
/RECT/i,
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
// ── Reserved net names ────────────────────────────────────────────────────
|
|
94
|
+
/**
|
|
95
|
+
* Net names that are reserved for specific purposes and should not be
|
|
96
|
+
* reassigned to other signal types.
|
|
97
|
+
*/
|
|
98
|
+
export const RESERVED_NET_NAMES = new Set([
|
|
99
|
+
'GND',
|
|
100
|
+
'VSS',
|
|
101
|
+
'VCC',
|
|
102
|
+
'VDD',
|
|
103
|
+
'VEE',
|
|
104
|
+
'VSSA',
|
|
105
|
+
'VDDA',
|
|
106
|
+
'AGND',
|
|
107
|
+
'DGND',
|
|
108
|
+
'PGND',
|
|
109
|
+
'GNDA',
|
|
110
|
+
'GNDD',
|
|
111
|
+
'GNDP',
|
|
112
|
+
]);
|
|
113
|
+
// ── Power / Ground expectation sets ────────────────────────────────────────
|
|
114
|
+
/**
|
|
115
|
+
* Minimum set of power nets that a complete design should contain
|
|
116
|
+
* (case-insensitive matching).
|
|
117
|
+
*/
|
|
118
|
+
export const REQUIRED_POWER_NETS = new Set(['VIN', '3V3']);
|
|
119
|
+
/**
|
|
120
|
+
* Minimum set of ground nets that a complete design should contain.
|
|
121
|
+
*/
|
|
122
|
+
export const REQUIRED_GROUND_NETS = new Set(['GND']);
|
|
123
|
+
// ── Convention mappings ───────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Map from NetType to expected naming convention domain.
|
|
126
|
+
* A net with a given NetType should have a name matching the
|
|
127
|
+
* corresponding domain(s).
|
|
128
|
+
*/
|
|
129
|
+
export const NET_TYPE_EXPECTED_DOMAIN = {
|
|
130
|
+
power: [NetDomain.Power],
|
|
131
|
+
ground: [NetDomain.Ground],
|
|
132
|
+
signal: [
|
|
133
|
+
NetDomain.Digital,
|
|
134
|
+
NetDomain.Analog,
|
|
135
|
+
NetDomain.Clock,
|
|
136
|
+
NetDomain.Control,
|
|
137
|
+
NetDomain.Other,
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/net-validation/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6EAA6E;AAE7E;;;;;GAKG;AACH,MAAM,CAAN,IAAY,SAiBX;AAjBD,WAAY,SAAS;IACnB,oEAAoE;IACpE,8BAAiB,CAAA;IACjB,qEAAqE;IACrE,gCAAmB,CAAA;IACnB,+DAA+D;IAC/D,4BAAe,CAAA;IACf,6DAA6D;IAC7D,8BAAiB,CAAA;IACjB,kEAAkE;IAClE,yCAA4B,CAAA;IAC5B,sDAAsD;IACtD,4BAAe,CAAA;IACf,6DAA6D;IAC7D,gCAAmB,CAAA;IACnB,8BAA8B;IAC9B,4BAAe,CAAA;AACjB,CAAC,EAjBW,SAAS,KAAT,SAAS,QAiBpB;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA0D;IACxF,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;QACjB,gBAAgB,EAAE,oBAAoB;QACtC,wCAAwC,EAAE,4BAA4B;QACtE,2BAA2B,EAAE,aAAa;QAC1C,MAAM;QACN,QAAQ;QACR,UAAU;KACX;IACD,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAClB,QAAQ;QACR,QAAQ,EAAE,+BAA+B;QACzC,QAAQ;QACR,SAAS;QACT,WAAW;KACZ;IACD,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAClB,QAAQ;QACR,OAAO,EAAE,WAAW;QACpB,OAAO;QACP,QAAQ;QACR,SAAS;QACT,OAAO,EAAE,oBAAoB;QAC7B,MAAM;QACN,SAAS;QACT,SAAS,EAAE,0BAA0B;KACtC;IACD,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,qDAAqD;QACrD,sDAAsD;QACtD,2BAA2B,EAAE,iDAAiD;KAC/E;IACD,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IACvE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,iEAAiE;QACjE,QAAQ;QACR,UAAU;QACV,QAAQ;KACT;IACD,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;QACvB,MAAM;QACN,OAAO;QACP,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE,kBAAkB;QAC3B,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,OAAO;KACR;CACF,CAAC;AAEF,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACxC,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAErD,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAgC;IACnE,KAAK,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;IAC1B,MAAM,EAAE;QACN,SAAS,CAAC,OAAO;QACjB,SAAS,CAAC,MAAM;QAChB,SAAS,CAAC,KAAK;QACf,SAAS,CAAC,OAAO;QACjB,SAAS,CAAC,KAAK;KAChB;CACF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Net validation — wire-name and topology validation rules.
|
|
3
|
+
*
|
|
4
|
+
* Implements 10 validation rules that operate on {@link NetValidationInput}
|
|
5
|
+
* and produce structured {@link NetValidationIssue}s.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* 1. Floating net (zero nodes)
|
|
9
|
+
* 2. Duplicate net names
|
|
10
|
+
* 3. Accidental short (same device pin on different nets)
|
|
11
|
+
* 4. Missing power net
|
|
12
|
+
* 5. Missing ground net
|
|
13
|
+
* 6. Missing hierarchical port
|
|
14
|
+
* 7. Unconnected required pin
|
|
15
|
+
* 8. Inconsistent cross-sheet interface pins
|
|
16
|
+
* 9. Naming convention violation (domain mismatch)
|
|
17
|
+
* 10. Protected AC/high-voltage domain naming
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { NetValidationResult } from './errors.js';
|
|
22
|
+
import type { NetValidationInput } from './schema.js';
|
|
23
|
+
/**
|
|
24
|
+
* Run all net validation rules against an input net list.
|
|
25
|
+
*
|
|
26
|
+
* Orchestrates 10 rules:
|
|
27
|
+
* 1. Floating nets — error if net has zero nodes
|
|
28
|
+
* 2. Duplicate names — error if multiple nets share a name
|
|
29
|
+
* 3. Accidental shorts — error if one device pin belongs to multiple nets
|
|
30
|
+
* 4. Missing power — error if no type=power net + warnings for specific names
|
|
31
|
+
* 5. Missing ground — error if no type=ground net + warnings for specific names
|
|
32
|
+
* 6. Missing hierarchical port — error if interface references an unknown net
|
|
33
|
+
* 7. Unconnected required pins — warning if a device has zero connections
|
|
34
|
+
* 8. Cross-sheet consistency — error if same-name interfaces have different pinouts
|
|
35
|
+
* 9. Naming convention — warning if power/ground nets have non-standard names
|
|
36
|
+
* 10. Protected domain — error if high-voltage net lacks protective naming
|
|
37
|
+
*/
|
|
38
|
+
export declare function validateNets(input: NetValidationInput): NetValidationResult;
|
|
39
|
+
/**
|
|
40
|
+
* Validate nets and throw on the first error.
|
|
41
|
+
*
|
|
42
|
+
* Returns the full result on success. Throws the first `NetValidationIssue`
|
|
43
|
+
* found (as an error) if validation fails.
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateNetsOrThrow(input: NetValidationInput): NetValidationResult;
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Net validation — wire-name and topology validation rules.
|
|
3
|
+
*
|
|
4
|
+
* Implements 10 validation rules that operate on {@link NetValidationInput}
|
|
5
|
+
* and produce structured {@link NetValidationIssue}s.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* 1. Floating net (zero nodes)
|
|
9
|
+
* 2. Duplicate net names
|
|
10
|
+
* 3. Accidental short (same device pin on different nets)
|
|
11
|
+
* 4. Missing power net
|
|
12
|
+
* 5. Missing ground net
|
|
13
|
+
* 6. Missing hierarchical port
|
|
14
|
+
* 7. Unconnected required pin
|
|
15
|
+
* 8. Inconsistent cross-sheet interface pins
|
|
16
|
+
* 9. Naming convention violation (domain mismatch)
|
|
17
|
+
* 10. Protected AC/high-voltage domain naming
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { NetValidationCode, netError, netWarning } from './errors.js';
|
|
22
|
+
import { NET_DOMAIN_PATTERNS, NET_TYPE_EXPECTED_DOMAIN, REQUIRED_GROUND_NETS, REQUIRED_POWER_NETS, RESERVED_NET_NAMES, NetDomain, } from './schema.js';
|
|
23
|
+
// ── Rule: floating nets ────────────────────────────────────────────────────
|
|
24
|
+
function checkFloatingNets(input) {
|
|
25
|
+
const issues = [];
|
|
26
|
+
for (const net of input.nets) {
|
|
27
|
+
if (net.nodes.length === 0) {
|
|
28
|
+
issues.push(netError(NetValidationCode.NetFloating, `Net "${net.name}" (${net.id}) has no node connections — it is floating`, {
|
|
29
|
+
path: `nets[${input.nets.indexOf(net)}]`,
|
|
30
|
+
netName: net.name,
|
|
31
|
+
remediationHint: 'Connect this net to at least one device pin or remove it',
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return issues;
|
|
36
|
+
}
|
|
37
|
+
// ── Rule: duplicate net names ──────────────────────────────────────────────
|
|
38
|
+
function checkDuplicateNetNames(input) {
|
|
39
|
+
const issues = [];
|
|
40
|
+
const nameMap = new Map();
|
|
41
|
+
for (const net of input.nets) {
|
|
42
|
+
const normalised = net.name.toUpperCase();
|
|
43
|
+
if (!nameMap.has(normalised)) {
|
|
44
|
+
nameMap.set(normalised, []);
|
|
45
|
+
}
|
|
46
|
+
nameMap.get(normalised).push(net);
|
|
47
|
+
}
|
|
48
|
+
for (const [name, nets] of nameMap) {
|
|
49
|
+
if (nets.length > 1) {
|
|
50
|
+
const ids = nets.map((n) => n.id).join(', ');
|
|
51
|
+
issues.push(netError(NetValidationCode.NetDuplicateName, `Net name "${name}" is used by ${nets.length} nets: ${ids}`, {
|
|
52
|
+
netName: name,
|
|
53
|
+
remediationHint: 'Rename conflicting nets or merge them if they are intended to be the same electrical node',
|
|
54
|
+
details: { matchingNetIds: nets.map((n) => n.id) },
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return issues;
|
|
59
|
+
}
|
|
60
|
+
// ── Rule: accidental shorts ────────────────────────────────────────────────
|
|
61
|
+
function checkAccidentalShorts(input) {
|
|
62
|
+
const issues = [];
|
|
63
|
+
const pinToNets = new Map();
|
|
64
|
+
for (const net of input.nets) {
|
|
65
|
+
for (const node of net.nodes) {
|
|
66
|
+
const key = `${node.deviceRef}:${node.pin}`;
|
|
67
|
+
if (!pinToNets.has(key)) {
|
|
68
|
+
pinToNets.set(key, []);
|
|
69
|
+
}
|
|
70
|
+
pinToNets.get(key).push(net);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const [key, nets] of pinToNets) {
|
|
74
|
+
if (nets.length > 1) {
|
|
75
|
+
const parts = key.split(':');
|
|
76
|
+
issues.push(netError(NetValidationCode.NetAccidentalShort, `Device pin "${key}" is connected to ${nets.length} different nets: ${nets.map((n) => n.name).join(', ')}`, {
|
|
77
|
+
componentRef: parts[0],
|
|
78
|
+
pin: parts[1],
|
|
79
|
+
remediationHint: 'Ensure only one net connects to each device pin, or use a net junction if intentional',
|
|
80
|
+
details: {
|
|
81
|
+
conflictingNets: nets.map((n) => ({ id: n.id, name: n.name })),
|
|
82
|
+
},
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return issues;
|
|
87
|
+
}
|
|
88
|
+
// ── Rule: missing power net ────────────────────────────────────────────────
|
|
89
|
+
function checkMissingPowerNet(input) {
|
|
90
|
+
const issues = [];
|
|
91
|
+
// Check that at least one net has type=power
|
|
92
|
+
const powerNets = input.nets.filter((n) => n.type === 'power');
|
|
93
|
+
if (powerNets.length === 0) {
|
|
94
|
+
issues.push(netError(NetValidationCode.NetMissingPower, 'No power net found — the design must have at least one net of type=power', {
|
|
95
|
+
remediationHint: 'Add a power net (e.g. "3V3", "VIN", "VCC") with type="power"',
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
// Also check for required specific power net names
|
|
99
|
+
for (const required of REQUIRED_POWER_NETS) {
|
|
100
|
+
const found = input.nets.some((n) => n.name.toUpperCase() === required.toUpperCase());
|
|
101
|
+
if (!found) {
|
|
102
|
+
issues.push(netWarning(NetValidationCode.NetMissingPower, `Required power net "${required}" not found in the design`, {
|
|
103
|
+
netName: required,
|
|
104
|
+
remediationHint: `Add a "${required}" power rail or ensure your power source is properly named`,
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return issues;
|
|
109
|
+
}
|
|
110
|
+
// ── Rule: missing ground net ───────────────────────────────────────────────
|
|
111
|
+
function checkMissingGroundNet(input) {
|
|
112
|
+
const issues = [];
|
|
113
|
+
const groundNets = input.nets.filter((n) => n.type === 'ground');
|
|
114
|
+
if (groundNets.length === 0) {
|
|
115
|
+
issues.push(netError(NetValidationCode.NetMissingGround, 'No ground net found — the design must have at least one net of type=ground', {
|
|
116
|
+
remediationHint: 'Add a ground net (e.g. "GND") with type="ground"',
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
// Also check for required specific ground net names
|
|
120
|
+
for (const required of REQUIRED_GROUND_NETS) {
|
|
121
|
+
const found = input.nets.some((n) => n.name.toUpperCase() === required.toUpperCase());
|
|
122
|
+
if (!found) {
|
|
123
|
+
issues.push(netWarning(NetValidationCode.NetMissingGround, `Required ground net "${required}" not found in the design`, {
|
|
124
|
+
netName: required,
|
|
125
|
+
remediationHint: `Add a "${required}" net with type="ground"`,
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return issues;
|
|
130
|
+
}
|
|
131
|
+
// ── Rule: missing hierarchical port ────────────────────────────────────────
|
|
132
|
+
function checkMissingHierarchicalPorts(input) {
|
|
133
|
+
const issues = [];
|
|
134
|
+
if (!input.interfaces || input.interfaces.length === 0) {
|
|
135
|
+
return issues; // No interfaces defined — skip
|
|
136
|
+
}
|
|
137
|
+
const netNames = new Set(input.nets.map((n) => n.name.toUpperCase()));
|
|
138
|
+
for (const intf of input.interfaces) {
|
|
139
|
+
for (const pinEntry of intf.pinout) {
|
|
140
|
+
if (!netNames.has(pinEntry.signal.toUpperCase())) {
|
|
141
|
+
issues.push(netError(NetValidationCode.NetMissingHierarchicalPort, `Interface "${intf.name}" references signal "${pinEntry.signal}" (pin ${pinEntry.pin}) but no matching net was found`, {
|
|
142
|
+
netName: pinEntry.signal,
|
|
143
|
+
pin: pinEntry.pin,
|
|
144
|
+
remediationHint: `Add a net named "${pinEntry.signal}" or update the interface pinout`,
|
|
145
|
+
details: { interfaceName: intf.name },
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return issues;
|
|
151
|
+
}
|
|
152
|
+
// ── Rule: unconnected required pins ────────────────────────────────────────
|
|
153
|
+
function checkUnconnectedPins(input) {
|
|
154
|
+
const issues = [];
|
|
155
|
+
if (!input.devices || input.devices.length === 0) {
|
|
156
|
+
return issues;
|
|
157
|
+
}
|
|
158
|
+
// Build set of connected pins
|
|
159
|
+
const connectedPins = new Set();
|
|
160
|
+
for (const net of input.nets) {
|
|
161
|
+
for (const node of net.nodes) {
|
|
162
|
+
connectedPins.add(`${node.deviceRef}:${node.pin}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Check each device for unconnected pins
|
|
166
|
+
// For now, only flag devices with no connections at all (not individual pins,
|
|
167
|
+
// since we don't have a comprehensive required-pin list per device category)
|
|
168
|
+
for (const device of input.devices) {
|
|
169
|
+
const devicePins = [...connectedPins].filter((p) => p.startsWith(`${device.id}:`));
|
|
170
|
+
if (devicePins.length === 0) {
|
|
171
|
+
issues.push(netWarning(NetValidationCode.NetUnconnectedRequiredPin, `Device "${device.ref}" (${device.id}) has no pin connections`, {
|
|
172
|
+
componentRef: device.ref,
|
|
173
|
+
remediationHint: 'Connect at least one pin of this device to a net, or remove it if unused',
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return issues;
|
|
178
|
+
}
|
|
179
|
+
// ── Rule: inconsistent cross-sheet interfaces ──────────────────────────────
|
|
180
|
+
function checkCrossSheetConsistency(input) {
|
|
181
|
+
const issues = [];
|
|
182
|
+
if (!input.interfaces || input.interfaces.length < 2) {
|
|
183
|
+
return issues; // Need at least 2 interfaces to compare
|
|
184
|
+
}
|
|
185
|
+
// For cross-sheet validation, interfaces with the same name on different
|
|
186
|
+
// sheets should have matching pinout lists
|
|
187
|
+
const byName = new Map();
|
|
188
|
+
for (const intf of input.interfaces) {
|
|
189
|
+
const key = intf.name.toUpperCase();
|
|
190
|
+
if (!byName.has(key)) {
|
|
191
|
+
byName.set(key, []);
|
|
192
|
+
}
|
|
193
|
+
byName.get(key).push(intf);
|
|
194
|
+
}
|
|
195
|
+
for (const [name, group] of byName) {
|
|
196
|
+
if (group.length < 2)
|
|
197
|
+
continue;
|
|
198
|
+
// Compare all interfaces with the same name (group.length >= 2 here)
|
|
199
|
+
const reference = group[0];
|
|
200
|
+
for (let i = 1; i < group.length; i++) {
|
|
201
|
+
const other = group[i];
|
|
202
|
+
// Check pin count matches
|
|
203
|
+
if (reference.pinout.length !== other.pinout.length) {
|
|
204
|
+
issues.push(netError(NetValidationCode.NetInconsistentCrossSheet, `Interface "${name}" has inconsistent pin counts: sheet 1 has ${reference.pinout.length} pins, sheet ${i + 1} has ${other.pinout.length} pins`, {
|
|
205
|
+
remediationHint: 'Ensure all instances of this interface have the same pinout',
|
|
206
|
+
details: {
|
|
207
|
+
interfaceName: name,
|
|
208
|
+
firstInstanceId: reference.id,
|
|
209
|
+
otherInstanceId: other.id,
|
|
210
|
+
},
|
|
211
|
+
}));
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
// Check individual pin names match
|
|
215
|
+
for (let j = 0; j < reference.pinout.length; j++) {
|
|
216
|
+
const refPin = reference.pinout[j];
|
|
217
|
+
const otherPin = other.pinout[j];
|
|
218
|
+
if (refPin.signal.toUpperCase() !== otherPin.signal.toUpperCase()) {
|
|
219
|
+
issues.push(netError(NetValidationCode.NetInconsistentCrossSheet, `Interface "${name}" has mismatched signals at index ${j}: "${refPin.signal}" vs "${otherPin.signal}"`, {
|
|
220
|
+
pin: refPin.pin,
|
|
221
|
+
remediationHint: 'Update the interface pinout to match across all sheets',
|
|
222
|
+
details: {
|
|
223
|
+
interfaceName: name,
|
|
224
|
+
expectedSignal: refPin.signal,
|
|
225
|
+
actualSignal: otherPin.signal,
|
|
226
|
+
},
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return issues;
|
|
233
|
+
}
|
|
234
|
+
// ── Rule: naming convention violations ─────────────────────────────────────
|
|
235
|
+
/**
|
|
236
|
+
* Classify a net name into one or more {@link NetDomain}s.
|
|
237
|
+
*/
|
|
238
|
+
function classifyNetDomain(name) {
|
|
239
|
+
const domains = new Set();
|
|
240
|
+
for (const [domain, patterns] of Object.entries(NET_DOMAIN_PATTERNS)) {
|
|
241
|
+
for (const pattern of patterns) {
|
|
242
|
+
if (pattern.test(name)) {
|
|
243
|
+
domains.add(domain);
|
|
244
|
+
break; // One match per domain is enough
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return domains;
|
|
249
|
+
}
|
|
250
|
+
function checkNamingConventions(input) {
|
|
251
|
+
const issues = [];
|
|
252
|
+
for (const net of input.nets) {
|
|
253
|
+
const name = net.name;
|
|
254
|
+
// Skip reserved names (GND, VCC, etc.) — these are convention by definition
|
|
255
|
+
if (RESERVED_NET_NAMES.has(name.toUpperCase()))
|
|
256
|
+
continue;
|
|
257
|
+
// Get expected domain for this net's type
|
|
258
|
+
const expectedDomains = NET_TYPE_EXPECTED_DOMAIN[net.type];
|
|
259
|
+
if (!expectedDomains)
|
|
260
|
+
continue;
|
|
261
|
+
// Classify the net name
|
|
262
|
+
const actualDomains = classifyNetDomain(name);
|
|
263
|
+
// If the net type is power, the name should look like a power rail
|
|
264
|
+
if (net.type === 'power' && !actualDomains.has(NetDomain.Power)) {
|
|
265
|
+
issues.push(netWarning(NetValidationCode.NetNamingConvention, `Power net "${name}" does not follow power rail naming conventions (e.g. "3V3", "VCC", "VIN")`, {
|
|
266
|
+
netName: name,
|
|
267
|
+
remediationHint: 'Rename to a conventional power rail name like "VCC", "3V3", or "VIN_5V"',
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
// If the net type is ground, the name should look like a ground
|
|
271
|
+
if (net.type === 'ground' && !actualDomains.has(NetDomain.Ground)) {
|
|
272
|
+
issues.push(netWarning(NetValidationCode.NetNamingConvention, `Ground net "${name}" does not follow ground naming conventions (e.g. "GND", "AGND", "PGND")`, {
|
|
273
|
+
netName: name,
|
|
274
|
+
remediationHint: 'Rename to a conventional ground name like "GND", "AGND", or "PGND"',
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
// Check for AC/high-voltage naming without protection (next rule handles this more specifically)
|
|
278
|
+
}
|
|
279
|
+
return issues;
|
|
280
|
+
}
|
|
281
|
+
// ── Rule: protected AC/high-voltage domain ─────────────────────────────────
|
|
282
|
+
function checkProtectedDomain(input) {
|
|
283
|
+
const issues = [];
|
|
284
|
+
for (const net of input.nets) {
|
|
285
|
+
const actualDomains = classifyNetDomain(net.name);
|
|
286
|
+
// If the net name suggests high-voltage domain, it should have clear
|
|
287
|
+
// protective labeling
|
|
288
|
+
if (actualDomains.has(NetDomain.HighVoltage)) {
|
|
289
|
+
// High-voltage nets should not be named generically
|
|
290
|
+
if (/^[A-Z]?[0-9]?$/.test(net.name.trim())) {
|
|
291
|
+
issues.push(netError(NetValidationCode.NetProtectedDomain, `Net "${net.name}" appears to be in the high-voltage domain but has a generic name — use protective naming like "HV_*" or "AC_*"`, {
|
|
292
|
+
netName: net.name,
|
|
293
|
+
remediationHint: 'Prefix the net name with "HV_" or "AC_" to clearly indicate high-voltage domain (e.g. "HV_BULK", "AC_L")',
|
|
294
|
+
}));
|
|
295
|
+
}
|
|
296
|
+
// High-voltage nets should not be mixed with low-voltage signal naming
|
|
297
|
+
if (actualDomains.has(NetDomain.Digital) || actualDomains.has(NetDomain.Clock)) {
|
|
298
|
+
issues.push(netError(NetValidationCode.NetProtectedDomain, `Net "${net.name}" is classified as both high-voltage and digital/clock — this is a safety hazard`, {
|
|
299
|
+
netName: net.name,
|
|
300
|
+
remediationHint: 'Separate high-voltage and low-voltage domains; use isolated net names with "HV_" prefix',
|
|
301
|
+
details: { detectedDomains: [...actualDomains] },
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return issues;
|
|
307
|
+
}
|
|
308
|
+
const RULES = [
|
|
309
|
+
checkFloatingNets,
|
|
310
|
+
checkDuplicateNetNames,
|
|
311
|
+
checkAccidentalShorts,
|
|
312
|
+
checkMissingPowerNet,
|
|
313
|
+
checkMissingGroundNet,
|
|
314
|
+
checkMissingHierarchicalPorts,
|
|
315
|
+
checkUnconnectedPins,
|
|
316
|
+
checkCrossSheetConsistency,
|
|
317
|
+
checkNamingConventions,
|
|
318
|
+
checkProtectedDomain,
|
|
319
|
+
];
|
|
320
|
+
// ── Main entry point ───────────────────────────────────────────────────────
|
|
321
|
+
/**
|
|
322
|
+
* Run all net validation rules against an input net list.
|
|
323
|
+
*
|
|
324
|
+
* Orchestrates 10 rules:
|
|
325
|
+
* 1. Floating nets — error if net has zero nodes
|
|
326
|
+
* 2. Duplicate names — error if multiple nets share a name
|
|
327
|
+
* 3. Accidental shorts — error if one device pin belongs to multiple nets
|
|
328
|
+
* 4. Missing power — error if no type=power net + warnings for specific names
|
|
329
|
+
* 5. Missing ground — error if no type=ground net + warnings for specific names
|
|
330
|
+
* 6. Missing hierarchical port — error if interface references an unknown net
|
|
331
|
+
* 7. Unconnected required pins — warning if a device has zero connections
|
|
332
|
+
* 8. Cross-sheet consistency — error if same-name interfaces have different pinouts
|
|
333
|
+
* 9. Naming convention — warning if power/ground nets have non-standard names
|
|
334
|
+
* 10. Protected domain — error if high-voltage net lacks protective naming
|
|
335
|
+
*/
|
|
336
|
+
export function validateNets(input) {
|
|
337
|
+
const errors = [];
|
|
338
|
+
const warnings = [];
|
|
339
|
+
for (const rule of RULES) {
|
|
340
|
+
const issues = rule(input);
|
|
341
|
+
for (const issue of issues) {
|
|
342
|
+
if (issue.severity === 'error') {
|
|
343
|
+
errors.push(issue);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
warnings.push(issue);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
valid: errors.length === 0,
|
|
352
|
+
errors,
|
|
353
|
+
warnings,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Validate nets and throw on the first error.
|
|
358
|
+
*
|
|
359
|
+
* Returns the full result on success. Throws the first `NetValidationIssue`
|
|
360
|
+
* found (as an error) if validation fails.
|
|
361
|
+
*/
|
|
362
|
+
export function validateNetsOrThrow(input) {
|
|
363
|
+
const result = validateNets(input);
|
|
364
|
+
if (!result.valid) {
|
|
365
|
+
throw result.errors[0];
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=validation.js.map
|