@tscircuit/cli 0.1.2211 → 0.1.2212
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/dist/cli/main.js +1031 -68
- package/dist/lib/index.js +2 -2
- package/package.json +2 -2
package/dist/cli/main.js
CHANGED
|
@@ -154298,7 +154298,7 @@ var import_perfect_cli = __toESM3(require_dist3(), 1);
|
|
|
154298
154298
|
// lib/getVersion.ts
|
|
154299
154299
|
import { createRequire as createRequire2 } from "node:module";
|
|
154300
154300
|
// package.json
|
|
154301
|
-
var version = "0.1.
|
|
154301
|
+
var version = "0.1.2211";
|
|
154302
154302
|
var package_default = {
|
|
154303
154303
|
name: "@tscircuit/cli",
|
|
154304
154304
|
version,
|
|
@@ -154317,7 +154317,7 @@ var package_default = {
|
|
|
154317
154317
|
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.26.tgz",
|
|
154318
154318
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.15",
|
|
154319
154319
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.8",
|
|
154320
|
-
"@tscircuit/circuit-json-schematic-placement-analysis": "https://jscdn.tscircuit.com/@tscircuit/circuit-json-schematic-placement-analysis/0.0.
|
|
154320
|
+
"@tscircuit/circuit-json-schematic-placement-analysis": "https://jscdn.tscircuit.com/@tscircuit/circuit-json-schematic-placement-analysis/0.0.33.tgz",
|
|
154321
154321
|
"@tscircuit/circuit-json-util": "^0.0.116",
|
|
154322
154322
|
"@tscircuit/eval": "0.0.1402",
|
|
154323
154323
|
"@tscircuit/fake-snippets": "^0.0.182",
|
|
@@ -330754,7 +330754,7 @@ var registerCheckRoutingDifficulty = (program) => {
|
|
|
330754
330754
|
});
|
|
330755
330755
|
};
|
|
330756
330756
|
|
|
330757
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/
|
|
330757
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/MosfetGateNetworkPlacementSolver/MosfetGateNetworkPlacementSolver.ts
|
|
330758
330758
|
import { BaseSolver as BaseSolver5 } from "@tscircuit/solver-utils";
|
|
330759
330759
|
|
|
330760
330760
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/format.ts
|
|
@@ -330775,21 +330775,6 @@ var addAttr = (attrs, key, value, options) => {
|
|
|
330775
330775
|
attrs.push(`${key}="${stringValue}"`);
|
|
330776
330776
|
};
|
|
330777
330777
|
|
|
330778
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/geometry.ts
|
|
330779
|
-
function centeredRect(cx, cy, w, h) {
|
|
330780
|
-
return {
|
|
330781
|
-
left: cx - w / 2,
|
|
330782
|
-
right: cx + w / 2,
|
|
330783
|
-
top: cy + h / 2,
|
|
330784
|
-
bottom: cy - h / 2
|
|
330785
|
-
};
|
|
330786
|
-
}
|
|
330787
|
-
function rectOverlap(a, b) {
|
|
330788
|
-
const ow = Math.min(a.right, b.right) - Math.max(a.left, b.left);
|
|
330789
|
-
const oh = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
|
|
330790
|
-
return ow > 0 && oh > 0 ? { ow, oh } : null;
|
|
330791
|
-
}
|
|
330792
|
-
|
|
330793
330778
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/source-connectivity.ts
|
|
330794
330779
|
function getSourceConnectivity(circuitJson) {
|
|
330795
330780
|
const parent = new Map;
|
|
@@ -330934,8 +330919,632 @@ function append2(map, key, value) {
|
|
|
330934
330919
|
map.set(key, [value]);
|
|
330935
330920
|
}
|
|
330936
330921
|
|
|
330937
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/
|
|
330922
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/MosfetGateNetworkPlacementSolver/MosfetGateNetworkPlacementSolver.ts
|
|
330923
|
+
class MosfetGateNetworkPlacementSolver extends BaseSolver5 {
|
|
330924
|
+
params;
|
|
330925
|
+
index;
|
|
330926
|
+
mosfetIds;
|
|
330927
|
+
currentIndex = 0;
|
|
330928
|
+
constructor(params2) {
|
|
330929
|
+
super();
|
|
330930
|
+
this.params = params2;
|
|
330931
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
330932
|
+
this.mosfetIds = [...this.index.components.keys()].filter((id) => this.mosfetPorts(id));
|
|
330933
|
+
this.solved = this.mosfetIds.length === 0;
|
|
330934
|
+
}
|
|
330935
|
+
_step() {
|
|
330936
|
+
const id = this.mosfetIds[this.currentIndex++];
|
|
330937
|
+
this.solved = this.currentIndex >= this.mosfetIds.length;
|
|
330938
|
+
if (!id)
|
|
330939
|
+
return;
|
|
330940
|
+
const index = this.index;
|
|
330941
|
+
const mosfet = index.placement(id);
|
|
330942
|
+
const roles = this.mosfetPorts(id);
|
|
330943
|
+
if (!mosfet)
|
|
330944
|
+
return;
|
|
330945
|
+
const gateNet = index.connected(roles.gate.source_port_id);
|
|
330946
|
+
const sourceNet = index.connected(roles.sources[0].source_port_id);
|
|
330947
|
+
const drainNet = index.connected(roles.drains[0].source_port_id);
|
|
330948
|
+
if (new Set([gateNet, sourceNet, drainNet]).size !== 3 || index.isRail(gateNet))
|
|
330949
|
+
return;
|
|
330950
|
+
if ([roles.gate, ...roles.sources, ...roles.drains].some((p) => {
|
|
330951
|
+
const pin = index.port(p);
|
|
330952
|
+
return !pin || pin.schematic_sheet_id !== mosfet.schematicSheetId;
|
|
330953
|
+
}))
|
|
330954
|
+
return;
|
|
330955
|
+
const peers = (index.portsByNet.get(gateNet) ?? []).filter((p) => p.source_component_id !== id);
|
|
330956
|
+
if (peers.length !== 2)
|
|
330957
|
+
return;
|
|
330958
|
+
const resistors = peers.map((p) => {
|
|
330959
|
+
const resistorId = p.source_component_id;
|
|
330960
|
+
const component = index.components.get(resistorId);
|
|
330961
|
+
const placement = index.placement(resistorId);
|
|
330962
|
+
const nets = index.twoTerminalNets(resistorId);
|
|
330963
|
+
if (component?.ftype !== "simple_resistor" || !Number.isFinite(component.resistance) || component.resistance <= 0 || !placement || !nets || !index.sameLocalScope(mosfet, placement) || index.portsByComponent.get(resistorId).some((port) => {
|
|
330964
|
+
const pin = index.port(port);
|
|
330965
|
+
return port.do_not_connect || !pin || pin.schematic_sheet_id !== mosfet.schematicSheetId;
|
|
330966
|
+
}))
|
|
330967
|
+
return;
|
|
330968
|
+
return { placement, otherNet: nets.find((net) => net !== gateNet) };
|
|
330969
|
+
});
|
|
330970
|
+
if (resistors.some((r) => !r))
|
|
330971
|
+
return;
|
|
330972
|
+
const shunts = resistors.filter((r) => r.otherNet === sourceNet);
|
|
330973
|
+
const series = resistors.filter((r) => r.otherNet !== sourceNet);
|
|
330974
|
+
if (shunts.length !== 1 || series.length !== 1)
|
|
330975
|
+
return;
|
|
330976
|
+
const gateSourceResistor = shunts[0].placement;
|
|
330977
|
+
const seriesGateResistor = series[0].placement;
|
|
330978
|
+
if (series[0].otherNet === drainNet || index.isRail(series[0].otherNet))
|
|
330979
|
+
return;
|
|
330980
|
+
const maxRecommendedBodyGap = Math.max(6, 3 * Math.max(mosfet.width, mosfet.height));
|
|
330981
|
+
const maxBodyGap = Math.max(bodyGap(mosfet, seriesGateResistor), bodyGap(mosfet, gateSourceResistor));
|
|
330982
|
+
if (maxBodyGap <= maxRecommendedBodyGap)
|
|
330983
|
+
return;
|
|
330984
|
+
this.params.issues.push({
|
|
330985
|
+
lineItemType: "MosfetGateNetworkNotGrouped",
|
|
330986
|
+
mosfetSchematicBox: mosfet,
|
|
330987
|
+
seriesGateResistorSchematicBox: seriesGateResistor,
|
|
330988
|
+
gateSourceResistorSchematicBox: gateSourceResistor,
|
|
330989
|
+
maxBodyGap,
|
|
330990
|
+
maxRecommendedBodyGap,
|
|
330991
|
+
message: `Group ${seriesGateResistor.sourceComponentName ?? seriesGateResistor.sourceComponentId} and ${gateSourceResistor.sourceComponentName ?? gateSourceResistor.sourceComponentId} beside ${mosfet.sourceComponentName ?? id}'s gate/source pins so the gate-drive branch can be read together. Preserve all pin connections, leave room for labels, and reroute affected traces.`
|
|
330992
|
+
});
|
|
330993
|
+
}
|
|
330994
|
+
mosfetPorts(id) {
|
|
330995
|
+
const type = this.index.components.get(id)?.ftype;
|
|
330996
|
+
if (type !== "simple_mosfet" && type !== "simple_chip")
|
|
330997
|
+
return;
|
|
330998
|
+
const ports = this.index.portsByComponent.get(id) ?? [];
|
|
330999
|
+
const gate = ports.filter((p) => hasRole(p, /^(G|GATE)$/));
|
|
331000
|
+
const sources = ports.filter((p) => hasRole(p, /^(S|SOURCE)[0-9]*$/));
|
|
331001
|
+
const drains = ports.filter((p) => hasRole(p, /^(D|DRAIN)[0-9]*$/));
|
|
331002
|
+
if (gate.length !== 1 || !sources.length || !drains.length || gate.length + sources.length + drains.length !== ports.length || new Set([...gate, ...sources, ...drains]).size !== ports.length || ports.some((p) => p.do_not_connect))
|
|
331003
|
+
return;
|
|
331004
|
+
for (const group of [sources, drains])
|
|
331005
|
+
if (new Set(group.map((p) => this.index.connected(p.source_port_id))).size !== 1)
|
|
331006
|
+
return;
|
|
331007
|
+
return { gate: gate[0], sources, drains };
|
|
331008
|
+
}
|
|
331009
|
+
static issueToString(issue) {
|
|
331010
|
+
const attrs = [];
|
|
331011
|
+
addAttr(attrs, "mosfetName", issue.mosfetSchematicBox.sourceComponentName);
|
|
331012
|
+
addAttr(attrs, "seriesGateResistorName", issue.seriesGateResistorSchematicBox.sourceComponentName);
|
|
331013
|
+
addAttr(attrs, "gateSourceResistorName", issue.gateSourceResistorSchematicBox.sourceComponentName);
|
|
331014
|
+
addAttr(attrs, "maxBodyGap", issue.maxBodyGap);
|
|
331015
|
+
addAttr(attrs, "maxRecommendedBodyGap", issue.maxRecommendedBodyGap);
|
|
331016
|
+
addAttr(attrs, "message", issue.message);
|
|
331017
|
+
return `<MosfetGateNetworkNotGrouped ${attrs.join(" ")} />`;
|
|
331018
|
+
}
|
|
331019
|
+
}
|
|
331020
|
+
function hasRole(port, pattern) {
|
|
331021
|
+
return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
|
|
331022
|
+
}
|
|
331023
|
+
function bodyGap(a, b) {
|
|
331024
|
+
return Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));
|
|
331025
|
+
}
|
|
331026
|
+
|
|
331027
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/RelayFlybackDiodePlacementSolver/RelayFlybackDiodePlacementSolver.ts
|
|
331028
|
+
import { BaseSolver as BaseSolver6 } from "@tscircuit/solver-utils";
|
|
331029
|
+
class RelayFlybackDiodePlacementSolver extends BaseSolver6 {
|
|
331030
|
+
params;
|
|
331031
|
+
index;
|
|
331032
|
+
relayIds;
|
|
331033
|
+
currentIndex = 0;
|
|
331034
|
+
constructor(params2) {
|
|
331035
|
+
super();
|
|
331036
|
+
this.params = params2;
|
|
331037
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
331038
|
+
this.relayIds = [...this.index.components.keys()].filter((id) => this.coilPorts(id));
|
|
331039
|
+
this.solved = this.relayIds.length === 0;
|
|
331040
|
+
}
|
|
331041
|
+
_step() {
|
|
331042
|
+
const relayId = this.relayIds[this.currentIndex++];
|
|
331043
|
+
this.solved = this.currentIndex >= this.relayIds.length;
|
|
331044
|
+
if (!relayId)
|
|
331045
|
+
return;
|
|
331046
|
+
const index = this.index;
|
|
331047
|
+
const relay = index.placement(relayId);
|
|
331048
|
+
const coil = this.coilPorts(relayId);
|
|
331049
|
+
if (!relay || coil.some((p) => p.do_not_connect))
|
|
331050
|
+
return;
|
|
331051
|
+
const nets = coil.map((p) => index.connected(p.source_port_id));
|
|
331052
|
+
if (nets[0] === nets[1])
|
|
331053
|
+
return;
|
|
331054
|
+
if (this.relayIds.some((id) => id !== relayId && this.coilPorts(id).every((p) => nets.includes(index.connected(p.source_port_id)))))
|
|
331055
|
+
return;
|
|
331056
|
+
const diodeIds = new Set((index.portsByNet.get(nets[0]) ?? []).filter((p) => index.components.get(p.source_component_id)?.ftype === "simple_diode").map((p) => p.source_component_id).filter((id) => index.twoTerminalNets(id)?.includes(nets[1])));
|
|
331057
|
+
if (diodeIds.size !== 1)
|
|
331058
|
+
return;
|
|
331059
|
+
const diodeId = [...diodeIds][0];
|
|
331060
|
+
const diode = index.placement(diodeId);
|
|
331061
|
+
const anode = this.uniquePort(diodeId, /^(?:ANODE|A)$/);
|
|
331062
|
+
const cathode = this.uniquePort(diodeId, /^(?:CATHODE|K)$/);
|
|
331063
|
+
if (!diode || !index.sameLocalScope(relay, diode) || !anode || !cathode || anode === cathode || anode.do_not_connect || cathode.do_not_connect)
|
|
331064
|
+
return;
|
|
331065
|
+
const anodeNet = index.connected(anode.source_port_id);
|
|
331066
|
+
const cathodeNet = index.connected(cathode.source_port_id);
|
|
331067
|
+
if (index.isRail(anodeNet) || index.groundNets.has(cathodeNet) || !this.hasGroundedDriver(anodeNet, cathodeNet))
|
|
331068
|
+
return;
|
|
331069
|
+
const coilPins = coil.map((p) => index.port(p));
|
|
331070
|
+
const diodePins = [anode, cathode].map((p) => index.port(p));
|
|
331071
|
+
if ([...coilPins, ...diodePins].some((p) => !p || p.schematic_sheet_id !== relay.schematicSheetId))
|
|
331072
|
+
return;
|
|
331073
|
+
const [first, second] = coilPins;
|
|
331074
|
+
const left = Math.min(first.center.x, second.center.x);
|
|
331075
|
+
const right = Math.max(first.center.x, second.center.x);
|
|
331076
|
+
const bottom = Math.min(first.center.y, second.center.y);
|
|
331077
|
+
const top = Math.max(first.center.y, second.center.y);
|
|
331078
|
+
const gapX = Math.max(left - (diode.schX + diode.width / 2), diode.schX - diode.width / 2 - right, 0);
|
|
331079
|
+
const gapY = Math.max(bottom - (diode.schY + diode.height / 2), diode.schY - diode.height / 2 - top, 0);
|
|
331080
|
+
const distanceFromCoilPins = Math.hypot(gapX, gapY);
|
|
331081
|
+
const pinSpan = Math.hypot(right - left, top - bottom);
|
|
331082
|
+
if (distanceFromCoilPins <= Math.max(1.5, 2 * pinSpan) || distanceFromCoilPins > Math.max(8, 4 * Math.max(relay.width, relay.height)))
|
|
331083
|
+
return;
|
|
331084
|
+
if (!this.params.ctx.circuitJson.some((e) => e.type === "schematic_net_label" && e.schematic_sheet_id === relay.schematicSheetId && e.anchor_position && diodePins.some((p) => Math.hypot(p.center.x - e.anchor_position.x, p.center.y - e.anchor_position.y) < 0.01 && !this.hasWireAtPin(p))))
|
|
331085
|
+
return;
|
|
331086
|
+
this.params.issues.push({
|
|
331087
|
+
lineItemType: "FlybackDiodeSeparatedFromRelayCoil",
|
|
331088
|
+
relaySchematicBox: relay,
|
|
331089
|
+
diodeSchematicBox: diode,
|
|
331090
|
+
coilSourcePortIds: [coil[0].source_port_id, coil[1].source_port_id],
|
|
331091
|
+
distanceFromCoilPins,
|
|
331092
|
+
message: `Place ${diode.sourceComponentName ?? diodeId} beside ${relay.sourceComponentName ?? relayId}'s coil pins so the flyback protection loop can be read together. Preserve diode polarity and all pin connections; leave room for labels and reroute affected traces.`
|
|
331093
|
+
});
|
|
331094
|
+
}
|
|
331095
|
+
hasWireAtPin(pin) {
|
|
331096
|
+
return this.params.ctx.circuitJson.some((e) => e.type === "schematic_trace" && e.schematic_sheet_id === pin.schematic_sheet_id && e.edges.some(({ from, to }) => {
|
|
331097
|
+
const dx = to.x - from.x, dy = to.y - from.y;
|
|
331098
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
331099
|
+
const t = lengthSquared ? Math.max(0, Math.min(1, ((pin.center.x - from.x) * dx + (pin.center.y - from.y) * dy) / lengthSquared)) : 0;
|
|
331100
|
+
return Math.hypot(pin.center.x - from.x - t * dx, pin.center.y - from.y - t * dy) < 0.01;
|
|
331101
|
+
}));
|
|
331102
|
+
}
|
|
331103
|
+
uniquePort(id, pattern) {
|
|
331104
|
+
const ports = this.index.portsByComponent.get(id)?.filter((p) => hasHint(p, pattern));
|
|
331105
|
+
return ports?.length === 1 ? ports[0] : undefined;
|
|
331106
|
+
}
|
|
331107
|
+
coilPorts(id) {
|
|
331108
|
+
if (this.index.components.get(id)?.ftype !== "simple_chip")
|
|
331109
|
+
return;
|
|
331110
|
+
const ports = this.index.portsByComponent.get(id) ?? [];
|
|
331111
|
+
if (!this.uniquePort(id, /^(?:COM|COMMON)$/) || !ports.some((p) => hasHint(p, /^(?:NO|NC|NORMALLYOPEN|NORMALLYCLOSED)$/)))
|
|
331112
|
+
return;
|
|
331113
|
+
const coil = ports.filter((p) => hasHint(p, /^(?:COIL[A-B12]|A[12])$/));
|
|
331114
|
+
if (coil.length !== 2)
|
|
331115
|
+
return;
|
|
331116
|
+
for (const [a, b] of [
|
|
331117
|
+
["COILA", "COILB"],
|
|
331118
|
+
["COIL1", "COIL2"],
|
|
331119
|
+
["A1", "A2"]
|
|
331120
|
+
]) {
|
|
331121
|
+
const first = this.uniquePort(id, new RegExp(`^${a}$`));
|
|
331122
|
+
const second = this.uniquePort(id, new RegExp(`^${b}$`));
|
|
331123
|
+
if (first && second && first !== second && !hasHint(first, new RegExp(`^${b}$`)) && !hasHint(second, new RegExp(`^${a}$`)))
|
|
331124
|
+
return [first, second];
|
|
331125
|
+
}
|
|
331126
|
+
}
|
|
331127
|
+
hasGroundedDriver(anodeNet, cathodeNet) {
|
|
331128
|
+
return (this.index.portsByNet.get(anodeNet) ?? []).some((p) => {
|
|
331129
|
+
const id = p.source_component_id;
|
|
331130
|
+
const component = this.index.components.get(id);
|
|
331131
|
+
if (component?.ftype !== "simple_chip" && !(component?.ftype === "simple_transistor" && component.transistor_type === "npn"))
|
|
331132
|
+
return false;
|
|
331133
|
+
if (this.index.portsByComponent.get(id)?.length !== 3)
|
|
331134
|
+
return false;
|
|
331135
|
+
const c = this.uniquePort(id, /^(?:C|COLLECTOR)$/);
|
|
331136
|
+
const e = this.uniquePort(id, /^(?:E|EMITTER)$/);
|
|
331137
|
+
const b = this.uniquePort(id, /^(?:B|BASE)$/);
|
|
331138
|
+
if (!c || !e || !b || new Set([c, e, b]).size !== 3 || [c, e, b].some((p) => p.do_not_connect) || c.source_port_id !== p.source_port_id)
|
|
331139
|
+
return false;
|
|
331140
|
+
const emitterNet = this.index.connected(e.source_port_id), baseNet = this.index.connected(b.source_port_id);
|
|
331141
|
+
return this.index.groundNets.has(emitterNet) && !this.index.powerNets.has(emitterNet) && new Set([anodeNet, cathodeNet, emitterNet, baseNet]).size === 4;
|
|
331142
|
+
});
|
|
331143
|
+
}
|
|
331144
|
+
static issueToString(issue) {
|
|
331145
|
+
const attrs = [];
|
|
331146
|
+
addAttr(attrs, "relayName", issue.relaySchematicBox.sourceComponentName);
|
|
331147
|
+
addAttr(attrs, "diodeName", issue.diodeSchematicBox.sourceComponentName);
|
|
331148
|
+
addAttr(attrs, "distanceFromCoilPins", issue.distanceFromCoilPins);
|
|
331149
|
+
addAttr(attrs, "message", issue.message);
|
|
331150
|
+
return `<FlybackDiodeSeparatedFromRelayCoil ${attrs.join(" ")} />`;
|
|
331151
|
+
}
|
|
331152
|
+
}
|
|
331153
|
+
function hasHint(port, pattern) {
|
|
331154
|
+
return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
|
|
331155
|
+
}
|
|
331156
|
+
|
|
331157
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CurrentSenseShuntPlacementSolver/CurrentSenseShuntPlacementSolver.ts
|
|
331158
|
+
import { BaseSolver as BaseSolver7 } from "@tscircuit/solver-utils";
|
|
330938
331159
|
var EPSILON3 = 0.01;
|
|
331160
|
+
|
|
331161
|
+
class CurrentSenseShuntPlacementSolver extends BaseSolver7 {
|
|
331162
|
+
params;
|
|
331163
|
+
index;
|
|
331164
|
+
hostIds;
|
|
331165
|
+
traces;
|
|
331166
|
+
currentIndex = 0;
|
|
331167
|
+
constructor(params2) {
|
|
331168
|
+
super();
|
|
331169
|
+
this.params = params2;
|
|
331170
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
331171
|
+
this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
|
|
331172
|
+
this.traces = params2.ctx.circuitJson.filter((element) => element.type === "schematic_trace");
|
|
331173
|
+
this.solved = this.hostIds.length === 0;
|
|
331174
|
+
}
|
|
331175
|
+
_step() {
|
|
331176
|
+
const hostId = this.hostIds[this.currentIndex++];
|
|
331177
|
+
this.solved = this.currentIndex >= this.hostIds.length;
|
|
331178
|
+
if (!hostId)
|
|
331179
|
+
return;
|
|
331180
|
+
const index = this.index;
|
|
331181
|
+
const host = index.placement(hostId);
|
|
331182
|
+
const ports = index.portsByComponent.get(hostId) ?? [];
|
|
331183
|
+
const positive = ports.filter((port) => inputRole(port) === "positive");
|
|
331184
|
+
const negative = ports.filter((port) => inputRole(port) === "negative");
|
|
331185
|
+
const outputs = ports.filter((port) => hasHint2(port, /^(?:OUT|VOUT|OUTPUT)$/));
|
|
331186
|
+
if (!host || positive.length !== 1 || negative.length !== 1 || outputs.length !== 1 || !ports.some((port) => hasHint2(port, /^(?:VS|VCC|VDD)$/)) || !ports.some((port) => hasHint2(port, /^(?:GND|GROUND|VSS)$/)))
|
|
331187
|
+
return;
|
|
331188
|
+
const inputs = [positive[0], negative[0]];
|
|
331189
|
+
const nets = inputs.map((port) => index.connected(port.source_port_id));
|
|
331190
|
+
if (inputs.some((port) => port.do_not_connect) || nets[0] === nets[1] || nets.includes(index.connected(outputs[0].source_port_id)))
|
|
331191
|
+
return;
|
|
331192
|
+
const pins = inputs.map((port) => index.port(port));
|
|
331193
|
+
const [positivePin, negativePin] = pins;
|
|
331194
|
+
if (!positivePin || !negativePin || !positivePin.facing_direction || positivePin.facing_direction !== negativePin.facing_direction || pins.some((pin) => pin.schematic_sheet_id !== host.schematicSheetId))
|
|
331195
|
+
return;
|
|
331196
|
+
const resistorIds = new Set((index.portsByNet.get(nets[0]) ?? []).filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id).filter((id) => index.twoTerminalNets(id)?.includes(nets[1])));
|
|
331197
|
+
if (resistorIds.size !== 1)
|
|
331198
|
+
return;
|
|
331199
|
+
const shuntId = [...resistorIds][0];
|
|
331200
|
+
const component = index.components.get(shuntId);
|
|
331201
|
+
if (component?.ftype !== "simple_resistor" || !Number.isFinite(component.resistance) || component.resistance <= 0 || component.resistance > 1)
|
|
331202
|
+
return;
|
|
331203
|
+
if (nets.some((net) => (index.portsByNet.get(net) ?? []).some((port) => port.source_component_id !== hostId && inputRole(port) !== undefined && index.components.get(port.source_component_id)?.ftype === "simple_chip")))
|
|
331204
|
+
return;
|
|
331205
|
+
const shunt = index.placement(shuntId);
|
|
331206
|
+
if (!shunt || !index.sameLocalScope(host, shunt))
|
|
331207
|
+
return;
|
|
331208
|
+
const shuntPorts = index.portsByComponent.get(shuntId);
|
|
331209
|
+
if (shuntPorts.some((port) => port.do_not_connect))
|
|
331210
|
+
return;
|
|
331211
|
+
const shuntPins = nets.map((net) => index.port(shuntPorts.find((port) => index.connected(port.source_port_id) === net)));
|
|
331212
|
+
if (shuntPins.some((pin) => !pin || pin.schematic_sheet_id !== host.schematicSheetId))
|
|
331213
|
+
return;
|
|
331214
|
+
const horizontalInputs = positivePin.facing_direction === "left" || positivePin.facing_direction === "right";
|
|
331215
|
+
const across = (point) => horizontalInputs ? point.y : point.x;
|
|
331216
|
+
const first = across(positivePin.center), second = across(negativePin.center);
|
|
331217
|
+
const span = Math.abs(first - second);
|
|
331218
|
+
if (span < EPSILON3)
|
|
331219
|
+
return;
|
|
331220
|
+
const shuntAcross = horizontalInputs ? shunt.schY : shunt.schX;
|
|
331221
|
+
const halfSize = (horizontalInputs ? shunt.height : shunt.width) / 2;
|
|
331222
|
+
const inputBandGap = Math.max(Math.min(first, second) - (shuntAcross + halfSize), shuntAcross - halfSize - Math.max(first, second));
|
|
331223
|
+
if (inputBandGap <= Math.max(1.5, 2 * span) || Math.hypot(shunt.schX - host.schX, shunt.schY - host.schY) > Math.max(8, 4 * Math.max(host.width, host.height)))
|
|
331224
|
+
return;
|
|
331225
|
+
const visible = pins.map((pin, i) => this.hasVisibleConnection(shuntPins[i], pin, nets[i]));
|
|
331226
|
+
if (visible[0] === visible[1])
|
|
331227
|
+
return;
|
|
331228
|
+
const labeledIndex = visible[0] ? 1 : 0;
|
|
331229
|
+
const labeledNet = nets[labeledIndex];
|
|
331230
|
+
if (!this.params.ctx.circuitJson.some((element) => {
|
|
331231
|
+
if (element.type !== "schematic_net_label" || element.schematic_sheet_id !== host.schematicSheetId)
|
|
331232
|
+
return false;
|
|
331233
|
+
if (element.source_net_id && (index.connected(element.source_net_id) === labeledNet || index.connected(`connectivity:${element.source_net_id}`) === labeledNet))
|
|
331234
|
+
return true;
|
|
331235
|
+
const pin = shuntPins[labeledIndex].center;
|
|
331236
|
+
if (element.anchor_position && Math.hypot(element.anchor_position.x - pin.x, element.anchor_position.y - pin.y) < EPSILON3)
|
|
331237
|
+
return true;
|
|
331238
|
+
return element.source_trace_id !== undefined && this.sourceTraceTouchesNet(element.source_trace_id, labeledNet);
|
|
331239
|
+
}))
|
|
331240
|
+
return;
|
|
331241
|
+
this.params.issues.push({
|
|
331242
|
+
lineItemType: "CurrentSenseShuntSeparatedFromInputs",
|
|
331243
|
+
amplifierSchematicBox: host,
|
|
331244
|
+
shuntSchematicBox: shunt,
|
|
331245
|
+
positiveInputSourcePortId: inputs[0].source_port_id,
|
|
331246
|
+
negativeInputSourcePortId: inputs[1].source_port_id,
|
|
331247
|
+
inputBandGap,
|
|
331248
|
+
message: `Place ${shunt.sourceComponentName ?? shuntId} near ${host.sourceComponentName ?? hostId}.${inputs[0].name}/${inputs[1].name}, so both sense connections can be read together. Move or rotate the shunt as needed; preserve all pin connections and leave room for labels.`
|
|
331249
|
+
});
|
|
331250
|
+
}
|
|
331251
|
+
hasVisibleConnection(from, to, net) {
|
|
331252
|
+
const edges = this.traces.filter((trace) => {
|
|
331253
|
+
if (trace.schematic_sheet_id !== from.schematic_sheet_id)
|
|
331254
|
+
return false;
|
|
331255
|
+
if (trace.subcircuit_connectivity_map_key)
|
|
331256
|
+
return this.index.connected(`connectivity:${trace.subcircuit_connectivity_map_key}`) === net;
|
|
331257
|
+
if (this.sourceTraceTouchesNet(trace.source_trace_id, net))
|
|
331258
|
+
return true;
|
|
331259
|
+
const endpoints = [trace.edges[0]?.from, trace.edges.at(-1)?.to];
|
|
331260
|
+
const endpointNets = new Set(this.params.ctx.circuitJson.flatMap((element) => element.type === "schematic_port" && element.source_port_id && element.schematic_sheet_id === trace.schematic_sheet_id && endpoints.some((point) => point && Math.hypot(point.x - element.center.x, point.y - element.center.y) < EPSILON3) ? [this.index.connected(element.source_port_id)] : []));
|
|
331261
|
+
return endpointNets.size === 1 && endpointNets.has(net);
|
|
331262
|
+
}).flatMap((trace) => trace.edges);
|
|
331263
|
+
const reached = edges.filter((edge) => onSegment4(from.center, edge.from, edge.to));
|
|
331264
|
+
const visited = new Set;
|
|
331265
|
+
for (let i = 0;i < reached.length; i++) {
|
|
331266
|
+
const current = reached[i];
|
|
331267
|
+
if (onSegment4(to.center, current.from, current.to))
|
|
331268
|
+
return true;
|
|
331269
|
+
for (const [edgeIndex, edge] of edges.entries()) {
|
|
331270
|
+
if (visited.has(edgeIndex) || ![current.from, current.to].some((point) => onSegment4(point, edge.from, edge.to)) && ![edge.from, edge.to].some((point) => onSegment4(point, current.from, current.to)))
|
|
331271
|
+
continue;
|
|
331272
|
+
visited.add(edgeIndex);
|
|
331273
|
+
reached.push(edge);
|
|
331274
|
+
}
|
|
331275
|
+
}
|
|
331276
|
+
return false;
|
|
331277
|
+
}
|
|
331278
|
+
sourceTraceTouchesNet(traceId, net) {
|
|
331279
|
+
if (!traceId)
|
|
331280
|
+
return false;
|
|
331281
|
+
const source = this.params.ctx.circuitJson.find((element) => element.type === "source_trace" && element.source_trace_id === traceId);
|
|
331282
|
+
return source?.type === "source_trace" && source.connected_source_port_ids.some((id) => this.index.connected(id) === net);
|
|
331283
|
+
}
|
|
331284
|
+
static issueToString(issue) {
|
|
331285
|
+
const attrs = [];
|
|
331286
|
+
addAttr(attrs, "amplifierName", issue.amplifierSchematicBox.sourceComponentName);
|
|
331287
|
+
addAttr(attrs, "shuntName", issue.shuntSchematicBox.sourceComponentName);
|
|
331288
|
+
addAttr(attrs, "inputBandGap", issue.inputBandGap);
|
|
331289
|
+
addAttr(attrs, "message", issue.message);
|
|
331290
|
+
return `<CurrentSenseShuntSeparatedFromInputs ${attrs.join(" ")} />`;
|
|
331291
|
+
}
|
|
331292
|
+
}
|
|
331293
|
+
function hasHint2(port, pattern) {
|
|
331294
|
+
return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
|
|
331295
|
+
}
|
|
331296
|
+
function inputRole(port) {
|
|
331297
|
+
const positive = hasHint2(port, /^(?:IN\+|VIN\+|INPOS|VINPOS)$/);
|
|
331298
|
+
const negative = hasHint2(port, /^(?:IN-|VIN-|INNEG|VINNEG)$/);
|
|
331299
|
+
return positive === negative ? undefined : positive ? "positive" : "negative";
|
|
331300
|
+
}
|
|
331301
|
+
function onSegment4(point, from, to) {
|
|
331302
|
+
const dx = to.x - from.x, dy = to.y - from.y;
|
|
331303
|
+
const length = Math.hypot(dx, dy);
|
|
331304
|
+
if (length < EPSILON3)
|
|
331305
|
+
return Math.hypot(point.x - from.x, point.y - from.y) < EPSILON3;
|
|
331306
|
+
const projection = ((point.x - from.x) * dx + (point.y - from.y) * dy) / length;
|
|
331307
|
+
return projection >= -EPSILON3 && projection <= length + EPSILON3 && Math.abs((point.x - from.x) * dy - (point.y - from.y) * dx) / length < EPSILON3;
|
|
331308
|
+
}
|
|
331309
|
+
|
|
331310
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/VoltageDividerPlacementSolver/VoltageDividerPlacementSolver.ts
|
|
331311
|
+
import { BaseSolver as BaseSolver8 } from "@tscircuit/solver-utils";
|
|
331312
|
+
class VoltageDividerPlacementSolver extends BaseSolver8 {
|
|
331313
|
+
params;
|
|
331314
|
+
index;
|
|
331315
|
+
positiveNets = new Set;
|
|
331316
|
+
resistorIds;
|
|
331317
|
+
currentIndex = 0;
|
|
331318
|
+
constructor(params2) {
|
|
331319
|
+
super();
|
|
331320
|
+
this.params = params2;
|
|
331321
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
331322
|
+
this.resistorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_resistor").map((component) => component.source_component_id);
|
|
331323
|
+
for (const element of params2.ctx.circuitJson) {
|
|
331324
|
+
if (element.type === "source_net" && element.is_positive_voltage_source)
|
|
331325
|
+
this.positiveNets.add(this.index.connected(element.source_net_id));
|
|
331326
|
+
}
|
|
331327
|
+
this.solved = this.resistorIds.length === 0;
|
|
331328
|
+
}
|
|
331329
|
+
_step() {
|
|
331330
|
+
const supplyId = this.resistorIds[this.currentIndex++];
|
|
331331
|
+
this.solved = this.currentIndex >= this.resistorIds.length;
|
|
331332
|
+
if (!supplyId || !this.isResistor(supplyId))
|
|
331333
|
+
return;
|
|
331334
|
+
const index = this.index;
|
|
331335
|
+
const nets = index.twoTerminalNets(supplyId);
|
|
331336
|
+
if (!nets)
|
|
331337
|
+
return;
|
|
331338
|
+
const rails = nets.filter((net) => index.isRail(net));
|
|
331339
|
+
if (rails.length !== 1)
|
|
331340
|
+
return;
|
|
331341
|
+
const supplyNet = rails[0];
|
|
331342
|
+
if (!this.positiveNets.has(supplyNet) || index.groundNets.has(supplyNet))
|
|
331343
|
+
return;
|
|
331344
|
+
const tap = nets.find((net) => net !== supplyNet);
|
|
331345
|
+
const tapPorts = index.portsByNet.get(tap) ?? [];
|
|
331346
|
+
const resistorIds = new Set(tapPorts.filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id));
|
|
331347
|
+
if (resistorIds.size !== 2)
|
|
331348
|
+
return;
|
|
331349
|
+
const groundId = [...resistorIds].find((id) => id !== supplyId);
|
|
331350
|
+
if (!this.isResistor(groundId))
|
|
331351
|
+
return;
|
|
331352
|
+
const groundNets = index.twoTerminalNets(groundId);
|
|
331353
|
+
const groundNet = groundNets?.find((net) => net !== tap);
|
|
331354
|
+
if (!groundNets?.includes(tap) || !groundNet || !index.groundNets.has(groundNet) || index.powerNets.has(groundNet) || !tapPorts.some((port) => !resistorIds.has(port.source_component_id)))
|
|
331355
|
+
return;
|
|
331356
|
+
const supply = index.placement(supplyId);
|
|
331357
|
+
const ground = index.placement(groundId);
|
|
331358
|
+
if (!supply || !ground || !index.sameLocalScope(supply, ground))
|
|
331359
|
+
return;
|
|
331360
|
+
const supplyTap = this.getDownwardResistorPorts(supplyId, supplyNet, tap);
|
|
331361
|
+
const groundTap = this.getDownwardResistorPorts(groundId, tap, groundNet);
|
|
331362
|
+
if (!supplyTap || !groundTap)
|
|
331363
|
+
return;
|
|
331364
|
+
const reversedBodyGap = ground.schY - ground.height / 2 - (supply.schY + supply.height / 2);
|
|
331365
|
+
if (reversedBodyGap <= 1.5)
|
|
331366
|
+
return;
|
|
331367
|
+
this.params.issues.push({
|
|
331368
|
+
lineItemType: "VoltageDividerSupplyResistorBelowGroundResistor",
|
|
331369
|
+
supplyResistorSchematicBox: supply,
|
|
331370
|
+
groundResistorSchematicBox: ground,
|
|
331371
|
+
supplyTapSourcePortId: supplyTap.bottom.source_port_id,
|
|
331372
|
+
groundTapSourcePortId: groundTap.top.source_port_id,
|
|
331373
|
+
reversedBodyGap,
|
|
331374
|
+
message: `Place ${supply.sourceComponentName ?? supplyId} above ${ground.sourceComponentName ?? groundId}, close enough to read their shared divider tap. Preserve all connections and leave room for labels; exact alignment is not required.`
|
|
331375
|
+
});
|
|
331376
|
+
}
|
|
331377
|
+
isResistor(id) {
|
|
331378
|
+
const component = this.index.components.get(id);
|
|
331379
|
+
return component?.ftype === "simple_resistor" && Number.isFinite(component.resistance) && component.resistance > 0;
|
|
331380
|
+
}
|
|
331381
|
+
getDownwardResistorPorts(id, topNet, bottomNet) {
|
|
331382
|
+
const index = this.index;
|
|
331383
|
+
const placement = index.placement(id);
|
|
331384
|
+
const ports = index.portsByComponent.get(id);
|
|
331385
|
+
if (ports.some((port) => port.do_not_connect))
|
|
331386
|
+
return;
|
|
331387
|
+
const top = ports.find((port) => index.connected(port.source_port_id) === topNet);
|
|
331388
|
+
const bottom = ports.find((port) => index.connected(port.source_port_id) === bottomNet);
|
|
331389
|
+
if (!top || !bottom)
|
|
331390
|
+
return;
|
|
331391
|
+
const topPin = index.port(top);
|
|
331392
|
+
const bottomPin = index.port(bottom);
|
|
331393
|
+
if (!topPin || !bottomPin || topPin.schematic_sheet_id !== placement.schematicSheetId || bottomPin.schematic_sheet_id !== placement.schematicSheetId || topPin.facing_direction !== "up" || bottomPin.facing_direction !== "down" || topPin.center.y <= bottomPin.center.y)
|
|
331394
|
+
return;
|
|
331395
|
+
return { top, bottom };
|
|
331396
|
+
}
|
|
331397
|
+
static issueToString(issue) {
|
|
331398
|
+
const attrs = [];
|
|
331399
|
+
addAttr(attrs, "supplyResistorName", issue.supplyResistorSchematicBox.sourceComponentName);
|
|
331400
|
+
addAttr(attrs, "groundResistorName", issue.groundResistorSchematicBox.sourceComponentName);
|
|
331401
|
+
addAttr(attrs, "reversedBodyGap", issue.reversedBodyGap);
|
|
331402
|
+
addAttr(attrs, "message", issue.message);
|
|
331403
|
+
return `<VoltageDividerSupplyResistorBelowGroundResistor ${attrs.join(" ")} />`;
|
|
331404
|
+
}
|
|
331405
|
+
}
|
|
331406
|
+
|
|
331407
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/RegulatorInputOutputCapacitorPlacementSolver/RegulatorInputOutputCapacitorPlacementSolver.ts
|
|
331408
|
+
import { BaseSolver as BaseSolver9 } from "@tscircuit/solver-utils";
|
|
331409
|
+
class RegulatorInputOutputCapacitorPlacementSolver extends BaseSolver9 {
|
|
331410
|
+
params;
|
|
331411
|
+
index;
|
|
331412
|
+
hostIds;
|
|
331413
|
+
currentIndex = 0;
|
|
331414
|
+
constructor(params2) {
|
|
331415
|
+
super();
|
|
331416
|
+
this.params = params2;
|
|
331417
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
331418
|
+
this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
|
|
331419
|
+
this.solved = this.hostIds.length === 0;
|
|
331420
|
+
}
|
|
331421
|
+
_step() {
|
|
331422
|
+
const hostId = this.hostIds[this.currentIndex++];
|
|
331423
|
+
this.solved = this.currentIndex >= this.hostIds.length;
|
|
331424
|
+
if (!hostId)
|
|
331425
|
+
return;
|
|
331426
|
+
const index = this.index;
|
|
331427
|
+
const host = index.placement(hostId);
|
|
331428
|
+
const ports = index.portsByComponent.get(hostId) ?? [];
|
|
331429
|
+
if (!host || ports.some((port) => !portRole(port)))
|
|
331430
|
+
return;
|
|
331431
|
+
const inputs = ports.filter((port) => portRole(port) === "input");
|
|
331432
|
+
const outputs = ports.filter((port) => portRole(port) === "output");
|
|
331433
|
+
const grounds = ports.filter((port) => portRole(port) === "ground");
|
|
331434
|
+
if (inputs.length !== 1 || outputs.length !== 1 || !grounds.length)
|
|
331435
|
+
return;
|
|
331436
|
+
const input = inputs[0];
|
|
331437
|
+
const output = outputs[0];
|
|
331438
|
+
if ([input, output, ...grounds].some((port) => port.do_not_connect))
|
|
331439
|
+
return;
|
|
331440
|
+
const inputNet = index.connected(input.source_port_id);
|
|
331441
|
+
const outputNet = index.connected(output.source_port_id);
|
|
331442
|
+
const groundNets = new Set(grounds.map((port) => index.connected(port.source_port_id)));
|
|
331443
|
+
if (groundNets.size !== 1)
|
|
331444
|
+
return;
|
|
331445
|
+
const groundNet = [...groundNets][0];
|
|
331446
|
+
if (new Set([inputNet, outputNet, groundNet]).size !== 3 || !(index.groundNets.has(groundNet) || grounds.some((port) => port.requires_ground || port.provides_ground)) || !(index.powerNets.has(inputNet) || input.requires_power) || !(index.powerNets.has(outputNet) || output.provides_power))
|
|
331447
|
+
return;
|
|
331448
|
+
const inputPin = index.port(input);
|
|
331449
|
+
const outputPin = index.port(output);
|
|
331450
|
+
if (!inputPin || !outputPin || inputPin.schematic_sheet_id !== host.schematicSheetId || outputPin.schematic_sheet_id !== host.schematicSheetId)
|
|
331451
|
+
return;
|
|
331452
|
+
const horizontal = inputPin.facing_direction === "left" && outputPin.facing_direction === "right" || inputPin.facing_direction === "right" && outputPin.facing_direction === "left";
|
|
331453
|
+
const vertical = inputPin.facing_direction === "up" && outputPin.facing_direction === "down" || inputPin.facing_direction === "down" && outputPin.facing_direction === "up";
|
|
331454
|
+
if (!horizontal && !vertical)
|
|
331455
|
+
return;
|
|
331456
|
+
const sign = outputPin.facing_direction === "right" || outputPin.facing_direction === "up" ? 1 : -1;
|
|
331457
|
+
const pinSeparation = sign * (horizontal ? outputPin.center.x - inputPin.center.x : outputPin.center.y - inputPin.center.y);
|
|
331458
|
+
if (pinSeparation <= 0.01)
|
|
331459
|
+
return;
|
|
331460
|
+
const inputCap = this.localCapacitor(host, inputNet, groundNet);
|
|
331461
|
+
const outputCap = this.localCapacitor(host, outputNet, groundNet);
|
|
331462
|
+
if (!inputCap || !outputCap)
|
|
331463
|
+
return;
|
|
331464
|
+
const beyondOppositeSide = (cap, side) => {
|
|
331465
|
+
const distance = side * sign * (horizontal ? cap.schX - host.schX : cap.schY - host.schY);
|
|
331466
|
+
const halfBodies = horizontal ? (host.width + cap.width) / 2 : (host.height + cap.height) / 2;
|
|
331467
|
+
return distance > halfBodies + 0.2;
|
|
331468
|
+
};
|
|
331469
|
+
if (!beyondOppositeSide(inputCap, 1) || !beyondOppositeSide(outputCap, -1))
|
|
331470
|
+
return;
|
|
331471
|
+
const name = host.sourceComponentName ?? hostId;
|
|
331472
|
+
this.params.issues.push({
|
|
331473
|
+
lineItemType: "RegulatorCapacitorsOnWrongSides",
|
|
331474
|
+
regulatorSchematicBox: host,
|
|
331475
|
+
inputCapacitorSchematicBox: inputCap,
|
|
331476
|
+
outputCapacitorSchematicBox: outputCap,
|
|
331477
|
+
inputSourcePortId: input.source_port_id,
|
|
331478
|
+
outputSourcePortId: output.source_port_id,
|
|
331479
|
+
message: `Place ${inputCap.sourceComponentName} near ${name}.${input.name} on the ${inputPin.facing_direction} side and ${outputCap.sourceComponentName} near ${name}.${output.name} on the ${outputPin.facing_direction} side. Preserve all connections and leave room for labels; exact alignment is not required.`
|
|
331480
|
+
});
|
|
331481
|
+
}
|
|
331482
|
+
localCapacitor(host, rail, ground) {
|
|
331483
|
+
const index = this.index;
|
|
331484
|
+
const candidates = [];
|
|
331485
|
+
const maxDistance = Math.max(6, 4 * Math.max(host.width, host.height));
|
|
331486
|
+
const ids = new Set((index.portsByNet.get(rail) ?? []).map((port) => port.source_component_id));
|
|
331487
|
+
for (const id of ids) {
|
|
331488
|
+
if (index.components.get(id)?.ftype !== "simple_capacitor")
|
|
331489
|
+
continue;
|
|
331490
|
+
const nets = index.twoTerminalNets(id);
|
|
331491
|
+
const cap = index.placement(id);
|
|
331492
|
+
if (!nets?.includes(ground) || !cap || !index.sameLocalScope(host, cap))
|
|
331493
|
+
continue;
|
|
331494
|
+
if (Math.hypot(cap.schX - host.schX, cap.schY - host.schY) > maxDistance)
|
|
331495
|
+
continue;
|
|
331496
|
+
const ports = index.portsByComponent.get(id);
|
|
331497
|
+
if (ports.some((port) => port.do_not_connect || !index.port(port) || index.port(port).schematic_sheet_id !== host.schematicSheetId))
|
|
331498
|
+
continue;
|
|
331499
|
+
candidates.push(cap);
|
|
331500
|
+
}
|
|
331501
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
331502
|
+
}
|
|
331503
|
+
static issueToString(issue) {
|
|
331504
|
+
const attrs = [];
|
|
331505
|
+
addAttr(attrs, "regulatorName", issue.regulatorSchematicBox.sourceComponentName);
|
|
331506
|
+
addAttr(attrs, "inputCapacitorName", issue.inputCapacitorSchematicBox.sourceComponentName);
|
|
331507
|
+
addAttr(attrs, "outputCapacitorName", issue.outputCapacitorSchematicBox.sourceComponentName);
|
|
331508
|
+
addAttr(attrs, "message", issue.message);
|
|
331509
|
+
return `<RegulatorCapacitorsOnWrongSides ${attrs.join(" ")} />`;
|
|
331510
|
+
}
|
|
331511
|
+
}
|
|
331512
|
+
function portRole(port) {
|
|
331513
|
+
const roles = new Set;
|
|
331514
|
+
for (const hint of [port.name, ...port.port_hints ?? []]) {
|
|
331515
|
+
const name = hint.toUpperCase().replace(/[ _-]/g, "");
|
|
331516
|
+
if (/^(?:VIN|IN|INPUT)$/.test(name))
|
|
331517
|
+
roles.add("input");
|
|
331518
|
+
else if (/^(?:VOUT|OUT|OUTPUT)$/.test(name))
|
|
331519
|
+
roles.add("output");
|
|
331520
|
+
else if (/^(?:GND\d*|VSS)$/.test(name))
|
|
331521
|
+
roles.add("ground");
|
|
331522
|
+
else if (/^(?:EN|ENABLE|CE|SHDN|NC\d*|EP|PAD|ADJ|FB|BYP|BYPASS|NR|PG|PGOOD)$/.test(name))
|
|
331523
|
+
roles.add("control");
|
|
331524
|
+
}
|
|
331525
|
+
return roles.size === 1 ? [...roles][0] : undefined;
|
|
331526
|
+
}
|
|
331527
|
+
|
|
331528
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/ConnectorPlacementSolver/ConnectorPlacementSolver.ts
|
|
331529
|
+
import { BaseSolver as BaseSolver10 } from "@tscircuit/solver-utils";
|
|
331530
|
+
|
|
331531
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/geometry.ts
|
|
331532
|
+
function centeredRect(cx, cy, w, h) {
|
|
331533
|
+
return {
|
|
331534
|
+
left: cx - w / 2,
|
|
331535
|
+
right: cx + w / 2,
|
|
331536
|
+
top: cy + h / 2,
|
|
331537
|
+
bottom: cy - h / 2
|
|
331538
|
+
};
|
|
331539
|
+
}
|
|
331540
|
+
function rectOverlap(a, b) {
|
|
331541
|
+
const ow = Math.min(a.right, b.right) - Math.max(a.left, b.left);
|
|
331542
|
+
const oh = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
|
|
331543
|
+
return ow > 0 && oh > 0 ? { ow, oh } : null;
|
|
331544
|
+
}
|
|
331545
|
+
|
|
331546
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/ConnectorPlacementSolver/ConnectorPlacementSolver.ts
|
|
331547
|
+
var EPSILON4 = 0.01;
|
|
330939
331548
|
var directions = {
|
|
330940
331549
|
right: { x: 1, y: 0 },
|
|
330941
331550
|
left: { x: -1, y: 0 },
|
|
@@ -330944,10 +331553,10 @@ var directions = {
|
|
|
330944
331553
|
};
|
|
330945
331554
|
var dot2 = (a, b) => a.x * b.x + a.y * b.y;
|
|
330946
331555
|
var distance49 = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
330947
|
-
var near = (a, b) => distance49(a, b) <=
|
|
331556
|
+
var near = (a, b) => distance49(a, b) <= EPSILON4;
|
|
330948
331557
|
var round = (value) => Math.round(value * 100) / 100;
|
|
330949
331558
|
|
|
330950
|
-
class ConnectorPlacementSolver extends
|
|
331559
|
+
class ConnectorPlacementSolver extends BaseSolver10 {
|
|
330951
331560
|
params;
|
|
330952
331561
|
constructor(params2) {
|
|
330953
331562
|
super();
|
|
@@ -331015,7 +331624,7 @@ class ConnectorPlacementSolver extends BaseSolver5 {
|
|
|
331015
331624
|
continue;
|
|
331016
331625
|
const detours = detouredConnections.flat();
|
|
331017
331626
|
const ordered = [...connections].sort((a, b) => dot2(a.pin.center, across) - dot2(b.pin.center, across));
|
|
331018
|
-
if (ordered.some((c, i) => i > 0 && dot2(c.peer.center, across) <= dot2(ordered[i - 1].peer.center, across) +
|
|
331627
|
+
if (ordered.some((c, i) => i > 0 && dot2(c.peer.center, across) <= dot2(ordered[i - 1].peer.center, across) + EPSILON4))
|
|
331019
331628
|
continue;
|
|
331020
331629
|
const center = { x: connector.schX, y: connector.schY };
|
|
331021
331630
|
const pinOffset = Math.max(...connections.map((c) => dot2(c.pin.center, along) - dot2(center, along)));
|
|
@@ -331031,7 +331640,7 @@ class ConnectorPlacementSolver extends BaseSolver5 {
|
|
|
331031
331640
|
x: pin.center.x + delta.x,
|
|
331032
331641
|
y: pin.center.y + delta.y
|
|
331033
331642
|
});
|
|
331034
|
-
if (connections.some((c) => distance49(movedPin(c.pin), c.peer.center) > distance49(c.pin.center, c.peer.center) +
|
|
331643
|
+
if (connections.some((c) => distance49(movedPin(c.pin), c.peer.center) > distance49(c.pin.center, c.peer.center) + EPSILON4))
|
|
331035
331644
|
continue;
|
|
331036
331645
|
const before = connections.reduce((sum, c) => sum + distance49(c.pin.center, c.peer.center), 0);
|
|
331037
331646
|
const after = connections.reduce((sum, c) => sum + distance49(movedPin(c.pin), c.peer.center), 0);
|
|
@@ -331118,7 +331727,7 @@ function bendCount(trace) {
|
|
|
331118
331727
|
return 0;
|
|
331119
331728
|
if (near(edge.from, edge.to))
|
|
331120
331729
|
continue;
|
|
331121
|
-
const axis = Math.abs(edge.from.y - edge.to.y) <
|
|
331730
|
+
const axis = Math.abs(edge.from.y - edge.to.y) < EPSILON4 ? "x" : Math.abs(edge.from.x - edge.to.x) < EPSILON4 ? "y" : undefined;
|
|
331122
331731
|
if (!axis)
|
|
331123
331732
|
return 0;
|
|
331124
331733
|
if (previousAxis && previousAxis !== axis)
|
|
@@ -331133,8 +331742,8 @@ function segmentCrossesBox(a, b, box) {
|
|
|
331133
331742
|
}
|
|
331134
331743
|
|
|
331135
331744
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/LowSideTransistorPlacementSolver/LowSideTransistorPlacementSolver.ts
|
|
331136
|
-
import { BaseSolver as
|
|
331137
|
-
class LowSideTransistorPlacementSolver extends
|
|
331745
|
+
import { BaseSolver as BaseSolver11 } from "@tscircuit/solver-utils";
|
|
331746
|
+
class LowSideTransistorPlacementSolver extends BaseSolver11 {
|
|
331138
331747
|
index;
|
|
331139
331748
|
positiveNets = new Set;
|
|
331140
331749
|
transistorIds;
|
|
@@ -331253,8 +331862,129 @@ class LowSideTransistorPlacementSolver extends BaseSolver6 {
|
|
|
331253
331862
|
}
|
|
331254
331863
|
}
|
|
331255
331864
|
|
|
331865
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/UsbSeriesResistorPlacementSolver/UsbSeriesResistorPlacementSolver.ts
|
|
331866
|
+
import { BaseSolver as BaseSolver12 } from "@tscircuit/solver-utils";
|
|
331867
|
+
class UsbSeriesResistorPlacementSolver extends BaseSolver12 {
|
|
331868
|
+
params;
|
|
331869
|
+
index;
|
|
331870
|
+
hostIds;
|
|
331871
|
+
reportedPairs = new Set;
|
|
331872
|
+
currentIndex = 0;
|
|
331873
|
+
constructor(params2) {
|
|
331874
|
+
super();
|
|
331875
|
+
this.params = params2;
|
|
331876
|
+
this.index = new PlacementNetworkIndex(params2.ctx);
|
|
331877
|
+
this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
|
|
331878
|
+
this.solved = this.hostIds.length === 0;
|
|
331879
|
+
}
|
|
331880
|
+
_step() {
|
|
331881
|
+
const hostId = this.hostIds[this.currentIndex++];
|
|
331882
|
+
this.solved = this.currentIndex >= this.hostIds.length;
|
|
331883
|
+
if (!hostId)
|
|
331884
|
+
return;
|
|
331885
|
+
const ports = this.index.portsByComponent.get(hostId) ?? [];
|
|
331886
|
+
const positivePorts = ports.filter((port) => usbRole(port) === "positive");
|
|
331887
|
+
const negativePorts = ports.filter((port) => usbRole(port) === "negative");
|
|
331888
|
+
if (positivePorts.length !== 1 || negativePorts.length !== 1)
|
|
331889
|
+
return;
|
|
331890
|
+
const positivePort = positivePorts[0];
|
|
331891
|
+
const negativePort = negativePorts[0];
|
|
331892
|
+
const positive = this.seriesResistor(positivePort);
|
|
331893
|
+
const negative = this.seriesResistor(negativePort);
|
|
331894
|
+
if (!positive || !negative || positive.axis !== negative.axis || !this.index.sameLocalScope(positive.placement, negative.placement) || new Set([
|
|
331895
|
+
positive.hostNet,
|
|
331896
|
+
negative.hostNet,
|
|
331897
|
+
positive.interfaceNet,
|
|
331898
|
+
negative.interfaceNet
|
|
331899
|
+
]).size !== 4 || !this.shareInterface(positive, negative, hostId))
|
|
331900
|
+
return;
|
|
331901
|
+
const pairKey = [positive.id, negative.id].sort().join("\x00");
|
|
331902
|
+
if (this.reportedPairs.has(pairKey))
|
|
331903
|
+
return;
|
|
331904
|
+
const a = positive.placement;
|
|
331905
|
+
const b = negative.placement;
|
|
331906
|
+
const horizontal = positive.axis === "horizontal";
|
|
331907
|
+
const along = Math.abs(horizontal ? a.schX - b.schX : a.schY - b.schY);
|
|
331908
|
+
const across = Math.abs(horizontal ? a.schY - b.schY : a.schX - b.schX);
|
|
331909
|
+
const alongA = horizontal ? a.width : a.height;
|
|
331910
|
+
const alongB = horizontal ? b.width : b.height;
|
|
331911
|
+
const acrossA = horizontal ? a.height : a.width;
|
|
331912
|
+
const acrossB = horizontal ? b.height : b.width;
|
|
331913
|
+
const bodyGap = along - (alongA + alongB) / 2;
|
|
331914
|
+
if (bodyGap < Math.max(alongA, alongB) || across >= (acrossA + acrossB) / 2 - 0.01)
|
|
331915
|
+
return;
|
|
331916
|
+
this.reportedPairs.add(pairKey);
|
|
331917
|
+
const positiveName = a.sourceComponentName ?? positive.id;
|
|
331918
|
+
const negativeName = b.sourceComponentName ?? negative.id;
|
|
331919
|
+
this.params.issues.push({
|
|
331920
|
+
lineItemType: "UsbSeriesResistorsNotAligned",
|
|
331921
|
+
positiveResistorSchematicBox: a,
|
|
331922
|
+
negativeResistorSchematicBox: b,
|
|
331923
|
+
hostSourceComponentId: hostId,
|
|
331924
|
+
positiveSourcePortId: positivePort.source_port_id,
|
|
331925
|
+
negativeSourcePortId: negativePort.source_port_id,
|
|
331926
|
+
signalAxis: positive.axis,
|
|
331927
|
+
message: `Place ${positiveName} (D+) and ${negativeName} (D−) near each other and draw clear traces to their corresponding USB ports. Exact alignment is not required; preserve pin assignments and leave space for labels.`
|
|
331928
|
+
});
|
|
331929
|
+
}
|
|
331930
|
+
seriesResistor(hostPort) {
|
|
331931
|
+
const index = this.index;
|
|
331932
|
+
const hostNet = index.connected(hostPort.source_port_id);
|
|
331933
|
+
if (index.isRail(hostNet))
|
|
331934
|
+
return;
|
|
331935
|
+
const candidates = new Set((index.portsByNet.get(hostNet) ?? []).filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id));
|
|
331936
|
+
if (candidates.size !== 1)
|
|
331937
|
+
return;
|
|
331938
|
+
const id = [...candidates][0];
|
|
331939
|
+
const nets = index.twoTerminalNets(id);
|
|
331940
|
+
const interfaceNet = nets?.find((net) => net !== hostNet);
|
|
331941
|
+
const placement = index.placement(id);
|
|
331942
|
+
if (!interfaceNet || index.isRail(interfaceNet) || !placement)
|
|
331943
|
+
return;
|
|
331944
|
+
if ((index.portsByNet.get(interfaceNet) ?? []).some((port) => port.source_component_id !== id && index.components.get(port.source_component_id)?.ftype === "simple_resistor"))
|
|
331945
|
+
return;
|
|
331946
|
+
const pins = index.portsByComponent.get(id).map((port) => index.port(port));
|
|
331947
|
+
const [first, second] = pins;
|
|
331948
|
+
if (!first || !second)
|
|
331949
|
+
return;
|
|
331950
|
+
const facing = new Set([first.facing_direction, second.facing_direction]);
|
|
331951
|
+
let axis;
|
|
331952
|
+
if (facing.has("left") && facing.has("right") && Math.abs(first.center.y - second.center.y) < 0.01)
|
|
331953
|
+
axis = "horizontal";
|
|
331954
|
+
else if (facing.has("up") && facing.has("down") && Math.abs(first.center.x - second.center.x) < 0.01)
|
|
331955
|
+
axis = "vertical";
|
|
331956
|
+
else
|
|
331957
|
+
return;
|
|
331958
|
+
return { id, placement, hostNet, interfaceNet, axis };
|
|
331959
|
+
}
|
|
331960
|
+
shareInterface(positive, negative, hostId) {
|
|
331961
|
+
const peerIds = (net) => new Set((this.index.portsByNet.get(net) ?? []).map((port) => port.source_component_id).filter((id) => id !== hostId && id !== positive.id && id !== negative.id && (this.index.portsByComponent.get(id)?.length ?? 0) > 2));
|
|
331962
|
+
const positivePeers = peerIds(positive.interfaceNet);
|
|
331963
|
+
return [...peerIds(negative.interfaceNet)].some((id) => positivePeers.has(id));
|
|
331964
|
+
}
|
|
331965
|
+
static issueToString(issue) {
|
|
331966
|
+
const attrs = [];
|
|
331967
|
+
addAttr(attrs, "positiveResistorName", issue.positiveResistorSchematicBox.sourceComponentName);
|
|
331968
|
+
addAttr(attrs, "negativeResistorName", issue.negativeResistorSchematicBox.sourceComponentName);
|
|
331969
|
+
addAttr(attrs, "signalAxis", issue.signalAxis);
|
|
331970
|
+
addAttr(attrs, "message", issue.message);
|
|
331971
|
+
return `<UsbSeriesResistorsNotAligned ${attrs.join(" ")} />`;
|
|
331972
|
+
}
|
|
331973
|
+
}
|
|
331974
|
+
function usbRole(port) {
|
|
331975
|
+
const roles = new Set;
|
|
331976
|
+
for (const hint of [port.name, ...port.port_hints ?? []]) {
|
|
331977
|
+
const name = hint.toUpperCase();
|
|
331978
|
+
if (/^(?:USB_?)?D(?:P|\+|_POS)$/.test(name))
|
|
331979
|
+
roles.add("positive");
|
|
331980
|
+
if (/^(?:USB_?)?D(?:M|N|-|_NEG)$/.test(name))
|
|
331981
|
+
roles.add("negative");
|
|
331982
|
+
}
|
|
331983
|
+
return roles.size === 1 ? [...roles][0] : undefined;
|
|
331984
|
+
}
|
|
331985
|
+
|
|
331256
331986
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts
|
|
331257
|
-
import { BaseSolver as
|
|
331987
|
+
import { BaseSolver as BaseSolver13 } from "@tscircuit/solver-utils";
|
|
331258
331988
|
|
|
331259
331989
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/graphics.ts
|
|
331260
331990
|
import { mergeGraphics as mergeGraphics2 } from "graphics-debug";
|
|
@@ -331289,7 +332019,7 @@ function visualizeCircuitJson(circuitJson) {
|
|
|
331289
332019
|
}
|
|
331290
332020
|
|
|
331291
332021
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts
|
|
331292
|
-
class CapacitorOrientationSolver extends
|
|
332022
|
+
class CapacitorOrientationSolver extends BaseSolver13 {
|
|
331293
332023
|
static EPSILON = 0.01;
|
|
331294
332024
|
static ORIENTATION_MESSAGE = 'Use schOrientation="vertical" on this capacitor to fix the symbol orientation';
|
|
331295
332025
|
ctx;
|
|
@@ -331434,8 +332164,8 @@ class CapacitorOrientationSolver extends BaseSolver7 {
|
|
|
331434
332164
|
}
|
|
331435
332165
|
|
|
331436
332166
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/DecouplingCapacitorGroupingSolver/DecouplingCapacitorGroupingSolver.ts
|
|
331437
|
-
import { BaseSolver as
|
|
331438
|
-
class DecouplingCapacitorGroupingSolver extends
|
|
332167
|
+
import { BaseSolver as BaseSolver14 } from "@tscircuit/solver-utils";
|
|
332168
|
+
class DecouplingCapacitorGroupingSolver extends BaseSolver14 {
|
|
331439
332169
|
params;
|
|
331440
332170
|
static MIN_BODY_GAP = 4;
|
|
331441
332171
|
banks = [];
|
|
@@ -331567,8 +332297,8 @@ function getNetLabelBounds(label) {
|
|
|
331567
332297
|
}
|
|
331568
332298
|
|
|
331569
332299
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/ComponentNetLabelCollisionSolver/ComponentNetLabelCollisionSolver.ts
|
|
331570
|
-
import { BaseSolver as
|
|
331571
|
-
class ComponentNetLabelCollisionSolver extends
|
|
332300
|
+
import { BaseSolver as BaseSolver15 } from "@tscircuit/solver-utils";
|
|
332301
|
+
class ComponentNetLabelCollisionSolver extends BaseSolver15 {
|
|
331572
332302
|
params;
|
|
331573
332303
|
placements;
|
|
331574
332304
|
netLabelsByComponentId;
|
|
@@ -331892,8 +332622,8 @@ class ComponentNetLabelCollisionSolver extends BaseSolver9 {
|
|
|
331892
332622
|
}
|
|
331893
332623
|
|
|
331894
332624
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/ComponentPinAlignmentSolver/ComponentPinAlignmentSolver.ts
|
|
331895
|
-
import { BaseSolver as
|
|
331896
|
-
class ComponentPinAlignmentSolver extends
|
|
332625
|
+
import { BaseSolver as BaseSolver16 } from "@tscircuit/solver-utils";
|
|
332626
|
+
class ComponentPinAlignmentSolver extends BaseSolver16 {
|
|
331897
332627
|
static ALIGNMENT_EPSILON = 0.01;
|
|
331898
332628
|
ctx;
|
|
331899
332629
|
out;
|
|
@@ -332027,8 +332757,8 @@ class ComponentPinAlignmentSolver extends BaseSolver10 {
|
|
|
332027
332757
|
}
|
|
332028
332758
|
|
|
332029
332759
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CrystalLoadCapacitorPlacementSolver/CrystalLoadCapacitorPlacementSolver.ts
|
|
332030
|
-
import { BaseSolver as
|
|
332031
|
-
class CrystalLoadCapacitorPlacementSolver extends
|
|
332760
|
+
import { BaseSolver as BaseSolver17 } from "@tscircuit/solver-utils";
|
|
332761
|
+
class CrystalLoadCapacitorPlacementSolver extends BaseSolver17 {
|
|
332032
332762
|
static ALIGNMENT_TOLERANCE = 0.1;
|
|
332033
332763
|
issues;
|
|
332034
332764
|
networks;
|
|
@@ -332188,9 +332918,9 @@ var distance50 = (first, second) => Math.hypot(first.schX - second.schX, first.s
|
|
|
332188
332918
|
var round2 = (value) => Math.round(value * 100) / 100;
|
|
332189
332919
|
|
|
332190
332920
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/DiodeResistorAlignmentSolver/DiodeResistorAlignmentSolver.ts
|
|
332191
|
-
import { BaseSolver as
|
|
332921
|
+
import { BaseSolver as BaseSolver18 } from "@tscircuit/solver-utils";
|
|
332192
332922
|
import { getSourcePortConnectivityMapFromCircuitJson as getSourcePortConnectivityMapFromCircuitJson2 } from "circuit-json-to-connectivity-map";
|
|
332193
|
-
class DiodeResistorAlignmentSolver extends
|
|
332923
|
+
class DiodeResistorAlignmentSolver extends BaseSolver18 {
|
|
332194
332924
|
static DIODE_FTYPES = new Set(["simple_led", "simple_diode"]);
|
|
332195
332925
|
ctx;
|
|
332196
332926
|
out;
|
|
@@ -332356,8 +333086,8 @@ class DiodeResistorAlignmentSolver extends BaseSolver12 {
|
|
|
332356
333086
|
}
|
|
332357
333087
|
|
|
332358
333088
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/FeedbackNetworkPlacementSolver/FeedbackNetworkPlacementSolver.ts
|
|
332359
|
-
import { BaseSolver as
|
|
332360
|
-
class FeedbackNetworkPlacementSolver extends
|
|
333089
|
+
import { BaseSolver as BaseSolver19 } from "@tscircuit/solver-utils";
|
|
333090
|
+
class FeedbackNetworkPlacementSolver extends BaseSolver19 {
|
|
332361
333091
|
static MIN_BODY_GAP = 4;
|
|
332362
333092
|
index;
|
|
332363
333093
|
amplifierIds;
|
|
@@ -332442,11 +333172,75 @@ function distanceBetweenBoxes(a, b) {
|
|
|
332442
333172
|
}
|
|
332443
333173
|
|
|
332444
333174
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/PullResistorPlacementSolver/PullResistorPlacementSolver.ts
|
|
332445
|
-
import { BaseSolver as
|
|
332446
|
-
|
|
333175
|
+
import { BaseSolver as BaseSolver20 } from "@tscircuit/solver-utils";
|
|
333176
|
+
|
|
333177
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/switch-pull-resistor-pairs.ts
|
|
333178
|
+
function getSwitchPullResistorPairs(index) {
|
|
333179
|
+
const pairs = [];
|
|
333180
|
+
const isHorizontal = (id) => {
|
|
333181
|
+
const ports = index.portsByComponent.get(id);
|
|
333182
|
+
if (ports?.length !== 2)
|
|
333183
|
+
return false;
|
|
333184
|
+
const a = index.port(ports[0]);
|
|
333185
|
+
const b = index.port(ports[1]);
|
|
333186
|
+
return !!a && !!b && Math.abs(a.center.y - b.center.y) < 0.01 && Math.abs(a.center.x - b.center.x) > 0.01;
|
|
333187
|
+
};
|
|
333188
|
+
for (const component of index.components.values()) {
|
|
333189
|
+
if (component.ftype !== "simple_resistor" || component.resistance <= 0)
|
|
333190
|
+
continue;
|
|
333191
|
+
const id = component.source_component_id;
|
|
333192
|
+
const nets = index.twoTerminalNets(id);
|
|
333193
|
+
if (!nets || nets.filter((net) => index.isRail(net)).length !== 1)
|
|
333194
|
+
continue;
|
|
333195
|
+
const rail = nets.find((net) => index.isRail(net));
|
|
333196
|
+
if (index.powerNets.has(rail) && index.groundNets.has(rail))
|
|
333197
|
+
continue;
|
|
333198
|
+
const signal = nets.find((net) => net !== rail);
|
|
333199
|
+
const peers = index.portsByNet.get(signal) ?? [];
|
|
333200
|
+
const switches = peers.filter((port) => {
|
|
333201
|
+
const type = index.components.get(port.source_component_id)?.ftype;
|
|
333202
|
+
return type === "simple_switch" || type === "simple_push_button";
|
|
333203
|
+
});
|
|
333204
|
+
if (switches.length !== 1 || peers.filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").length !== 1)
|
|
333205
|
+
continue;
|
|
333206
|
+
const signalPort = switches[0];
|
|
333207
|
+
const switchId = signalPort.source_component_id;
|
|
333208
|
+
const switchType = index.components.get(switchId)?.ftype;
|
|
333209
|
+
const switchNets = index.twoTerminalNets(switchId);
|
|
333210
|
+
const otherRail = switchNets?.find((net) => net !== signal);
|
|
333211
|
+
if (!otherRail)
|
|
333212
|
+
continue;
|
|
333213
|
+
const pullDirection = index.powerNets.has(rail) ? "up" : "down";
|
|
333214
|
+
if (pullDirection === "up" ? !index.groundNets.has(otherRail) || index.powerNets.has(otherRail) : !index.powerNets.has(otherRail) || index.groundNets.has(otherRail))
|
|
333215
|
+
continue;
|
|
333216
|
+
if ([id, switchId].some((componentId) => index.portsByComponent.get(componentId)?.some((port) => port.do_not_connect)))
|
|
333217
|
+
continue;
|
|
333218
|
+
const resistor = index.placement(id);
|
|
333219
|
+
const switchBox = index.placement(switchId);
|
|
333220
|
+
const pin = index.port(signalPort);
|
|
333221
|
+
if (!resistor || !switchBox || !pin || !index.sameLocalScope(resistor, switchBox))
|
|
333222
|
+
continue;
|
|
333223
|
+
pairs.push({
|
|
333224
|
+
resistor,
|
|
333225
|
+
switchBox,
|
|
333226
|
+
signalPort,
|
|
333227
|
+
signalSchY: pin.center.y,
|
|
333228
|
+
pullDirection,
|
|
333229
|
+
horizontalPushbutton: switchType === "simple_push_button" && isHorizontal(id) && isHorizontal(switchId)
|
|
333230
|
+
});
|
|
333231
|
+
}
|
|
333232
|
+
return pairs;
|
|
333233
|
+
}
|
|
333234
|
+
function getHorizontalPushbuttonComponentIds(index) {
|
|
333235
|
+
return new Set(getSwitchPullResistorPairs(index).flatMap((pair) => pair.horizontalPushbutton ? [pair.resistor.sourceComponentId, pair.switchBox.sourceComponentId] : []));
|
|
333236
|
+
}
|
|
333237
|
+
|
|
333238
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/PullResistorPlacementSolver/PullResistorPlacementSolver.ts
|
|
333239
|
+
class PullResistorPlacementSolver extends BaseSolver20 {
|
|
332447
333240
|
static MIN_WRONG_SIDE_GAP = 1.5;
|
|
332448
333241
|
index;
|
|
332449
333242
|
resistorIds;
|
|
333243
|
+
horizontalPushbuttonComponentIds;
|
|
332450
333244
|
issues;
|
|
332451
333245
|
currentIndex = 0;
|
|
332452
333246
|
constructor({
|
|
@@ -332456,6 +333250,7 @@ class PullResistorPlacementSolver extends BaseSolver14 {
|
|
|
332456
333250
|
super();
|
|
332457
333251
|
this.issues = issues;
|
|
332458
333252
|
this.index = new PlacementNetworkIndex(ctx);
|
|
333253
|
+
this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);
|
|
332459
333254
|
this.resistorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_resistor" && component.resistance > 0).map((component) => component.source_component_id);
|
|
332460
333255
|
this.solved = this.resistorIds.length === 0;
|
|
332461
333256
|
}
|
|
@@ -332464,6 +333259,8 @@ class PullResistorPlacementSolver extends BaseSolver14 {
|
|
|
332464
333259
|
this.solved = this.currentIndex >= this.resistorIds.length;
|
|
332465
333260
|
if (!id)
|
|
332466
333261
|
return;
|
|
333262
|
+
if (this.horizontalPushbuttonComponentIds.has(id))
|
|
333263
|
+
return;
|
|
332467
333264
|
const index = this.index;
|
|
332468
333265
|
const resistor = index.placement(id);
|
|
332469
333266
|
const nets = index.twoTerminalNets(id);
|
|
@@ -332539,14 +333336,15 @@ class PullResistorPlacementSolver extends BaseSolver14 {
|
|
|
332539
333336
|
}
|
|
332540
333337
|
|
|
332541
333338
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/TwoPinComponentRailOrientationSolver/TwoPinComponentRailOrientationSolver.ts
|
|
332542
|
-
import { BaseSolver as
|
|
332543
|
-
class TwoPinComponentRailOrientationSolver extends
|
|
333339
|
+
import { BaseSolver as BaseSolver21 } from "@tscircuit/solver-utils";
|
|
333340
|
+
class TwoPinComponentRailOrientationSolver extends BaseSolver21 {
|
|
332544
333341
|
static EPSILON = 0.01;
|
|
332545
333342
|
index;
|
|
332546
333343
|
powerNets;
|
|
332547
333344
|
groundNets;
|
|
332548
333345
|
positiveVoltageNets = new Set;
|
|
332549
333346
|
componentIds;
|
|
333347
|
+
horizontalPushbuttonComponentIds;
|
|
332550
333348
|
issues;
|
|
332551
333349
|
currentIndex = 0;
|
|
332552
333350
|
constructor({
|
|
@@ -332556,6 +333354,7 @@ class TwoPinComponentRailOrientationSolver extends BaseSolver15 {
|
|
|
332556
333354
|
super();
|
|
332557
333355
|
this.issues = issues;
|
|
332558
333356
|
this.index = new PlacementNetworkIndex(ctx);
|
|
333357
|
+
this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);
|
|
332559
333358
|
this.powerNets = new Set(this.index.powerNets);
|
|
332560
333359
|
this.groundNets = new Set(this.index.groundNets);
|
|
332561
333360
|
for (const element of ctx.circuitJson) {
|
|
@@ -332579,10 +333378,13 @@ class TwoPinComponentRailOrientationSolver extends BaseSolver15 {
|
|
|
332579
333378
|
return;
|
|
332580
333379
|
const index = this.index;
|
|
332581
333380
|
const component = index.placement(id);
|
|
333381
|
+
const sourceComponent = index.components.get(id);
|
|
332582
333382
|
const nets = index.twoTerminalNets(id);
|
|
332583
333383
|
if (!component || !nets)
|
|
332584
333384
|
return;
|
|
332585
|
-
if (
|
|
333385
|
+
if (sourceComponent?.ftype === "simple_inductor" && !nets.some((net) => this.groundNets.has(net)))
|
|
333386
|
+
return;
|
|
333387
|
+
if (sourceComponent?.ftype === "simple_diode" && nets.every((net) => this.powerNets.has(net)))
|
|
332586
333388
|
return;
|
|
332587
333389
|
if (nets.some((net) => this.powerNets.has(net) && this.groundNets.has(net)))
|
|
332588
333390
|
return;
|
|
@@ -332617,6 +333419,8 @@ class TwoPinComponentRailOrientationSolver extends BaseSolver15 {
|
|
|
332617
333419
|
const horizontal = Math.abs(railPort.center.y - otherPort.center.y) <= TwoPinComponentRailOrientationSolver.EPSILON && Math.abs(railPort.center.x - otherPort.center.x) > TwoPinComponentRailOrientationSolver.EPSILON && (railPort.facing_direction === "left" && otherPort.facing_direction === "right" || railPort.facing_direction === "right" && otherPort.facing_direction === "left");
|
|
332618
333420
|
if (!horizontal)
|
|
332619
333421
|
return;
|
|
333422
|
+
if (this.horizontalPushbuttonComponentIds.has(id))
|
|
333423
|
+
return;
|
|
332620
333424
|
const suggestedRailFacingDirection = railType === "power" ? "up" : "down";
|
|
332621
333425
|
const deltaSchRotation = railPort.facing_direction === "left" === (railType === "power") ? -90 : 90;
|
|
332622
333426
|
this.issues.push({
|
|
@@ -332648,8 +333452,8 @@ function getSchematicBoxComponentIds(circuitJson) {
|
|
|
332648
333452
|
}
|
|
332649
333453
|
|
|
332650
333454
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxInnerLabelCollisionSolver/SchematicBoxInnerLabelCollisionSolver.ts
|
|
332651
|
-
import { BaseSolver as
|
|
332652
|
-
class SchematicBoxInnerLabelCollisionSolver extends
|
|
333455
|
+
import { BaseSolver as BaseSolver22 } from "@tscircuit/solver-utils";
|
|
333456
|
+
class SchematicBoxInnerLabelCollisionSolver extends BaseSolver22 {
|
|
332653
333457
|
params;
|
|
332654
333458
|
MESSAGE = "Inner labels are colliding. Increase the schWidth or schHeight.";
|
|
332655
333459
|
PIN_LABEL_EDGE_PADDING = 0.1;
|
|
@@ -332846,8 +333650,8 @@ class SchematicBoxInnerLabelCollisionSolver extends BaseSolver16 {
|
|
|
332846
333650
|
}
|
|
332847
333651
|
|
|
332848
333652
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxOverlapSolver/SchematicBoxOverlapSolver.ts
|
|
332849
|
-
import { BaseSolver as
|
|
332850
|
-
class SchematicBoxOverlapSolver extends
|
|
333653
|
+
import { BaseSolver as BaseSolver23 } from "@tscircuit/solver-utils";
|
|
333654
|
+
class SchematicBoxOverlapSolver extends BaseSolver23 {
|
|
332851
333655
|
params;
|
|
332852
333656
|
placements;
|
|
332853
333657
|
firstIndex = 0;
|
|
@@ -332966,8 +333770,8 @@ class SchematicBoxOverlapSolver extends BaseSolver17 {
|
|
|
332966
333770
|
}
|
|
332967
333771
|
|
|
332968
333772
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxTooWideSolver/SchematicBoxTooWideSolver.ts
|
|
332969
|
-
import { BaseSolver as
|
|
332970
|
-
class SchematicBoxTooWideSolver extends
|
|
333773
|
+
import { BaseSolver as BaseSolver24 } from "@tscircuit/solver-utils";
|
|
333774
|
+
class SchematicBoxTooWideSolver extends BaseSolver24 {
|
|
332971
333775
|
params;
|
|
332972
333776
|
SCHEMATIC_BOX_TOO_WIDE_MESSAGE = "Shrink schematic box width";
|
|
332973
333777
|
PIN_HEADER_MAX_ALLOWED_GAP = 0.1;
|
|
@@ -333147,8 +333951,8 @@ class SchematicBoxTooWideSolver extends BaseSolver18 {
|
|
|
333147
333951
|
}
|
|
333148
333952
|
|
|
333149
333953
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicPinPaddingToEdgeSolver/SchematicPinPaddingToEdgeSolver.ts
|
|
333150
|
-
import { BaseSolver as
|
|
333151
|
-
class SchematicPinPaddingToEdgeSolver extends
|
|
333954
|
+
import { BaseSolver as BaseSolver25 } from "@tscircuit/solver-utils";
|
|
333955
|
+
class SchematicPinPaddingToEdgeSolver extends BaseSolver25 {
|
|
333152
333956
|
params;
|
|
333153
333957
|
MESSAGE = "Move schematic pins closer to the box edge or change the schematic box";
|
|
333154
333958
|
PIN_NAME_CHARACTER_WIDTH = 0.095;
|
|
@@ -333204,7 +334008,7 @@ class SchematicPinPaddingToEdgeSolver extends BaseSolver19 {
|
|
|
333204
334008
|
continue;
|
|
333205
334009
|
const measuredPadding = this.getPinPaddingToEdge(schematicBox, outerPin, edgeSide);
|
|
333206
334010
|
const maxAllowedPadding = useLabelAwareMaxPadding ? this.getMaxAllowedPinPadding(pinSpacing, edgeSide, maxLabelLengthBySide) : pinSpacing;
|
|
333207
|
-
if (!this.exceedsMaxAllowedGap(measuredPadding, maxAllowedPadding))
|
|
334011
|
+
if (!this.exceedsMaxAllowedGap(measuredPadding, maxAllowedPadding + pinSpacing))
|
|
333208
334012
|
continue;
|
|
333209
334013
|
candidates.push({
|
|
333210
334014
|
schematicBox,
|
|
@@ -333527,6 +334331,47 @@ var buildSolverContext = (circuitJson) => {
|
|
|
333527
334331
|
return { circuitJson, componentPlacements };
|
|
333528
334332
|
};
|
|
333529
334333
|
|
|
334334
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SwitchPullResistorPlacementSolver/SwitchPullResistorPlacementSolver.ts
|
|
334335
|
+
import { BaseSolver as BaseSolver26 } from "@tscircuit/solver-utils";
|
|
334336
|
+
class SwitchPullResistorPlacementSolver extends BaseSolver26 {
|
|
334337
|
+
params;
|
|
334338
|
+
constructor(params2) {
|
|
334339
|
+
super();
|
|
334340
|
+
this.params = params2;
|
|
334341
|
+
}
|
|
334342
|
+
_step() {
|
|
334343
|
+
const index = new PlacementNetworkIndex(this.params.ctx);
|
|
334344
|
+
for (const pair of getSwitchPullResistorPairs(index)) {
|
|
334345
|
+
const { resistor, switchBox, signalPort, signalSchY, pullDirection } = pair;
|
|
334346
|
+
if (pair.horizontalPushbutton)
|
|
334347
|
+
continue;
|
|
334348
|
+
const signal = index.connected(signalPort.source_port_id);
|
|
334349
|
+
if (index.portsByNet.get(signal)?.length !== 2)
|
|
334350
|
+
continue;
|
|
334351
|
+
if (signalPort.needs_external_pullup || signalPort.needs_external_pulldown)
|
|
334352
|
+
continue;
|
|
334353
|
+
const wrongSideGap = pullDirection === "up" ? signalSchY - (resistor.schY + resistor.height / 2) : resistor.schY - resistor.height / 2 - signalSchY;
|
|
334354
|
+
if (wrongSideGap <= 1.5)
|
|
334355
|
+
continue;
|
|
334356
|
+
const preferredSide = pullDirection === "up" ? "above" : "below";
|
|
334357
|
+
this.params.issues.push({
|
|
334358
|
+
lineItemType: "PullResistorOnWrongSide",
|
|
334359
|
+
resistorSchematicBox: resistor,
|
|
334360
|
+
hostSchematicBox: switchBox,
|
|
334361
|
+
signalSourcePortId: signalPort.source_port_id,
|
|
334362
|
+
signalPinName: signalPort.name,
|
|
334363
|
+
signalSchY,
|
|
334364
|
+
pullDirection,
|
|
334365
|
+
preferredSide,
|
|
334366
|
+
wrongSideGap,
|
|
334367
|
+
maxRecommendedWrongSideGap: 1.5,
|
|
334368
|
+
message: `place ${resistor.sourceComponentName} ${preferredSide} ${switchBox.sourceComponentName} so the pull-${pullDirection} branch reads toward ${pullDirection === "up" ? "power" : "ground"}`
|
|
334369
|
+
});
|
|
334370
|
+
}
|
|
334371
|
+
this.solved = true;
|
|
334372
|
+
}
|
|
334373
|
+
}
|
|
334374
|
+
|
|
333530
334375
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/trace-name.ts
|
|
333531
334376
|
function getTraceName(circuitJson, trace) {
|
|
333532
334377
|
const sourceTrace = circuitJson.find((e) => e.type === "source_trace" && e.source_trace_id === trace.source_trace_id);
|
|
@@ -333679,8 +334524,8 @@ var polygonBounds = (polygons) => {
|
|
|
333679
334524
|
};
|
|
333680
334525
|
|
|
333681
334526
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/TraceSimplificationSolver/TraceSimplificationSolver.ts
|
|
333682
|
-
import { BaseSolver as
|
|
333683
|
-
class TraceSimplificationSolver extends
|
|
334527
|
+
import { BaseSolver as BaseSolver27 } from "@tscircuit/solver-utils";
|
|
334528
|
+
class TraceSimplificationSolver extends BaseSolver27 {
|
|
333684
334529
|
static EPSILON = 0.01;
|
|
333685
334530
|
ctx;
|
|
333686
334531
|
out;
|
|
@@ -334038,7 +334883,7 @@ class TraceSimplificationSolver extends BaseSolver20 {
|
|
|
334038
334883
|
}
|
|
334039
334884
|
|
|
334040
334885
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/TwoPinComponentOrientationSolver.ts
|
|
334041
|
-
import { BaseSolver as
|
|
334886
|
+
import { BaseSolver as BaseSolver28 } from "@tscircuit/solver-utils";
|
|
334042
334887
|
|
|
334043
334888
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/getPowerOrGroundConnectionIds.ts
|
|
334044
334889
|
import {
|
|
@@ -334077,7 +334922,7 @@ function getPowerOrGroundConnectionIds(circuitJson) {
|
|
|
334077
334922
|
}
|
|
334078
334923
|
|
|
334079
334924
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/TwoPinComponentOrientationSolver.ts
|
|
334080
|
-
class TwoPinComponentOrientationSolver extends
|
|
334925
|
+
class TwoPinComponentOrientationSolver extends BaseSolver28 {
|
|
334081
334926
|
static EPSILON = 0.01;
|
|
334082
334927
|
ctx;
|
|
334083
334928
|
out;
|
|
@@ -334323,8 +335168,8 @@ class TwoPinComponentOrientationSolver extends BaseSolver21 {
|
|
|
334323
335168
|
}
|
|
334324
335169
|
|
|
334325
335170
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/VerboseNetLabelSolver/VerboseNetLabelSolver.ts
|
|
334326
|
-
import { BaseSolver as
|
|
334327
|
-
class VerboseNetLabelSolver extends
|
|
335171
|
+
import { BaseSolver as BaseSolver29 } from "@tscircuit/solver-utils";
|
|
335172
|
+
class VerboseNetLabelSolver extends BaseSolver29 {
|
|
334328
335173
|
params;
|
|
334329
335174
|
VERBOSE_NET_LABEL_MESSAGE = "Create trace with schDisplayLabel";
|
|
334330
335175
|
netLabels;
|
|
@@ -334433,8 +335278,8 @@ class VerboseNetLabelSolver extends BaseSolver22 {
|
|
|
334433
335278
|
}
|
|
334434
335279
|
|
|
334435
335280
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicTextClearanceSolver/SchematicTextClearanceSolver.ts
|
|
334436
|
-
import { BaseSolver as
|
|
334437
|
-
class SchematicTextClearanceSolver extends
|
|
335281
|
+
import { BaseSolver as BaseSolver30 } from "@tscircuit/solver-utils";
|
|
335282
|
+
class SchematicTextClearanceSolver extends BaseSolver30 {
|
|
334438
335283
|
params;
|
|
334439
335284
|
texts;
|
|
334440
335285
|
obstacles;
|
|
@@ -334585,8 +335430,8 @@ class SchematicTextClearanceSolver extends BaseSolver23 {
|
|
|
334585
335430
|
}
|
|
334586
335431
|
|
|
334587
335432
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/ResetNetworkGroupingSolver/ResetNetworkGroupingSolver.ts
|
|
334588
|
-
import { BaseSolver as
|
|
334589
|
-
class ResetNetworkGroupingSolver extends
|
|
335433
|
+
import { BaseSolver as BaseSolver31 } from "@tscircuit/solver-utils";
|
|
335434
|
+
class ResetNetworkGroupingSolver extends BaseSolver31 {
|
|
334590
335435
|
params;
|
|
334591
335436
|
static MIN_DISTANCE = 6;
|
|
334592
335437
|
networks;
|
|
@@ -334740,6 +335585,50 @@ class ResetNetworkGroupingSolver extends BaseSolver24 {
|
|
|
334740
335585
|
var resetPinName = (port) => [port.name, ...port.port_hints ?? []].find((name) => /^N?(RESET|RST)(N|B)?$/.test(name.toUpperCase().replace(/[_\-!~#/]/g, "")));
|
|
334741
335586
|
|
|
334742
335587
|
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicPlacementPipeline/SchematicPlacementPipeline.ts
|
|
335588
|
+
var solversByIssueType = {
|
|
335589
|
+
MosfetGateNetworkNotGrouped: [MosfetGateNetworkPlacementSolver],
|
|
335590
|
+
FlybackDiodeSeparatedFromRelayCoil: [RelayFlybackDiodePlacementSolver],
|
|
335591
|
+
ComponentOverlap: [SchematicBoxOverlapSolver],
|
|
335592
|
+
SchematicBoxHasALotOfSurroundingWhitespace: [],
|
|
335593
|
+
CapacitorSymbolHorizontal: [
|
|
335594
|
+
CapacitorOrientationSolver,
|
|
335595
|
+
TwoPinComponentRailOrientationSolver
|
|
335596
|
+
],
|
|
335597
|
+
VerboseSchematicNetLabel: [VerboseNetLabelSolver],
|
|
335598
|
+
PinHeaderSchematicBoxTooWide: [SchematicBoxTooWideSolver],
|
|
335599
|
+
GenericSchematicBoxTooWide: [SchematicBoxTooWideSolver],
|
|
335600
|
+
SchematicBoxInnerLabelCollision: [SchematicBoxInnerLabelCollisionSolver],
|
|
335601
|
+
SchematicPinPaddingToEdgeTooLarge: [SchematicPinPaddingToEdgeSolver],
|
|
335602
|
+
DiodeResistorNotAligned: [DiodeResistorAlignmentSolver],
|
|
335603
|
+
ComponentPinsWouldAlignWithVerticalShift: [ComponentPinAlignmentSolver],
|
|
335604
|
+
TraceCanBeSimplifiedByMovingComponent: [TraceSimplificationSolver],
|
|
335605
|
+
CrystalNotCenteredOverLoadCapacitors: [CrystalLoadCapacitorPlacementSolver],
|
|
335606
|
+
ComponentNetLabelCollision: [ComponentNetLabelCollisionSolver],
|
|
335607
|
+
ComponentBoxNetLabelCollision: [ComponentNetLabelCollisionSolver],
|
|
335608
|
+
NetLabelCollision: [ComponentNetLabelCollisionSolver],
|
|
335609
|
+
FeedbackNetworkNotCompact: [FeedbackNetworkPlacementSolver],
|
|
335610
|
+
PullResistorOnWrongSide: [
|
|
335611
|
+
PullResistorPlacementSolver,
|
|
335612
|
+
SwitchPullResistorPlacementSolver
|
|
335613
|
+
],
|
|
335614
|
+
SchematicTextCollision: [SchematicTextClearanceSolver],
|
|
335615
|
+
ResetNetworkNotGrouped: [ResetNetworkGroupingSolver],
|
|
335616
|
+
TwoPinComponentCouldBeFlipped: [TwoPinComponentOrientationSolver],
|
|
335617
|
+
TwoPinComponentShouldBeVertical: [TwoPinComponentRailOrientationSolver],
|
|
335618
|
+
TwoPinComponentHasInvertedRails: [TwoPinComponentRailOrientationSolver],
|
|
335619
|
+
DecouplingCapacitorsNotCloseTogether: [DecouplingCapacitorGroupingSolver],
|
|
335620
|
+
ConnectorPositionCausesTraceDetours: [ConnectorPlacementSolver],
|
|
335621
|
+
LowSideTransistorNotAlignedWithLoad: [LowSideTransistorPlacementSolver],
|
|
335622
|
+
UsbSeriesResistorsNotAligned: [UsbSeriesResistorPlacementSolver],
|
|
335623
|
+
CurrentSenseShuntSeparatedFromInputs: [CurrentSenseShuntPlacementSolver],
|
|
335624
|
+
VoltageDividerSupplyResistorBelowGroundResistor: [
|
|
335625
|
+
VoltageDividerPlacementSolver
|
|
335626
|
+
],
|
|
335627
|
+
RegulatorCapacitorsOnWrongSides: [
|
|
335628
|
+
RegulatorInputOutputCapacitorPlacementSolver
|
|
335629
|
+
]
|
|
335630
|
+
};
|
|
335631
|
+
|
|
334743
335632
|
class SchematicPlacementPipeline extends BasePipelineSolver2 {
|
|
334744
335633
|
ctx;
|
|
334745
335634
|
issues = [];
|
|
@@ -334792,6 +335681,9 @@ class SchematicPlacementPipeline extends BasePipelineSolver2 {
|
|
|
334792
335681
|
definePipelineStep3("PullResistorPlacementSolver", PullResistorPlacementSolver, (p) => [
|
|
334793
335682
|
{ ctx: p.ctx, issues: p.issues }
|
|
334794
335683
|
]),
|
|
335684
|
+
definePipelineStep3("SwitchPullResistorPlacementSolver", SwitchPullResistorPlacementSolver, (p) => [
|
|
335685
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335686
|
+
]),
|
|
334795
335687
|
definePipelineStep3("ComponentNetLabelCollisionSolver", ComponentNetLabelCollisionSolver, (p) => [
|
|
334796
335688
|
{ ctx: p.ctx, issues: p.issues }
|
|
334797
335689
|
]),
|
|
@@ -334803,15 +335695,42 @@ class SchematicPlacementPipeline extends BasePipelineSolver2 {
|
|
|
334803
335695
|
]),
|
|
334804
335696
|
definePipelineStep3("LowSideTransistorPlacementSolver", LowSideTransistorPlacementSolver, (p) => [
|
|
334805
335697
|
{ ctx: p.ctx, issues: p.issues }
|
|
335698
|
+
]),
|
|
335699
|
+
definePipelineStep3("UsbSeriesResistorPlacementSolver", UsbSeriesResistorPlacementSolver, (p) => [
|
|
335700
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335701
|
+
]),
|
|
335702
|
+
definePipelineStep3("RegulatorInputOutputCapacitorPlacementSolver", RegulatorInputOutputCapacitorPlacementSolver, (p) => [
|
|
335703
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335704
|
+
]),
|
|
335705
|
+
definePipelineStep3("VoltageDividerPlacementSolver", VoltageDividerPlacementSolver, (p) => [
|
|
335706
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335707
|
+
]),
|
|
335708
|
+
definePipelineStep3("CurrentSenseShuntPlacementSolver", CurrentSenseShuntPlacementSolver, (p) => [
|
|
335709
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335710
|
+
]),
|
|
335711
|
+
definePipelineStep3("RelayFlybackDiodePlacementSolver", RelayFlybackDiodePlacementSolver, (p) => [
|
|
335712
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
335713
|
+
]),
|
|
335714
|
+
definePipelineStep3("MosfetGateNetworkPlacementSolver", MosfetGateNetworkPlacementSolver, (p) => [
|
|
335715
|
+
{ ctx: p.ctx, issues: p.issues }
|
|
334806
335716
|
])
|
|
334807
335717
|
];
|
|
335718
|
+
selectedIssueTypes;
|
|
335719
|
+
constructor(circuitJson, options = {}) {
|
|
335720
|
+
super(circuitJson);
|
|
335721
|
+
if (options.issueTypes !== undefined) {
|
|
335722
|
+
this.selectedIssueTypes = new Set(options.issueTypes);
|
|
335723
|
+
const selectedSolvers = new Set(options.issueTypes.flatMap((type) => solversByIssueType[type]));
|
|
335724
|
+
this.pipelineDef = this.pipelineDef.filter((step) => selectedSolvers.has(step.solverClass));
|
|
335725
|
+
}
|
|
335726
|
+
}
|
|
334808
335727
|
_setup() {
|
|
334809
335728
|
this.ctx = buildSolverContext(this.inputProblem);
|
|
334810
335729
|
}
|
|
334811
335730
|
getOutput() {
|
|
334812
335731
|
const railOrientationComponentIds = new Set(this.issues.flatMap((issue) => issue.lineItemType === "TwoPinComponentShouldBeVertical" && issue.schematicBox.schematicComponentId ? [issue.schematicBox.schematicComponentId] : []));
|
|
334813
335732
|
return {
|
|
334814
|
-
issues: this.issues.filter((issue) => issue.lineItemType !== "CapacitorSymbolHorizontal" || !railOrientationComponentIds.has(issue.schematicBox.schematicComponentId ?? "")),
|
|
335733
|
+
issues: this.issues.filter((issue) => issue.lineItemType !== "CapacitorSymbolHorizontal" || !railOrientationComponentIds.has(issue.schematicBox.schematicComponentId ?? "")).filter((issue) => this.selectedIssueTypes === undefined || this.selectedIssueTypes.has(issue.lineItemType)),
|
|
334815
335734
|
componentPlacements: this.ctx.componentPlacements
|
|
334816
335735
|
};
|
|
334817
335736
|
}
|
|
@@ -334854,6 +335773,32 @@ var getRelevantPlacementsForIssues = ({
|
|
|
334854
335773
|
};
|
|
334855
335774
|
for (const issue of issues) {
|
|
334856
335775
|
switch (issue.lineItemType) {
|
|
335776
|
+
case "MosfetGateNetworkNotGrouped":
|
|
335777
|
+
addPlacement(issue.mosfetSchematicBox);
|
|
335778
|
+
addPlacement(issue.seriesGateResistorSchematicBox);
|
|
335779
|
+
addPlacement(issue.gateSourceResistorSchematicBox);
|
|
335780
|
+
break;
|
|
335781
|
+
case "FlybackDiodeSeparatedFromRelayCoil":
|
|
335782
|
+
addPlacement(issue.relaySchematicBox);
|
|
335783
|
+
addPlacement(issue.diodeSchematicBox);
|
|
335784
|
+
break;
|
|
335785
|
+
case "CurrentSenseShuntSeparatedFromInputs":
|
|
335786
|
+
addPlacement(issue.amplifierSchematicBox);
|
|
335787
|
+
addPlacement(issue.shuntSchematicBox);
|
|
335788
|
+
break;
|
|
335789
|
+
case "VoltageDividerSupplyResistorBelowGroundResistor":
|
|
335790
|
+
addPlacement(issue.supplyResistorSchematicBox);
|
|
335791
|
+
addPlacement(issue.groundResistorSchematicBox);
|
|
335792
|
+
break;
|
|
335793
|
+
case "RegulatorCapacitorsOnWrongSides":
|
|
335794
|
+
addPlacement(issue.regulatorSchematicBox);
|
|
335795
|
+
addPlacement(issue.inputCapacitorSchematicBox);
|
|
335796
|
+
addPlacement(issue.outputCapacitorSchematicBox);
|
|
335797
|
+
break;
|
|
335798
|
+
case "UsbSeriesResistorsNotAligned":
|
|
335799
|
+
addPlacement(issue.positiveResistorSchematicBox);
|
|
335800
|
+
addPlacement(issue.negativeResistorSchematicBox);
|
|
335801
|
+
break;
|
|
334857
335802
|
case "LowSideTransistorNotAlignedWithLoad":
|
|
334858
335803
|
addPlacement(issue.transistorSchematicBox);
|
|
334859
335804
|
addPlacement(issue.loadSchematicBox);
|
|
@@ -335027,6 +335972,7 @@ class SchematicPlacementAnalysis {
|
|
|
335027
335972
|
}
|
|
335028
335973
|
getIssueCounts(filter = {}) {
|
|
335029
335974
|
const counts = {
|
|
335975
|
+
FlybackDiodeSeparatedFromRelayCoil: 0,
|
|
335030
335976
|
ComponentOverlap: 0,
|
|
335031
335977
|
SchematicBoxHasALotOfSurroundingWhitespace: 0,
|
|
335032
335978
|
CapacitorSymbolHorizontal: 0,
|
|
@@ -335051,7 +335997,12 @@ class SchematicPlacementAnalysis {
|
|
|
335051
335997
|
TwoPinComponentHasInvertedRails: 0,
|
|
335052
335998
|
DecouplingCapacitorsNotCloseTogether: 0,
|
|
335053
335999
|
ConnectorPositionCausesTraceDetours: 0,
|
|
335054
|
-
LowSideTransistorNotAlignedWithLoad: 0
|
|
336000
|
+
LowSideTransistorNotAlignedWithLoad: 0,
|
|
336001
|
+
UsbSeriesResistorsNotAligned: 0,
|
|
336002
|
+
RegulatorCapacitorsOnWrongSides: 0,
|
|
336003
|
+
VoltageDividerSupplyResistorBelowGroundResistor: 0,
|
|
336004
|
+
CurrentSenseShuntSeparatedFromInputs: 0,
|
|
336005
|
+
MosfetGateNetworkNotGrouped: 0
|
|
335055
336006
|
};
|
|
335056
336007
|
for (const issue of this.getIssues(filter))
|
|
335057
336008
|
counts[issue.lineItemType]++;
|
|
@@ -335072,6 +336023,10 @@ class SchematicPlacementAnalysis {
|
|
|
335072
336023
|
}
|
|
335073
336024
|
schematicIssuesToString(issue) {
|
|
335074
336025
|
switch (issue.lineItemType) {
|
|
336026
|
+
case "MosfetGateNetworkNotGrouped":
|
|
336027
|
+
return MosfetGateNetworkPlacementSolver.issueToString(issue);
|
|
336028
|
+
case "CurrentSenseShuntSeparatedFromInputs":
|
|
336029
|
+
return CurrentSenseShuntPlacementSolver.issueToString(issue);
|
|
335075
336030
|
case "ComponentOverlap":
|
|
335076
336031
|
return SchematicBoxOverlapSolver.issueToString(issue);
|
|
335077
336032
|
case "CapacitorSymbolHorizontal":
|
|
@@ -335114,6 +336069,14 @@ class SchematicPlacementAnalysis {
|
|
|
335114
336069
|
return ConnectorPlacementSolver.issueToString(issue);
|
|
335115
336070
|
case "LowSideTransistorNotAlignedWithLoad":
|
|
335116
336071
|
return LowSideTransistorPlacementSolver.issueToString(issue);
|
|
336072
|
+
case "FlybackDiodeSeparatedFromRelayCoil":
|
|
336073
|
+
return RelayFlybackDiodePlacementSolver.issueToString(issue);
|
|
336074
|
+
case "VoltageDividerSupplyResistorBelowGroundResistor":
|
|
336075
|
+
return VoltageDividerPlacementSolver.issueToString(issue);
|
|
336076
|
+
case "RegulatorCapacitorsOnWrongSides":
|
|
336077
|
+
return RegulatorInputOutputCapacitorPlacementSolver.issueToString(issue);
|
|
336078
|
+
case "UsbSeriesResistorsNotAligned":
|
|
336079
|
+
return UsbSeriesResistorPlacementSolver.issueToString(issue);
|
|
335117
336080
|
default:
|
|
335118
336081
|
return "";
|
|
335119
336082
|
}
|
|
@@ -335171,8 +336134,8 @@ class SchematicPlacementAnalysis {
|
|
|
335171
336134
|
];
|
|
335172
336135
|
}
|
|
335173
336136
|
}
|
|
335174
|
-
var analyzeSchematicPlacement = (circuitJson) => {
|
|
335175
|
-
const pipeline = new SchematicPlacementPipeline(circuitJson);
|
|
336137
|
+
var analyzeSchematicPlacement = (circuitJson, options = {}) => {
|
|
336138
|
+
const pipeline = new SchematicPlacementPipeline(circuitJson, options);
|
|
335176
336139
|
pipeline.solve();
|
|
335177
336140
|
const { issues, componentPlacements } = pipeline.getOutput();
|
|
335178
336141
|
const relevantPlacements = getRelevantPlacementsForIssues({
|