circuitscript 0.1.15 → 0.1.17
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/cjs/BaseVisitor.js +98 -35
- package/dist/cjs/antlr/CircuitScriptLexer.js +3 -3
- package/dist/cjs/antlr/CircuitScriptParser.js +868 -757
- package/dist/cjs/builtinMethods.js +11 -1
- package/dist/cjs/draw_symbols.js +18 -17
- package/dist/cjs/execute.js +58 -31
- package/dist/cjs/globals.js +4 -1
- package/dist/cjs/graph.js +372 -0
- package/dist/cjs/helpers.js +6 -2
- package/dist/cjs/layout.js +18 -259
- package/dist/cjs/objects/ClassComponent.js +27 -20
- package/dist/cjs/objects/ExecutionScope.js +7 -2
- package/dist/cjs/objects/Net.js +1 -1
- package/dist/cjs/objects/PinDefinition.js +55 -3
- package/dist/cjs/objects/types.js +42 -6
- package/dist/cjs/visitor.js +88 -48
- package/dist/esm/BaseVisitor.js +98 -35
- package/dist/esm/antlr/CircuitScriptLexer.js +3 -3
- package/dist/esm/antlr/CircuitScriptParser.js +864 -755
- package/dist/esm/antlr/CircuitScriptVisitor.js +2 -0
- package/dist/esm/builtinMethods.js +11 -1
- package/dist/esm/draw_symbols.js +18 -17
- package/dist/esm/execute.js +60 -33
- package/dist/esm/globals.js +3 -0
- package/dist/esm/graph.js +344 -0
- package/dist/esm/helpers.js +6 -2
- package/dist/esm/layout.js +14 -235
- package/dist/esm/objects/ClassComponent.js +28 -21
- package/dist/esm/objects/ExecutionScope.js +7 -2
- package/dist/esm/objects/Net.js +1 -1
- package/dist/esm/objects/PinDefinition.js +53 -2
- package/dist/esm/objects/types.js +42 -6
- package/dist/esm/visitor.js +90 -50
- package/dist/libs/std.cst +3 -2
- package/dist/types/BaseVisitor.d.ts +5 -2
- package/dist/types/antlr/CircuitScriptParser.d.ts +42 -26
- package/dist/types/antlr/CircuitScriptVisitor.d.ts +4 -0
- package/dist/types/draw_symbols.d.ts +13 -7
- package/dist/types/execute.d.ts +12 -12
- package/dist/types/globals.d.ts +4 -1
- package/dist/types/graph.d.ts +29 -0
- package/dist/types/layout.d.ts +4 -9
- package/dist/types/objects/ClassComponent.d.ts +8 -8
- package/dist/types/objects/ExecutionScope.d.ts +8 -7
- package/dist/types/objects/Net.d.ts +2 -2
- package/dist/types/objects/PinDefinition.d.ts +17 -2
- package/dist/types/objects/types.d.ts +31 -7
- package/libs/std.cst +3 -2
- package/package.json +2 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { Graph } from "@dagrejs/graphlib";
|
|
2
|
+
import { SymbolDrawing, SymbolPlaceholder, SymbolCustomModule, SymbolCustom } from "./draw_symbols.js";
|
|
3
|
+
import { ComponentTypes } from "./globals.js";
|
|
4
|
+
import { milsToMM } from "./helpers.js";
|
|
5
|
+
import { RenderFrame, RenderComponent, applyComponentParamsToSymbol, RenderWire } from "./layout.js";
|
|
6
|
+
import { SequenceAction, FrameAction } from "./objects/ExecutionScope.js";
|
|
7
|
+
import { Frame, FixedFrameIds, FrameParamKeys } from "./objects/Frame.js";
|
|
8
|
+
import { numeric } from "./objects/ParamDefinition.js";
|
|
9
|
+
import { NetTypes, TypeProps } from "./objects/types.js";
|
|
10
|
+
import Matrix, { solve } from "ml-matrix";
|
|
11
|
+
import { getPinDefinition } from "./objects/PinDefinition.js";
|
|
12
|
+
export class NetGraph {
|
|
13
|
+
logger;
|
|
14
|
+
constructor(logger) {
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
}
|
|
17
|
+
generateLayoutGraph(sequence, nets) {
|
|
18
|
+
this.print('===== creating graph and populating with nodes =====');
|
|
19
|
+
let previousNode = null;
|
|
20
|
+
let previousPin = null;
|
|
21
|
+
const graph = new Graph({
|
|
22
|
+
directed: true,
|
|
23
|
+
compound: true,
|
|
24
|
+
});
|
|
25
|
+
this.print('sequence length:', sequence.length);
|
|
26
|
+
const baseFrame = new RenderFrame(new Frame(FixedFrameIds.BaseFrame));
|
|
27
|
+
const frameStack = [baseFrame];
|
|
28
|
+
const containerFrames = [baseFrame];
|
|
29
|
+
sequence.forEach((sequenceStep, index) => {
|
|
30
|
+
const action = sequenceStep[0];
|
|
31
|
+
let tmpComponent;
|
|
32
|
+
switch (action) {
|
|
33
|
+
case SequenceAction.To:
|
|
34
|
+
case SequenceAction.At: {
|
|
35
|
+
this.print(...sequenceStep);
|
|
36
|
+
const [, component, pin] = sequenceStep;
|
|
37
|
+
const tmpInstanceName = component.instanceName;
|
|
38
|
+
if (!graph.hasNode(tmpInstanceName)) {
|
|
39
|
+
this.print('create instance', tmpInstanceName);
|
|
40
|
+
const { displayProp = null } = component;
|
|
41
|
+
let tmpSymbol;
|
|
42
|
+
if (displayProp instanceof SymbolDrawing) {
|
|
43
|
+
tmpSymbol = new SymbolPlaceholder(displayProp);
|
|
44
|
+
tmpSymbol.drawing.logger = this.logger;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const symbolPinDefinitions = generateLayoutPinDefinition(component);
|
|
48
|
+
if (component.typeProp === ComponentTypes.module) {
|
|
49
|
+
tmpSymbol = new SymbolCustomModule(symbolPinDefinitions, component.pinsMaxPositions);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
applyComponentParamsToSymbol(component, tmpSymbol);
|
|
56
|
+
tmpSymbol.refreshDrawing();
|
|
57
|
+
const { width: useWidth, height: useHeight } = tmpSymbol.size();
|
|
58
|
+
tmpComponent = new RenderComponent(component, useWidth, useHeight);
|
|
59
|
+
tmpComponent.symbol = tmpSymbol;
|
|
60
|
+
graph.setNode(tmpInstanceName, [RenderItemType.Component, tmpComponent, index]);
|
|
61
|
+
const currentFrame = frameStack[frameStack.length - 1];
|
|
62
|
+
currentFrame && currentFrame.innerItems.push(tmpComponent);
|
|
63
|
+
}
|
|
64
|
+
if (action === SequenceAction.To && previousNode && previousPin) {
|
|
65
|
+
this.setGraphEdge(graph, previousNode, tmpInstanceName, makeEdgeValue(previousNode, previousPin, tmpInstanceName, pin, index));
|
|
66
|
+
}
|
|
67
|
+
previousNode = tmpInstanceName;
|
|
68
|
+
previousPin = pin;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case SequenceAction.Wire: {
|
|
72
|
+
const [, wireId, wireSegments] = sequenceStep;
|
|
73
|
+
let useNet;
|
|
74
|
+
if (previousNode !== null) {
|
|
75
|
+
const [prevNodeType, prevNodeItem] = graph.node(previousNode);
|
|
76
|
+
if (prevNodeType === RenderItemType.Component) {
|
|
77
|
+
const matchingItem = nets.find(([comp, pin]) => {
|
|
78
|
+
return comp.instanceName === previousNode
|
|
79
|
+
&& pin.equals(previousPin);
|
|
80
|
+
});
|
|
81
|
+
if (matchingItem !== undefined) {
|
|
82
|
+
useNet = matchingItem[2];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (prevNodeType === RenderItemType.Wire) {
|
|
86
|
+
useNet = prevNodeItem.net;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const wire = new RenderWire(useNet, numeric(0), numeric(0), wireSegments);
|
|
90
|
+
wire.id = wireId;
|
|
91
|
+
wire.netName = useNet.toString();
|
|
92
|
+
const wireName = getWireName(wire.id);
|
|
93
|
+
graph.setNode(wireName, [RenderItemType.Wire, wire, index]);
|
|
94
|
+
this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, 0, index));
|
|
95
|
+
previousNode = wireName;
|
|
96
|
+
previousPin = 1;
|
|
97
|
+
const wireSegmentsInfo = wireSegments.map(item => {
|
|
98
|
+
const tmp = {
|
|
99
|
+
direction: item.direction,
|
|
100
|
+
value: item.value,
|
|
101
|
+
};
|
|
102
|
+
if (item.valueXY) {
|
|
103
|
+
tmp.valueXY = item.valueXY;
|
|
104
|
+
}
|
|
105
|
+
if (item.until) {
|
|
106
|
+
tmp.until = [item.until[0].toString(), item.until[1]];
|
|
107
|
+
}
|
|
108
|
+
return tmp;
|
|
109
|
+
});
|
|
110
|
+
this.print(SequenceAction.Wire, wireId, JSON.stringify(wireSegmentsInfo));
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case SequenceAction.WireJump: {
|
|
114
|
+
this.print(...sequenceStep);
|
|
115
|
+
const wireId = sequenceStep[1];
|
|
116
|
+
const wireName = getWireName(wireId);
|
|
117
|
+
let wirePin = 1;
|
|
118
|
+
if (sequenceStep.length === 3) {
|
|
119
|
+
wirePin = sequenceStep[2];
|
|
120
|
+
}
|
|
121
|
+
previousNode = wireName;
|
|
122
|
+
previousPin = wirePin;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case SequenceAction.Frame: {
|
|
126
|
+
const [, frameObject, frameAction] = sequenceStep;
|
|
127
|
+
if (frameAction === FrameAction.Enter) {
|
|
128
|
+
const prevFrame = frameStack[frameStack.length - 1];
|
|
129
|
+
const newFrame = new RenderFrame(frameObject);
|
|
130
|
+
if (frameObject.parameters.has(FrameParamKeys.Direction)) {
|
|
131
|
+
newFrame.direction =
|
|
132
|
+
frameObject.parameters.get(FrameParamKeys.Direction);
|
|
133
|
+
}
|
|
134
|
+
if (frameObject.parameters.has(FrameParamKeys.Padding)) {
|
|
135
|
+
newFrame.padding = milsToMM(frameObject.parameters.get(FrameParamKeys.Padding));
|
|
136
|
+
}
|
|
137
|
+
if (frameObject.parameters.has(FrameParamKeys.Border)) {
|
|
138
|
+
newFrame.borderWidth =
|
|
139
|
+
frameObject.parameters.get(FrameParamKeys.Border);
|
|
140
|
+
}
|
|
141
|
+
if (frameObject.parameters.has(FrameParamKeys.Width)) {
|
|
142
|
+
newFrame.width = milsToMM(frameObject.parameters.get(FrameParamKeys.Width));
|
|
143
|
+
}
|
|
144
|
+
if (frameObject.parameters.has(FrameParamKeys.Height)) {
|
|
145
|
+
newFrame.height = milsToMM(frameObject.parameters.get(FrameParamKeys.Height));
|
|
146
|
+
}
|
|
147
|
+
containerFrames.push(newFrame);
|
|
148
|
+
frameStack.push(newFrame);
|
|
149
|
+
prevFrame && prevFrame.innerItems.push(newFrame);
|
|
150
|
+
}
|
|
151
|
+
else if (frameAction === FrameAction.Exit) {
|
|
152
|
+
frameStack.pop();
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
this.print('===== done populating graph =====');
|
|
159
|
+
this.print('');
|
|
160
|
+
const logNodesAndEdges = true;
|
|
161
|
+
if (logNodesAndEdges) {
|
|
162
|
+
this.print('===== graph edges =====');
|
|
163
|
+
const allEdges = graph.edges();
|
|
164
|
+
allEdges.forEach(edge => {
|
|
165
|
+
const [nodeId1, pin1, nodeId2, pin2] = graph.edge(edge);
|
|
166
|
+
this.print(nodeId1, 'pin', pin1, '-----', nodeId2, 'pin', pin2);
|
|
167
|
+
});
|
|
168
|
+
this.print('===== end edges =====');
|
|
169
|
+
this.print();
|
|
170
|
+
this.print('===== graph nodes =====');
|
|
171
|
+
const nodes = graph.nodes();
|
|
172
|
+
nodes.forEach(node => {
|
|
173
|
+
this.print(`name:${node}, value:${graph.node(node)}`);
|
|
174
|
+
});
|
|
175
|
+
this.print('===== end nodes =====');
|
|
176
|
+
this.print('');
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
graph,
|
|
180
|
+
containerFrames,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
setGraphEdge(graph, node1, node2, edgeValue) {
|
|
184
|
+
if (!graph.isDirected && graph.hasEdge(node1, node2)) {
|
|
185
|
+
this.print(`Warning: edge already exists ${node1} ${node2}`);
|
|
186
|
+
}
|
|
187
|
+
graph.setEdge(node1, node2, edgeValue);
|
|
188
|
+
this.print(`created edge: node1:${node1} node2:${node2} edgeValue:${edgeValue}`);
|
|
189
|
+
}
|
|
190
|
+
print(...params) {
|
|
191
|
+
this.logger.add(params.join(' '));
|
|
192
|
+
}
|
|
193
|
+
generateNetGraph(nets) {
|
|
194
|
+
const uniqueNets = new Set(nets.map(([, , net]) => net));
|
|
195
|
+
const components = new Set(nets.map(([component, ,]) => component));
|
|
196
|
+
const tmpNets = Array.from(uniqueNets);
|
|
197
|
+
const gndNet = tmpNets.find(item => {
|
|
198
|
+
return item.toString() === '/GND';
|
|
199
|
+
});
|
|
200
|
+
const otherNets = tmpNets.filter(item => {
|
|
201
|
+
return item !== gndNet;
|
|
202
|
+
});
|
|
203
|
+
const netsIndexed = [];
|
|
204
|
+
if (gndNet) {
|
|
205
|
+
netsIndexed.push(gndNet);
|
|
206
|
+
}
|
|
207
|
+
netsIndexed.push(...otherNets);
|
|
208
|
+
const netsLength = netsIndexed.length;
|
|
209
|
+
const conductanceMatrix = Matrix.zeros(netsLength, netsLength);
|
|
210
|
+
components.forEach(item => {
|
|
211
|
+
if (item.typeProp === TypeProps.Resistor) {
|
|
212
|
+
const net1 = item.pinNets.get(1);
|
|
213
|
+
const net2 = item.pinNets.get(2);
|
|
214
|
+
const net1Index = netsIndexed.indexOf(net1);
|
|
215
|
+
const net2Index = netsIndexed.indexOf(net2);
|
|
216
|
+
const resistance = item.parameters.get('value');
|
|
217
|
+
const resistanceValue = resistance.toNumber();
|
|
218
|
+
const conductanceValue = 1 / resistanceValue;
|
|
219
|
+
const currentValue1 = conductanceMatrix.get(net1Index, net1Index);
|
|
220
|
+
const currentValue2 = conductanceMatrix.get(net2Index, net2Index);
|
|
221
|
+
const currentValue3 = conductanceMatrix.get(net1Index, net2Index);
|
|
222
|
+
const currentValue4 = conductanceMatrix.get(net2Index, net1Index);
|
|
223
|
+
conductanceMatrix.set(net1Index, net1Index, currentValue1 + conductanceValue);
|
|
224
|
+
conductanceMatrix.set(net2Index, net2Index, currentValue2 + conductanceValue);
|
|
225
|
+
conductanceMatrix.set(net1Index, net2Index, currentValue3 - conductanceValue);
|
|
226
|
+
conductanceMatrix.set(net2Index, net1Index, currentValue4 - conductanceValue);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
if (gndNet) {
|
|
230
|
+
conductanceMatrix.removeColumn(0);
|
|
231
|
+
conductanceMatrix.removeRow(0);
|
|
232
|
+
}
|
|
233
|
+
const netsWithoutGnd = netsIndexed.filter(net => {
|
|
234
|
+
return (net !== gndNet);
|
|
235
|
+
});
|
|
236
|
+
const netResistances = new Map();
|
|
237
|
+
try {
|
|
238
|
+
netsWithoutGnd.forEach((net, index) => {
|
|
239
|
+
if (net.type === NetTypes.Source) {
|
|
240
|
+
const currentVector = Matrix.zeros(netsWithoutGnd.length, 1);
|
|
241
|
+
currentVector.set(index, 0, 1);
|
|
242
|
+
const solution = solve(conductanceMatrix, currentVector);
|
|
243
|
+
for (let i = 0; i < solution.rows; i++) {
|
|
244
|
+
const resValue = solution.get(i, 0);
|
|
245
|
+
if (resValue > 0) {
|
|
246
|
+
const targetNet = netsIndexed[i];
|
|
247
|
+
netResistances.set(targetNet, resValue);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
nets,
|
|
257
|
+
netResistances,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
findNodePaths(graph, startNode, endNode, seenNodes = []) {
|
|
261
|
+
const edges = graph.nodeEdges(startNode);
|
|
262
|
+
const paths = [];
|
|
263
|
+
for (let i = 0; i < edges.length; i++) {
|
|
264
|
+
const edge = edges[i];
|
|
265
|
+
const node1 = edge.v;
|
|
266
|
+
const node2 = edge.w;
|
|
267
|
+
let nextNode = "";
|
|
268
|
+
if (node1 === startNode) {
|
|
269
|
+
nextNode = node2;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
nextNode = node1;
|
|
273
|
+
}
|
|
274
|
+
if (nextNode === endNode) {
|
|
275
|
+
paths.push([startNode, endNode]);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
else if (seenNodes.indexOf(nextNode) !== -1) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
seenNodes.push(startNode);
|
|
282
|
+
const routes = this.findNodePaths(graph, nextNode, endNode, seenNodes);
|
|
283
|
+
for (let j = 0; j < routes.length; j++) {
|
|
284
|
+
paths.push([startNode, ...routes[j]]);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return paths;
|
|
288
|
+
}
|
|
289
|
+
getNetNodeName(net) {
|
|
290
|
+
return 'net:' + net.toString();
|
|
291
|
+
}
|
|
292
|
+
getComponentName(component) {
|
|
293
|
+
return 'component:' + component.instanceName;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function makeEdgeValue(instanceName1, instancePin1, instanceName2, instancePin2, priority) {
|
|
297
|
+
return [instanceName1, instancePin1, instanceName2, instancePin2, priority];
|
|
298
|
+
}
|
|
299
|
+
export function getWireName(wireId) {
|
|
300
|
+
return 'wire:' + wireId;
|
|
301
|
+
}
|
|
302
|
+
export function generateLayoutPinDefinition(component) {
|
|
303
|
+
const pins = component.pins;
|
|
304
|
+
const symbolPinDefinitions = [];
|
|
305
|
+
const existingPinIds = Array.from(pins.keys());
|
|
306
|
+
const arrangeProps = component.arrangeProps ?? [];
|
|
307
|
+
const addedPins = [];
|
|
308
|
+
for (const [key, items] of arrangeProps) {
|
|
309
|
+
let useItems;
|
|
310
|
+
if (!Array.isArray(items)) {
|
|
311
|
+
useItems = [items];
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
useItems = [...items];
|
|
315
|
+
}
|
|
316
|
+
useItems.forEach(pinId => {
|
|
317
|
+
const existingPin = existingPinIds.find(pin => pin.equals(pinId));
|
|
318
|
+
if (existingPin) {
|
|
319
|
+
const pin = getPinDefinition(pins, existingPin);
|
|
320
|
+
symbolPinDefinitions.push({
|
|
321
|
+
side: key,
|
|
322
|
+
pinId: pinId,
|
|
323
|
+
text: pin.name,
|
|
324
|
+
position: pin.position,
|
|
325
|
+
pinType: pin.pinType,
|
|
326
|
+
});
|
|
327
|
+
addedPins.push(pinId);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const unplacedPins = existingPinIds.filter(pinId => {
|
|
332
|
+
return addedPins.find(id => id.equals(pinId)) === undefined;
|
|
333
|
+
});
|
|
334
|
+
if (unplacedPins.length > 0) {
|
|
335
|
+
component._unplacedPins = unplacedPins;
|
|
336
|
+
console.warn("Warning: There are unplaced pins: " + unplacedPins);
|
|
337
|
+
}
|
|
338
|
+
return symbolPinDefinitions;
|
|
339
|
+
}
|
|
340
|
+
export var RenderItemType;
|
|
341
|
+
(function (RenderItemType) {
|
|
342
|
+
RenderItemType["Wire"] = "wire";
|
|
343
|
+
RenderItemType["Component"] = "component";
|
|
344
|
+
})(RenderItemType || (RenderItemType = {}));
|
package/dist/esm/helpers.js
CHANGED
|
@@ -17,6 +17,7 @@ import { defaultPageMarginMM, defaultZoomScale, LengthUnit, MilsToMM, PxToMM } f
|
|
|
17
17
|
import { FrameParamKeys } from "./objects/Frame.js";
|
|
18
18
|
import Big from "big.js";
|
|
19
19
|
import { Logger } from "./logger.js";
|
|
20
|
+
import { NetGraph } from "./graph.js";
|
|
20
21
|
export var JSModuleType;
|
|
21
22
|
(function (JSModuleType) {
|
|
22
23
|
JSModuleType["CommonJs"] = "cjs";
|
|
@@ -237,11 +238,14 @@ export async function renderScript(scriptData, outputPath, options) {
|
|
|
237
238
|
errors,
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
|
-
const
|
|
241
|
+
const logger = new Logger();
|
|
242
|
+
const graphEngine = new NetGraph(logger);
|
|
243
|
+
const layoutEngine = new LayoutEngine(logger);
|
|
241
244
|
const layoutTimer = new SimpleStopwatch();
|
|
242
245
|
let sheetFrames;
|
|
243
246
|
try {
|
|
244
|
-
|
|
247
|
+
const { graph, containerFrames } = graphEngine.generateLayoutGraph(sequence, nets);
|
|
248
|
+
sheetFrames = layoutEngine.runLayout(graph, containerFrames, nets);
|
|
245
249
|
}
|
|
246
250
|
catch (err) {
|
|
247
251
|
throw new RenderError(`Error during layout generation: ${err}`, 'layout');
|
package/dist/esm/layout.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import graphlib
|
|
1
|
+
import graphlib from '@dagrejs/graphlib';
|
|
2
2
|
const { alg } = graphlib;
|
|
3
|
-
import { SymbolCustom, SymbolDrawing,
|
|
4
|
-
import {
|
|
5
|
-
import { ComponentTypes, defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, NetGraphicsParams, ParamKeys, WireAutoDirection } from './globals.js';
|
|
3
|
+
import { SymbolCustom, SymbolDrawing, SymbolPlaceholder, SymbolText, PlaceHolderCommands } from "./draw_symbols.js";
|
|
4
|
+
import { defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, NetGraphicsParams, ParamKeys, WireAutoDirection } from './globals.js';
|
|
6
5
|
import { Geometry, HorizontalAlign, VerticalAlign } from './geometry.js';
|
|
7
|
-
import { Logger } from './logger.js';
|
|
8
6
|
import { FixedFrameIds, Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.js';
|
|
9
7
|
import { areasOverlap, combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, roundValue, toNearestGrid } from './utils.js';
|
|
10
8
|
import { Direction } from './objects/types.js';
|
|
9
|
+
import { PinId } from './objects/PinDefinition.js';
|
|
11
10
|
import { milsToMM, UnitDimension } from './helpers.js';
|
|
12
|
-
import { numeric
|
|
11
|
+
import { numeric } from './objects/ParamDefinition.js';
|
|
12
|
+
import { generateLayoutPinDefinition, getWireName, RenderItemType } from './graph.js';
|
|
13
13
|
export class LayoutEngine {
|
|
14
14
|
logger;
|
|
15
15
|
layoutWarnings = [];
|
|
16
16
|
showBaseFrame = false;
|
|
17
|
-
constructor(options = { showBaseFrame: false }) {
|
|
18
|
-
this.logger =
|
|
17
|
+
constructor(logger, options = { showBaseFrame: false }) {
|
|
18
|
+
this.logger = logger;
|
|
19
19
|
const { showBaseFrame = false } = options ?? {};
|
|
20
20
|
this.showBaseFrame = showBaseFrame;
|
|
21
21
|
}
|
|
@@ -29,30 +29,8 @@ export class LayoutEngine {
|
|
|
29
29
|
const padding = ''.padStart(value * 4, ' ');
|
|
30
30
|
return "[" + value + "]" + padding;
|
|
31
31
|
}
|
|
32
|
-
runLayout(
|
|
33
|
-
const logNodesAndEdges = true;
|
|
32
|
+
runLayout(graph, containerFrames, nets) {
|
|
34
33
|
const renderNets = this.collectRenderNets(nets);
|
|
35
|
-
this.print('===== creating graph and populating with nodes =====');
|
|
36
|
-
const { graph, containerFrames } = this.generateLayoutGraph(sequence, nets);
|
|
37
|
-
this.print('===== done populating graph =====');
|
|
38
|
-
this.print('');
|
|
39
|
-
if (logNodesAndEdges) {
|
|
40
|
-
this.print('===== graph edges =====');
|
|
41
|
-
const allEdges = graph.edges();
|
|
42
|
-
allEdges.forEach(edge => {
|
|
43
|
-
const [nodeId1, pin1, nodeId2, pin2] = graph.edge(edge);
|
|
44
|
-
this.print(nodeId1, 'pin', pin1, '-----', nodeId2, 'pin', pin2);
|
|
45
|
-
});
|
|
46
|
-
this.print('===== end edges =====');
|
|
47
|
-
this.print();
|
|
48
|
-
this.print('===== graph nodes =====');
|
|
49
|
-
const nodes = graph.nodes();
|
|
50
|
-
nodes.forEach(node => {
|
|
51
|
-
this.print(`name:${node}, value:${graph.node(node)}`);
|
|
52
|
-
});
|
|
53
|
-
this.print('===== end nodes =====');
|
|
54
|
-
this.print('');
|
|
55
|
-
}
|
|
56
34
|
const subgraphInfo = this.sizeSubGraphs(graph);
|
|
57
35
|
const dumpSubgraphInfo = true;
|
|
58
36
|
if (dumpSubgraphInfo) {
|
|
@@ -643,158 +621,6 @@ export class LayoutEngine {
|
|
|
643
621
|
}
|
|
644
622
|
}
|
|
645
623
|
}
|
|
646
|
-
generateLayoutGraph(sequence, nets) {
|
|
647
|
-
let previousNode = null;
|
|
648
|
-
let previousPin = null;
|
|
649
|
-
const graph = new Graph({
|
|
650
|
-
directed: true,
|
|
651
|
-
compound: true,
|
|
652
|
-
});
|
|
653
|
-
this.print('sequence length:', sequence.length);
|
|
654
|
-
const baseFrame = new RenderFrame(new Frame(FixedFrameIds.BaseFrame));
|
|
655
|
-
const frameStack = [baseFrame];
|
|
656
|
-
const containerFrames = [baseFrame];
|
|
657
|
-
sequence.forEach((sequenceStep, index) => {
|
|
658
|
-
const action = sequenceStep[0];
|
|
659
|
-
let tmpComponent;
|
|
660
|
-
switch (action) {
|
|
661
|
-
case SequenceAction.To:
|
|
662
|
-
case SequenceAction.At: {
|
|
663
|
-
this.print(...sequenceStep);
|
|
664
|
-
const [, component, pin] = sequenceStep;
|
|
665
|
-
const tmpInstanceName = component.instanceName;
|
|
666
|
-
if (!graph.hasNode(tmpInstanceName)) {
|
|
667
|
-
this.print('create instance', tmpInstanceName);
|
|
668
|
-
const { displayProp = null } = component;
|
|
669
|
-
let tmpSymbol;
|
|
670
|
-
if (displayProp instanceof SymbolDrawing) {
|
|
671
|
-
tmpSymbol = new SymbolPlaceholder(displayProp);
|
|
672
|
-
tmpSymbol.drawing.logger = this.logger;
|
|
673
|
-
}
|
|
674
|
-
else {
|
|
675
|
-
const symbolPinDefinitions = generateLayoutPinDefinition(component);
|
|
676
|
-
if (component.typeProp === ComponentTypes.module) {
|
|
677
|
-
tmpSymbol = new SymbolCustomModule(symbolPinDefinitions, component.pinsMaxPositions);
|
|
678
|
-
}
|
|
679
|
-
else {
|
|
680
|
-
tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
applyComponentParamsToSymbol(component, tmpSymbol);
|
|
684
|
-
tmpSymbol.refreshDrawing();
|
|
685
|
-
const { width: useWidth, height: useHeight } = tmpSymbol.size();
|
|
686
|
-
tmpComponent = new RenderComponent(component, useWidth, useHeight);
|
|
687
|
-
tmpComponent.symbol = tmpSymbol;
|
|
688
|
-
graph.setNode(tmpInstanceName, [RenderItemType.Component, tmpComponent, index]);
|
|
689
|
-
const currentFrame = frameStack[frameStack.length - 1];
|
|
690
|
-
currentFrame && currentFrame.innerItems.push(tmpComponent);
|
|
691
|
-
}
|
|
692
|
-
if (action === SequenceAction.To && previousNode && previousPin) {
|
|
693
|
-
this.setGraphEdge(graph, previousNode, tmpInstanceName, makeEdgeValue(previousNode, previousPin, tmpInstanceName, pin, index));
|
|
694
|
-
}
|
|
695
|
-
previousNode = tmpInstanceName;
|
|
696
|
-
previousPin = pin;
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
case SequenceAction.Wire: {
|
|
700
|
-
const [, wireId, wireSegments] = sequenceStep;
|
|
701
|
-
let useNet;
|
|
702
|
-
if (previousNode !== null) {
|
|
703
|
-
const [prevNodeType, prevNodeItem] = graph.node(previousNode);
|
|
704
|
-
if (prevNodeType === RenderItemType.Component) {
|
|
705
|
-
const matchingItem = nets.find(([comp, pin]) => {
|
|
706
|
-
return comp.instanceName === previousNode
|
|
707
|
-
&& pin === previousPin;
|
|
708
|
-
});
|
|
709
|
-
if (matchingItem !== undefined) {
|
|
710
|
-
useNet = matchingItem[2];
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
else if (prevNodeType === RenderItemType.Wire) {
|
|
714
|
-
useNet = prevNodeItem.net;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
const wire = new RenderWire(useNet, numeric(0), numeric(0), wireSegments);
|
|
718
|
-
wire.id = wireId;
|
|
719
|
-
wire.netName = useNet.toString();
|
|
720
|
-
const wireName = getWireName(wire.id);
|
|
721
|
-
graph.setNode(wireName, [RenderItemType.Wire, wire, index]);
|
|
722
|
-
this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, 0, index));
|
|
723
|
-
previousNode = wireName;
|
|
724
|
-
previousPin = 1;
|
|
725
|
-
const wireSegmentsInfo = wireSegments.map(item => {
|
|
726
|
-
const tmp = {
|
|
727
|
-
direction: item.direction,
|
|
728
|
-
value: item.value,
|
|
729
|
-
};
|
|
730
|
-
if (item.valueXY) {
|
|
731
|
-
tmp.valueXY = item.valueXY;
|
|
732
|
-
}
|
|
733
|
-
if (item.until) {
|
|
734
|
-
tmp.until = [item.until[0].toString(), item.until[1]];
|
|
735
|
-
}
|
|
736
|
-
return tmp;
|
|
737
|
-
});
|
|
738
|
-
this.print(SequenceAction.Wire, wireId, JSON.stringify(wireSegmentsInfo));
|
|
739
|
-
break;
|
|
740
|
-
}
|
|
741
|
-
case SequenceAction.WireJump: {
|
|
742
|
-
this.print(...sequenceStep);
|
|
743
|
-
const wireId = sequenceStep[1];
|
|
744
|
-
const wireName = getWireName(wireId);
|
|
745
|
-
let wirePin = 1;
|
|
746
|
-
if (sequenceStep.length === 3) {
|
|
747
|
-
wirePin = sequenceStep[2];
|
|
748
|
-
}
|
|
749
|
-
previousNode = wireName;
|
|
750
|
-
previousPin = wirePin;
|
|
751
|
-
break;
|
|
752
|
-
}
|
|
753
|
-
case SequenceAction.Frame: {
|
|
754
|
-
const [, frameObject, frameAction] = sequenceStep;
|
|
755
|
-
if (frameAction === FrameAction.Enter) {
|
|
756
|
-
const prevFrame = frameStack[frameStack.length - 1];
|
|
757
|
-
const newFrame = new RenderFrame(frameObject);
|
|
758
|
-
if (frameObject.parameters.has(FrameParamKeys.Direction)) {
|
|
759
|
-
newFrame.direction =
|
|
760
|
-
frameObject.parameters.get(FrameParamKeys.Direction);
|
|
761
|
-
}
|
|
762
|
-
if (frameObject.parameters.has(FrameParamKeys.Padding)) {
|
|
763
|
-
newFrame.padding = milsToMM(frameObject.parameters.get(FrameParamKeys.Padding));
|
|
764
|
-
}
|
|
765
|
-
if (frameObject.parameters.has(FrameParamKeys.Border)) {
|
|
766
|
-
newFrame.borderWidth =
|
|
767
|
-
frameObject.parameters.get(FrameParamKeys.Border);
|
|
768
|
-
}
|
|
769
|
-
if (frameObject.parameters.has(FrameParamKeys.Width)) {
|
|
770
|
-
newFrame.width = milsToMM(frameObject.parameters.get(FrameParamKeys.Width));
|
|
771
|
-
}
|
|
772
|
-
if (frameObject.parameters.has(FrameParamKeys.Height)) {
|
|
773
|
-
newFrame.height = milsToMM(frameObject.parameters.get(FrameParamKeys.Height));
|
|
774
|
-
}
|
|
775
|
-
containerFrames.push(newFrame);
|
|
776
|
-
frameStack.push(newFrame);
|
|
777
|
-
prevFrame && prevFrame.innerItems.push(newFrame);
|
|
778
|
-
}
|
|
779
|
-
else if (frameAction === FrameAction.Exit) {
|
|
780
|
-
frameStack.pop();
|
|
781
|
-
}
|
|
782
|
-
break;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
});
|
|
786
|
-
return {
|
|
787
|
-
graph,
|
|
788
|
-
containerFrames,
|
|
789
|
-
};
|
|
790
|
-
}
|
|
791
|
-
setGraphEdge(graph, node1, node2, edgeValue) {
|
|
792
|
-
if (!graph.isDirected && graph.hasEdge(node1, node2)) {
|
|
793
|
-
this.print(`Warning: edge already exists ${node1} ${node2}`);
|
|
794
|
-
}
|
|
795
|
-
graph.setEdge(node1, node2, edgeValue);
|
|
796
|
-
this.print(`created edge: node1:${node1} node2:${node2} edgeValue:${edgeValue}`);
|
|
797
|
-
}
|
|
798
624
|
sizeSubGraphs(graph) {
|
|
799
625
|
const subGraphs = alg.components(graph);
|
|
800
626
|
const subGraphsStarts = [];
|
|
@@ -864,7 +690,11 @@ export class LayoutEngine {
|
|
|
864
690
|
}
|
|
865
691
|
if (subgraphEdges.length === 0) {
|
|
866
692
|
const [, node1] = graph.node(firstNodeId);
|
|
867
|
-
|
|
693
|
+
let defaultPin = new PinId(1);
|
|
694
|
+
if (node1 instanceof RenderComponent) {
|
|
695
|
+
defaultPin = node1.component.getDefaultPin();
|
|
696
|
+
}
|
|
697
|
+
this.placeNodeAtPosition(numeric(0), numeric(0), node1, defaultPin);
|
|
868
698
|
return;
|
|
869
699
|
}
|
|
870
700
|
let fixedNode;
|
|
@@ -1092,52 +922,6 @@ function getNeighbours(graph, nodeIds) {
|
|
|
1092
922
|
return accum;
|
|
1093
923
|
}, []);
|
|
1094
924
|
}
|
|
1095
|
-
function makeEdgeValue(instanceName1, instancePin1, instanceName2, instancePin2, priority) {
|
|
1096
|
-
return [instanceName1, instancePin1, instanceName2, instancePin2, priority];
|
|
1097
|
-
}
|
|
1098
|
-
function getWireName(wireId) {
|
|
1099
|
-
return 'wire:' + wireId;
|
|
1100
|
-
}
|
|
1101
|
-
function generateLayoutPinDefinition(component) {
|
|
1102
|
-
const pins = component.pins;
|
|
1103
|
-
const symbolPinDefinitions = [];
|
|
1104
|
-
const existingPinIds = Array.from(pins.keys());
|
|
1105
|
-
const arrangeProps = component.arrangeProps ?? [];
|
|
1106
|
-
const addedPins = [];
|
|
1107
|
-
for (const [key, items] of arrangeProps) {
|
|
1108
|
-
let useItems;
|
|
1109
|
-
if (!Array.isArray(items)) {
|
|
1110
|
-
useItems = [items];
|
|
1111
|
-
}
|
|
1112
|
-
else {
|
|
1113
|
-
useItems = [...items];
|
|
1114
|
-
}
|
|
1115
|
-
useItems.forEach(pinId => {
|
|
1116
|
-
if (pinId instanceof NumericValue) {
|
|
1117
|
-
const pinIdValue = pinId.toNumber();
|
|
1118
|
-
if (existingPinIds.indexOf(pinIdValue) !== -1) {
|
|
1119
|
-
const pin = pins.get(pinIdValue);
|
|
1120
|
-
symbolPinDefinitions.push({
|
|
1121
|
-
side: key,
|
|
1122
|
-
pinId: pinIdValue,
|
|
1123
|
-
text: pin.name,
|
|
1124
|
-
position: pin.position,
|
|
1125
|
-
pinType: pin.pinType,
|
|
1126
|
-
});
|
|
1127
|
-
addedPins.push(pinIdValue);
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
const unplacedPins = existingPinIds.filter(pinId => {
|
|
1133
|
-
return addedPins.indexOf(pinId) === -1;
|
|
1134
|
-
});
|
|
1135
|
-
if (unplacedPins.length > 0) {
|
|
1136
|
-
component._unplacedPins = unplacedPins;
|
|
1137
|
-
console.warn("Warning: There are unplaced pins: " + unplacedPins);
|
|
1138
|
-
}
|
|
1139
|
-
return symbolPinDefinitions;
|
|
1140
|
-
}
|
|
1141
925
|
export function applyComponentParamsToSymbol(component, symbol) {
|
|
1142
926
|
const { widthProp = null, heightProp = null } = component;
|
|
1143
927
|
const newMap = new Map(component.parameters);
|
|
@@ -1523,8 +1307,3 @@ export function ExtractDrawingRects(drawing) {
|
|
|
1523
1307
|
function isPointOverlap(x, y, other) {
|
|
1524
1308
|
return (x >= other.x && y >= other.y && x <= (other.x + other.width) && y <= (other.y + other.height));
|
|
1525
1309
|
}
|
|
1526
|
-
var RenderItemType;
|
|
1527
|
-
(function (RenderItemType) {
|
|
1528
|
-
RenderItemType["Wire"] = "wire";
|
|
1529
|
-
RenderItemType["Component"] = "component";
|
|
1530
|
-
})(RenderItemType || (RenderItemType = {}));
|