circuitscript 0.1.16 → 0.1.18

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.
Files changed (45) hide show
  1. package/dist/cjs/BaseVisitor.js +2 -1
  2. package/dist/cjs/draw_symbols.js +18 -17
  3. package/dist/cjs/execute.js +45 -26
  4. package/dist/cjs/export.js +3 -3
  5. package/dist/cjs/globals.js +1 -0
  6. package/dist/cjs/graph.js +101 -27
  7. package/dist/cjs/helpers.js +55 -22
  8. package/dist/cjs/layout.js +6 -1
  9. package/dist/cjs/objects/ClassComponent.js +27 -20
  10. package/dist/cjs/objects/ExecutionScope.js +9 -4
  11. package/dist/cjs/objects/Net.js +2 -1
  12. package/dist/cjs/objects/PinDefinition.js +55 -3
  13. package/dist/cjs/objects/types.js +17 -1
  14. package/dist/cjs/visitor.js +78 -20
  15. package/dist/esm/BaseVisitor.js +2 -1
  16. package/dist/esm/draw_symbols.js +18 -17
  17. package/dist/esm/execute.js +46 -27
  18. package/dist/esm/export.js +1 -1
  19. package/dist/esm/globals.js +1 -0
  20. package/dist/esm/graph.js +79 -28
  21. package/dist/esm/helpers.js +46 -21
  22. package/dist/esm/layout.js +6 -1
  23. package/dist/esm/objects/ClassComponent.js +28 -21
  24. package/dist/esm/objects/ExecutionScope.js +9 -4
  25. package/dist/esm/objects/Net.js +2 -1
  26. package/dist/esm/objects/PinDefinition.js +53 -2
  27. package/dist/esm/objects/types.js +16 -0
  28. package/dist/esm/visitor.js +80 -22
  29. package/dist/libs/std.cst +3 -2
  30. package/dist/types/BaseVisitor.d.ts +2 -1
  31. package/dist/types/draw_symbols.d.ts +13 -7
  32. package/dist/types/execute.d.ts +7 -7
  33. package/dist/types/export.d.ts +2 -2
  34. package/dist/types/globals.d.ts +1 -0
  35. package/dist/types/graph.d.ts +2 -1
  36. package/dist/types/helpers.d.ts +15 -2
  37. package/dist/types/layout.d.ts +2 -1
  38. package/dist/types/objects/ClassComponent.d.ts +8 -8
  39. package/dist/types/objects/ExecutionScope.d.ts +7 -6
  40. package/dist/types/objects/Net.d.ts +3 -2
  41. package/dist/types/objects/PinDefinition.d.ts +17 -2
  42. package/dist/types/objects/types.d.ts +17 -2
  43. package/dist/types/visitor.d.ts +1 -0
  44. package/libs/std.cst +3 -2
  45. package/package.json +2 -1
@@ -3,7 +3,7 @@ import { ClassComponent, ModuleComponent } from './objects/ClassComponent.js';
3
3
  import { ActiveObject, ExecutionScope, FrameAction, SequenceAction } from './objects/ExecutionScope.js';
4
4
  import { Net } from './objects/Net.js';
5
5
  import { numeric, NumericValue } from './objects/ParamDefinition.js';
6
- import { PortSide } from './objects/PinDefinition.js';
6
+ import { PinId, PortSide } from './objects/PinDefinition.js';
7
7
  import { AnyReference, CFunctionEntry, DeclaredReference, Direction } from './objects/types.js';
8
8
  import { Wire } from './objects/Wire.js';
9
9
  import { Frame } from './objects/Frame.js';
@@ -151,7 +151,7 @@ export class ExecutionContext {
151
151
  const tmpArrangeRight = [];
152
152
  pins.forEach((pin, index) => {
153
153
  const useArray = (index % 2 === 0) ? tmpArrangeLeft : tmpArrangeRight;
154
- useArray.push(numeric(pin.id));
154
+ useArray.push(pin.id);
155
155
  });
156
156
  const arrangeProp = new Map([
157
157
  [SymbolPinSide.Left, tmpArrangeLeft],
@@ -161,11 +161,9 @@ export class ExecutionContext {
161
161
  }
162
162
  if (props.arrange !== null) {
163
163
  component.arrangeProps = this.removeArrangePropDuplicates(props.arrange);
164
- const arrangePropPins = this.getArrangePropPins(component.arrangeProps).map(item => {
165
- return item.toNumber();
166
- });
164
+ const arrangePropPins = this.getArrangePropPins(component.arrangeProps);
167
165
  pins.forEach(pin => {
168
- if (arrangePropPins.indexOf(pin.id) === -1) {
166
+ if (arrangePropPins.find(id => id.equals(pin.id)) === undefined) {
169
167
  this.logWarning(`Pin ${pin.id} is not specified in arrange property`);
170
168
  }
171
169
  });
@@ -182,6 +180,7 @@ export class ExecutionContext {
182
180
  });
183
181
  if (component.typeProp === ComponentTypes.net) {
184
182
  const netName = paramsMap.get(ParamKeys.net_name);
183
+ const netType = paramsMap.get(ParamKeys.net_type);
185
184
  let priority = 0;
186
185
  if (paramsMap.has(ParamKeys.priority)) {
187
186
  priority = paramsMap.get(ParamKeys.priority).toNumber();
@@ -193,21 +192,26 @@ export class ExecutionContext {
193
192
  this.log('net found', tmpNet.namespace, tmpNet.name);
194
193
  }
195
194
  else {
196
- tmpNet = new Net(this.netNamespace, netName, priority);
195
+ tmpNet = new Net(this.netNamespace, netName, priority, netType);
197
196
  this.log('net not found, added net instance', tmpNet.namespace, tmpNet.name);
198
197
  }
199
- const defaultPin = 1;
198
+ const defaultPin = new PinId(1);
200
199
  this.scope.setNet(component, defaultPin, tmpNet);
201
200
  this.log('set net', netName, 'component', component, defaultPin);
202
201
  }
203
202
  const { pins: pinSides, maxPositions } = getPortSide(component.pins, component.arrangeProps);
204
203
  component.pinsMaxPositions = maxPositions;
204
+ const pinIdKeys = Array.from(component.pins.keys());
205
205
  pinSides.forEach(({ pinId, side, position }) => {
206
- if (component.pins.has(pinId)) {
207
- const tmpPin = component.pins.get(pinId);
206
+ const matchedPinId = pinIdKeys.find(id => id.equals(pinId));
207
+ if (matchedPinId) {
208
+ const tmpPin = component.pins.get(matchedPinId);
208
209
  tmpPin.side = side;
209
210
  tmpPin.position = position;
210
211
  }
212
+ else {
213
+ throw 'Not found!';
214
+ }
211
215
  });
212
216
  this.scope.instances.set(instanceName, component);
213
217
  const pinsOutput = pins.map((pin) => {
@@ -230,15 +234,32 @@ export class ExecutionContext {
230
234
  if (!Array.isArray(items)) {
231
235
  items = [items];
232
236
  }
237
+ items = items.map(item => {
238
+ if (item instanceof NumericValue) {
239
+ item = item.toNumber();
240
+ }
241
+ if (item instanceof PinId) {
242
+ return item;
243
+ }
244
+ else if (PinId.isPinIdType(item)) {
245
+ return new PinId(item);
246
+ }
247
+ return item;
248
+ });
249
+ arrangeProp.set(side, items);
250
+ if (!Array.isArray(items)) {
251
+ items = [items];
252
+ }
233
253
  const uniqueItems = [];
234
254
  items.forEach(item => {
235
- if (item instanceof NumericValue) {
236
- if (seenIds.indexOf(item.toNumber()) === -1) {
237
- seenIds.push(item.toNumber());
255
+ if (item instanceof PinId) {
256
+ const found = seenIds.find(id => id.equals(item));
257
+ if (!found) {
258
+ seenIds.push(item);
238
259
  uniqueItems.push(item);
239
260
  }
240
261
  else {
241
- this.logWarning(`Pin ${item.toNumber()} specified more than once in arrange property`);
262
+ this.logWarning(`Pin ${item.toString()} specified more than once in arrange property`);
242
263
  }
243
264
  }
244
265
  else {
@@ -261,7 +282,7 @@ export class ExecutionContext {
261
282
  const items = arrangeProps.get(side);
262
283
  if (items) {
263
284
  items.forEach(item => {
264
- if (item instanceof NumericValue) {
285
+ if (item instanceof PinId) {
265
286
  pins.push(item);
266
287
  }
267
288
  });
@@ -348,13 +369,12 @@ export class ExecutionContext {
348
369
  if (pinId === null) {
349
370
  usePinId = component.getDefaultPin();
350
371
  }
372
+ else if (component.hasPin(pinId)) {
373
+ usePinId = component.getPin(pinId);
374
+ }
351
375
  else {
352
- if (component.hasPin(pinId)) {
353
- usePinId = component.getPin(pinId);
354
- }
355
- else {
356
- throw 'Invalid pin number ' + pinId + ' in ' + component;
357
- }
376
+ throw new RuntimeExecutionError('Invalid pin number '
377
+ + pinId + ' in ' + component);
358
378
  }
359
379
  this.scope.setCurrent(component, usePinId);
360
380
  if (!this.scope.hasNet(component, pinId)) {
@@ -383,7 +403,7 @@ export class ExecutionContext {
383
403
  const cloneInstanceName = component.instanceName + ':' + idNum;
384
404
  this.scope.instances.set(cloneInstanceName, componentCopy);
385
405
  componentCopy.instanceName = cloneInstanceName;
386
- const defaultPin = 1;
406
+ const defaultPin = new PinId(1);
387
407
  if (this.scope.getNet(component, defaultPin) === null) {
388
408
  const foundNet = this.resolveComponentPinNet(component, defaultPin);
389
409
  if (foundNet !== null) {
@@ -602,7 +622,7 @@ export class ExecutionContext {
602
622
  else if (type === ReferenceTypes.instance) {
603
623
  const tmpComponent = parentValue;
604
624
  if (tmpComponent.typeProp === ComponentTypes.net) {
605
- const usedNet = this.scope.getNet(tmpComponent, 1);
625
+ const usedNet = this.scope.getNet(tmpComponent, new PinId(1));
606
626
  if (usedNet) {
607
627
  const trailerValue = trailers.join(".");
608
628
  useValue = usedNet.params.get(trailerValue) ?? null;
@@ -696,7 +716,7 @@ export class ExecutionContext {
696
716
  const linkRootComponent = true;
697
717
  const tmpRoot = childScope.componentRoot;
698
718
  if (linkRootComponent) {
699
- const netConnectedToRoot = childScope.getNet(tmpRoot, 1);
719
+ const netConnectedToRoot = childScope.getNet(tmpRoot, new PinId(1));
700
720
  if (netConnectedToRoot !== null) {
701
721
  let currentNet = this.scope.getNet(currentComponent, currentPin);
702
722
  if (currentNet === null) {
@@ -1043,10 +1063,9 @@ export function getPortSide(pins, arrangeProps) {
1043
1063
  position += item[0].toNumber();
1044
1064
  }
1045
1065
  else {
1046
- const itemValue = item.toNumber();
1047
- if (existingPinIds.indexOf(itemValue) !== -1) {
1066
+ if (existingPinIds.find(id => id.equals(item))) {
1048
1067
  result.push({
1049
- pinId: itemValue,
1068
+ pinId: item,
1050
1069
  side: useSide,
1051
1070
  position,
1052
1071
  order: counter
@@ -1,6 +1,6 @@
1
1
  import { NoNetText } from "./globals.js";
2
2
  import { NumericValue } from "./objects/ParamDefinition.js";
3
- export function generateKiCADNetList(netlist) {
3
+ export function generateKiCadNetList(netlist) {
4
4
  const componentsList = [];
5
5
  const nets = {};
6
6
  const missingFootprints = [];
@@ -12,6 +12,7 @@ export var ParamKeys;
12
12
  (function (ParamKeys) {
13
13
  ParamKeys["priority"] = "priority";
14
14
  ParamKeys["net_name"] = "net_name";
15
+ ParamKeys["net_type"] = "net_type";
15
16
  ParamKeys["flip"] = "flip";
16
17
  ParamKeys["flipX"] = "flipX";
17
18
  ParamKeys["flipY"] = "flipY";
package/dist/esm/graph.js CHANGED
@@ -5,7 +5,10 @@ import { milsToMM } from "./helpers.js";
5
5
  import { RenderFrame, RenderComponent, applyComponentParamsToSymbol, RenderWire } from "./layout.js";
6
6
  import { SequenceAction, FrameAction } from "./objects/ExecutionScope.js";
7
7
  import { Frame, FixedFrameIds, FrameParamKeys } from "./objects/Frame.js";
8
- import { numeric, NumericValue } from "./objects/ParamDefinition.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";
9
12
  export class NetGraph {
10
13
  logger;
11
14
  constructor(logger) {
@@ -73,7 +76,7 @@ export class NetGraph {
73
76
  if (prevNodeType === RenderItemType.Component) {
74
77
  const matchingItem = nets.find(([comp, pin]) => {
75
78
  return comp.instanceName === previousNode
76
- && pin === previousPin;
79
+ && pin.equals(previousPin);
77
80
  });
78
81
  if (matchingItem !== undefined) {
79
82
  useNet = matchingItem[2];
@@ -188,21 +191,71 @@ export class NetGraph {
188
191
  this.logger.add(params.join(' '));
189
192
  }
190
193
  generateNetGraph(nets) {
191
- const graph = new Graph({
192
- directed: false
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';
193
199
  });
194
- nets.forEach(item => {
195
- const [component, pin, net] = item;
196
- const netNodeName = this.getNetNodeName(net);
197
- if (!graph.hasNode(netNodeName)) {
198
- graph.setNode(netNodeName, net);
199
- }
200
- const componentNodeName = this.getComponentName(component);
201
- if (!graph.hasNode(componentNodeName)) {
202
- graph.setNode(componentNodeName, component);
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);
203
227
  }
204
- graph.setEdge(netNodeName, componentNodeName, [component, pin, net]);
205
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
+ };
206
259
  }
207
260
  findNodePaths(graph, startNode, endNode, seenNodes = []) {
208
261
  const edges = graph.nodeEdges(startNode);
@@ -261,24 +314,22 @@ export function generateLayoutPinDefinition(component) {
261
314
  useItems = [...items];
262
315
  }
263
316
  useItems.forEach(pinId => {
264
- if (pinId instanceof NumericValue) {
265
- const pinIdValue = pinId.toNumber();
266
- if (existingPinIds.indexOf(pinIdValue) !== -1) {
267
- const pin = pins.get(pinIdValue);
268
- symbolPinDefinitions.push({
269
- side: key,
270
- pinId: pinIdValue,
271
- text: pin.name,
272
- position: pin.position,
273
- pinType: pin.pinType,
274
- });
275
- addedPins.push(pinIdValue);
276
- }
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);
277
328
  }
278
329
  });
279
330
  }
280
331
  const unplacedPins = existingPinIds.filter(pinId => {
281
- return addedPins.indexOf(pinId) === -1;
332
+ return addedPins.find(id => id.equals(pinId)) === undefined;
282
333
  });
283
334
  if (unplacedPins.length > 0) {
284
335
  component._unplacedPins = unplacedPins;
@@ -1,7 +1,7 @@
1
1
  import { writeFileSync, createWriteStream, existsSync, mkdirSync } from "fs";
2
2
  import path from "path";
3
3
  import PDFDocument from "pdfkit";
4
- import { generateKiCADNetList, printTree } from "./export.js";
4
+ import { generateKiCadNetList, printTree } from "./export.js";
5
5
  import { LayoutEngine } from "./layout.js";
6
6
  import { parseFileWithVisitor } from "./parser.js";
7
7
  import { generatePdfOutput, generateSvgOutput, renderSheetsToSVG } from "./render.js";
@@ -148,6 +148,12 @@ export async function validateScript(filePath, scriptData, options) {
148
148
  return visitorResolver;
149
149
  }
150
150
  export async function renderScript(scriptData, outputPath, options) {
151
+ const parseHandlers = [
152
+ new KiCadNetListOutputHandler(),
153
+ ];
154
+ return renderScriptCustom(scriptData, outputPath, options, parseHandlers);
155
+ }
156
+ export async function renderScriptCustom(scriptData, outputPath, options, parseHandlers) {
151
157
  const { dumpNets = false, dumpData = false, showStats = false, environment } = options;
152
158
  const errors = [];
153
159
  const onErrorHandler = (message, context, error) => {
@@ -196,6 +202,12 @@ export async function renderScript(scriptData, outputPath, options) {
196
202
  printWarnings(visitor.getWarnings());
197
203
  showStats && console.log('Lexing took:', lexerTimeTaken);
198
204
  showStats && console.log('Parsing took:', parserTimeTaken);
205
+ try {
206
+ visitor.annotateComponents();
207
+ }
208
+ catch (err) {
209
+ throw new RenderError(`Error during component annotation: ${err}`, 'annotation');
210
+ }
199
211
  if (dumpNets) {
200
212
  const nets = visitor.dumpNets();
201
213
  nets.forEach(item => console.log(item.join(" | ")));
@@ -208,12 +220,6 @@ export async function renderScript(scriptData, outputPath, options) {
208
220
  let svgOutput = "";
209
221
  if (errors.length === 0) {
210
222
  const { frameComponent } = visitor.applySheetFrameComponent();
211
- try {
212
- visitor.annotateComponents();
213
- }
214
- catch (err) {
215
- throw new RenderError(`Error during component annotation: ${err}`, 'annotation');
216
- }
217
223
  const { sequence, nets } = visitor.getGraph();
218
224
  const tmpSequence = generateDebugSequenceAction(sequence).map(item => sequenceActionString(item));
219
225
  dumpData && writeFileSync(dumpDirectory + 'raw-sequence.txt', tmpSequence.join('\n'));
@@ -222,21 +228,18 @@ export async function renderScript(scriptData, outputPath, options) {
222
228
  let outputDefaultZoom = defaultZoomScale;
223
229
  if (outputPath) {
224
230
  fileExtension = path.extname(outputPath).substring(1);
225
- if (fileExtension === "pdf") {
226
- outputDefaultZoom = 1;
227
- }
228
231
  }
229
- if (fileExtension === 'net') {
230
- const { tree: kicadNetList, missingFootprints } = generateKiCADNetList(visitor.getNetList());
231
- missingFootprints.forEach(entry => {
232
- console.log(`${entry.refdes} (${entry.instanceName}) does not have footprint`);
233
- });
234
- writeFileSync(outputPath, printTree(kicadNetList));
235
- console.log('Generated file', outputPath);
236
- return {
237
- svgOutput: null,
238
- errors,
239
- };
232
+ for (let i = 0; i < parseHandlers.length; i++) {
233
+ const handler = parseHandlers[i];
234
+ if (handler.beforeRender) {
235
+ const keepParsing = handler.parse(visitor, outputPath, fileExtension);
236
+ if (!keepParsing) {
237
+ return {
238
+ svgOutput: null,
239
+ errors
240
+ };
241
+ }
242
+ }
240
243
  }
241
244
  const logger = new Logger();
242
245
  const graphEngine = new NetGraph(logger);
@@ -265,6 +268,9 @@ export async function renderScript(scriptData, outputPath, options) {
265
268
  showStats && console.log('Render took:', generateSvgTimer.lap());
266
269
  dumpData && writeFileSync(dumpDirectory + 'raw-render.txt', renderLogger.dump());
267
270
  try {
271
+ if (fileExtension === "pdf") {
272
+ outputDefaultZoom = 1;
273
+ }
268
274
  svgOutput = generateSvgOutput(svgCanvas, outputDefaultZoom);
269
275
  }
270
276
  catch (err) {
@@ -315,6 +321,25 @@ export async function renderScript(scriptData, outputPath, options) {
315
321
  errors
316
322
  };
317
323
  }
324
+ export class ParseOutputHandler {
325
+ beforeRender = false;
326
+ afterRender = false;
327
+ }
328
+ export class KiCadNetListOutputHandler extends ParseOutputHandler {
329
+ beforeRender = true;
330
+ parse(visitor, outputPath, fileExtension) {
331
+ if (outputPath !== null && fileExtension === "net") {
332
+ const { tree: kiCadNetList, missingFootprints } = generateKiCadNetList(visitor.getNetList());
333
+ missingFootprints.forEach(entry => {
334
+ console.log(`${entry.refdes} (${entry.instanceName}) does not have footprint`);
335
+ });
336
+ writeFileSync(outputPath, printTree(kiCadNetList));
337
+ console.log('Generated file', outputPath);
338
+ return false;
339
+ }
340
+ return true;
341
+ }
342
+ }
318
343
  export function detectJSModuleType() {
319
344
  if (typeof __filename === 'undefined' &&
320
345
  typeof __dirname === 'undefined') {
@@ -6,6 +6,7 @@ import { Geometry, HorizontalAlign, VerticalAlign } from './geometry.js';
6
6
  import { FixedFrameIds, Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.js';
7
7
  import { areasOverlap, combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, roundValue, toNearestGrid } from './utils.js';
8
8
  import { Direction } from './objects/types.js';
9
+ import { PinId } from './objects/PinDefinition.js';
9
10
  import { milsToMM, UnitDimension } from './helpers.js';
10
11
  import { numeric } from './objects/ParamDefinition.js';
11
12
  import { generateLayoutPinDefinition, getWireName, RenderItemType } from './graph.js';
@@ -689,7 +690,11 @@ export class LayoutEngine {
689
690
  }
690
691
  if (subgraphEdges.length === 0) {
691
692
  const [, node1] = graph.node(firstNodeId);
692
- this.placeNodeAtPosition(numeric(0), numeric(0), node1, 1);
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);
693
698
  return;
694
699
  }
695
700
  let fixedNode;
@@ -1,7 +1,8 @@
1
1
  import { SymbolDrawingCommands } from '../draw_symbols.js';
2
- import { PinDefinition, PinIdType } from './PinDefinition.js';
2
+ import { PinDefinition, PinId, PinIdType } from './PinDefinition.js';
3
3
  import { PinTypes } from './PinTypes.js';
4
4
  import { ParamKeys } from '../globals.js';
5
+ import { RuntimeExecutionError } from '../utils.js';
5
6
  export class ClassComponent {
6
7
  instanceName;
7
8
  numPins;
@@ -35,47 +36,53 @@ export class ClassComponent {
35
36
  setupPins() {
36
37
  for (let i = 1; i < this.numPins + 1; i++) {
37
38
  const pinIndex = i;
38
- this.pins.set(pinIndex, new PinDefinition(pinIndex, PinIdType.Int, pinIndex.toString(), PinTypes.Any));
39
+ this.pins.set(new PinId(pinIndex), new PinDefinition(pinIndex, PinIdType.Int, pinIndex.toString(), PinTypes.Any));
39
40
  }
40
41
  this.refreshPinsCache();
41
42
  }
42
43
  getDefaultPin() {
43
- return 1;
44
+ const pins = Array.from(this.pins.keys());
45
+ pins.sort();
46
+ return pins[0];
44
47
  }
45
48
  hasPin(pinId) {
46
- if (typeof pinId === 'number') {
47
- return this.pins.has(pinId);
48
- }
49
- else {
50
- for (const [, pinDef] of this.pins) {
51
- if (pinDef.name === pinId ||
52
- pinDef.altNames.indexOf(pinId) !== -1) {
53
- return true;
54
- }
49
+ for (const [pin, pinDef] of this.pins) {
50
+ if (pin.equals(pinId)) {
51
+ return true;
52
+ }
53
+ if (pinId.getType() === PinIdType.Str && (pinDef.name === pinId.getValue() ||
54
+ pinDef.altNames.indexOf(pinId.getValue()) !== -1)) {
55
+ return true;
55
56
  }
56
57
  }
57
58
  return false;
58
59
  }
59
60
  getPin(pinId) {
60
- if (typeof pinId === 'number') {
61
- return pinId;
61
+ for (const [pin,] of this.pins) {
62
+ if (pin.equals(pinId)) {
63
+ return pin;
64
+ }
62
65
  }
63
- else {
66
+ if (pinId.getType() === PinIdType.Str) {
67
+ const pinIdStringValue = pinId.getValue();
64
68
  for (const [pin, pinDef] of this.pins) {
65
- if (pinDef.name === pinId ||
66
- pinDef.altNames.indexOf(pinId) !== -1) {
69
+ if (pinDef.name === pinIdStringValue ||
70
+ pinDef.altNames.indexOf(pinIdStringValue) !== -1) {
67
71
  return pin;
68
72
  }
69
73
  }
70
- return -1;
71
74
  }
75
+ throw new RuntimeExecutionError(`Could not find pin '${pinId}' on component '${this.instanceName}'`);
72
76
  }
73
77
  getNextPinAfter(pinIndex) {
74
- if (pinIndex + 1 <= this.numPins) {
75
- return pinIndex + 1;
78
+ const pins = Array.from(this.pins.keys());
79
+ pins.sort();
80
+ const index = pins.findIndex(tmp => tmp.equals(pinIndex));
81
+ if (index + 1 < pins.length) {
82
+ return pins[index + 1];
76
83
  }
77
84
  else {
78
- return 1;
85
+ return this.getDefaultPin();
79
86
  }
80
87
  }
81
88
  setParam(key, value) {
@@ -1,4 +1,6 @@
1
1
  import { Property_key_exprContext } from '../antlr/CircuitScriptParser.js';
2
+ import { PinId } from './PinDefinition.js';
3
+ import { RuntimeExecutionError } from '../utils.js';
2
4
  export class ExecutionScope {
3
5
  scopeId;
4
6
  nets = [];
@@ -32,8 +34,11 @@ export class ExecutionScope {
32
34
  return scope;
33
35
  }
34
36
  findNet(component, pin) {
37
+ if (!(pin instanceof PinId)) {
38
+ throw new RuntimeExecutionError('Invalid value for PinId: ' + pin);
39
+ }
35
40
  return this.nets.find(([tmpComponent, tmpPin]) => {
36
- return tmpComponent.isEqual(component) && tmpPin === pin;
41
+ return tmpComponent.isEqual(component) && tmpPin.equals(pin);
37
42
  });
38
43
  }
39
44
  getNetWithName(name) {
@@ -81,8 +86,8 @@ export class ExecutionScope {
81
86
  const sortedNet = [...this.nets].sort((a, b) => {
82
87
  const netA = a[2];
83
88
  const netB = b[2];
84
- const netAId = netA.namespace + netA.name;
85
- const netBId = netB.namespace + b[2].name;
89
+ const netAId = netA.toString();
90
+ const netBId = netB.toString();
86
91
  if (netAId > netBId) {
87
92
  return 1;
88
93
  }
@@ -94,7 +99,7 @@ export class ExecutionScope {
94
99
  }
95
100
  });
96
101
  return sortedNet.map(([component, pin, net]) => {
97
- return [net.toString(), component.instanceName, pin];
102
+ return [net.toString(), component.instanceName, pin.value];
98
103
  });
99
104
  }
100
105
  printNets() {
@@ -1,3 +1,4 @@
1
+ import { NetTypes } from "./types.js";
1
2
  export class Net {
2
3
  name;
3
4
  baseName;
@@ -5,7 +6,7 @@ export class Net {
5
6
  priority;
6
7
  type;
7
8
  params = new Map();
8
- constructor(namespace, name, priority = 0, type = null) {
9
+ constructor(namespace, name, priority = 0, type = NetTypes.Any) {
9
10
  if (namespace.indexOf(' ') !== -1) {
10
11
  throw "Invalid net namespace provided";
11
12
  }