circuitscript 0.1.22 → 0.1.24

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 (57) hide show
  1. package/dist/cjs/BaseVisitor.js +35 -23
  2. package/dist/cjs/BomGeneration.js +167 -0
  3. package/dist/cjs/ComponentMatchConditions.js +116 -0
  4. package/dist/cjs/antlr/CircuitScriptLexer.js +247 -244
  5. package/dist/cjs/antlr/CircuitScriptParser.js +1503 -843
  6. package/dist/cjs/builtinMethods.js +6 -1
  7. package/dist/cjs/execute.js +27 -16
  8. package/dist/cjs/graph.js +10 -9
  9. package/dist/cjs/helpers.js +26 -6
  10. package/dist/cjs/layout.js +14 -13
  11. package/dist/cjs/main.js +17 -1
  12. package/dist/cjs/objects/ExecutionScope.js +3 -0
  13. package/dist/cjs/objects/PinDefinition.js +11 -1
  14. package/dist/cjs/objects/types.js +6 -4
  15. package/dist/cjs/rules-check/no-connect-on-connected-pin.js +81 -0
  16. package/dist/cjs/rules-check/rules.js +74 -0
  17. package/dist/cjs/rules-check/unconnected-pins.js +52 -0
  18. package/dist/cjs/visitor.js +124 -5
  19. package/dist/esm/BaseVisitor.js +35 -23
  20. package/dist/esm/BomGeneration.js +137 -0
  21. package/dist/esm/ComponentMatchConditions.js +109 -0
  22. package/dist/esm/antlr/CircuitScriptLexer.js +247 -244
  23. package/dist/esm/antlr/CircuitScriptParser.js +1498 -842
  24. package/dist/esm/antlr/CircuitScriptVisitor.js +7 -0
  25. package/dist/esm/builtinMethods.js +6 -1
  26. package/dist/esm/execute.js +27 -16
  27. package/dist/esm/graph.js +11 -10
  28. package/dist/esm/helpers.js +26 -6
  29. package/dist/esm/layout.js +15 -13
  30. package/dist/esm/main.js +17 -1
  31. package/dist/esm/objects/ExecutionScope.js +3 -0
  32. package/dist/esm/objects/PinDefinition.js +11 -1
  33. package/dist/esm/objects/types.js +7 -5
  34. package/dist/esm/rules-check/no-connect-on-connected-pin.js +77 -0
  35. package/dist/esm/rules-check/rules.js +70 -0
  36. package/dist/esm/rules-check/unconnected-pins.js +48 -0
  37. package/dist/esm/visitor.js +124 -5
  38. package/dist/libs/std.cst +7 -3
  39. package/dist/types/BomGeneration.d.ts +13 -0
  40. package/dist/types/ComponentMatchConditions.d.ts +19 -0
  41. package/dist/types/antlr/CircuitScriptLexer.d.ts +60 -59
  42. package/dist/types/antlr/CircuitScriptParser.d.ts +148 -63
  43. package/dist/types/antlr/CircuitScriptVisitor.d.ts +14 -0
  44. package/dist/types/execute.d.ts +2 -1
  45. package/dist/types/graph.d.ts +6 -1
  46. package/dist/types/helpers.d.ts +5 -2
  47. package/dist/types/layout.d.ts +3 -2
  48. package/dist/types/objects/ExecutionScope.d.ts +8 -2
  49. package/dist/types/objects/ParamDefinition.d.ts +1 -1
  50. package/dist/types/objects/PinDefinition.d.ts +1 -0
  51. package/dist/types/objects/types.d.ts +4 -2
  52. package/dist/types/rules-check/no-connect-on-connected-pin.d.ts +3 -0
  53. package/dist/types/rules-check/rules.d.ts +15 -0
  54. package/dist/types/rules-check/unconnected-pins.d.ts +2 -0
  55. package/dist/types/visitor.d.ts +10 -1
  56. package/libs/std.cst +7 -3
  57. package/package.json +2 -1
@@ -79,5 +79,12 @@ export class CircuitScriptVisitor extends AbstractParseTreeVisitor {
79
79
  visitElse_expr;
80
80
  visitWhile_expr;
81
81
  visitFor_expr;
82
+ visitPart_set_expr;
83
+ visitPart_set_key;
84
+ visitPart_match_block;
85
+ visitPart_sub_expr;
86
+ visitPart_condition_expr;
87
+ visitPart_condition_key_only_expr;
88
+ visitPart_value_expr;
82
89
  visitAnnotation_comment_expr;
83
90
  }
@@ -159,7 +159,12 @@ function toString(obj) {
159
159
  return obj.toDisplayString();
160
160
  }
161
161
  else if (obj.toString) {
162
- return obj.toString();
162
+ if (typeof obj === 'object') {
163
+ return JSON.stringify(obj);
164
+ }
165
+ else {
166
+ return obj.toString();
167
+ }
163
168
  }
164
169
  else {
165
170
  throw "Could not create string from object: " + obj;
@@ -378,9 +378,9 @@ export class ExecutionContext {
378
378
  + pinId + ' in ' + component);
379
379
  }
380
380
  this.scope.setCurrent(component, usePinId);
381
- if (!this.scope.hasNet(component, pinId)) {
381
+ if (!this.scope.hasNet(component, usePinId)) {
382
382
  const tmpNet = new Net(this.netNamespace, this.getUniqueNetName());
383
- this.scope.setNet(component, pinId, tmpNet);
383
+ this.scope.setNet(component, usePinId, tmpNet);
384
384
  }
385
385
  this.scope.clearActive();
386
386
  if (addSequence) {
@@ -502,7 +502,9 @@ export class ExecutionContext {
502
502
  const { start_point: [component, pin, wireId] } = stackRef;
503
503
  this.atComponent(component, pin, { addSequence: true });
504
504
  if (wireId !== -1) {
505
- this.scope.sequence.push([SequenceAction.WireJump, wireId, 1]);
505
+ const wireObject = this.scope.wires[wireId];
506
+ this.scope.sequence.push([SequenceAction.WireJump,
507
+ wireId, PinId.from(1), wireObject]);
506
508
  }
507
509
  }
508
510
  else if (blockType === BlockTypes.Join || blockType === BlockTypes.Parallel) {
@@ -628,7 +630,7 @@ export class ExecutionContext {
628
630
  type: isVariable ? ReferenceTypes.variable
629
631
  : ReferenceTypes.instance,
630
632
  found: (tmpReference.value !== undefined),
631
- parentValue: tmpReference.parentValue,
633
+ rootValue: tmpReference.rootValue,
632
634
  value: tmpReference.value,
633
635
  name: idName,
634
636
  trailers,
@@ -642,16 +644,19 @@ export class ExecutionContext {
642
644
  });
643
645
  }
644
646
  resolveTrailers(type, item, trailers = []) {
645
- let parentValue;
647
+ let rootValue;
646
648
  let useValue = item;
647
649
  if (trailers.length > 0) {
648
- parentValue = useValue;
650
+ rootValue = useValue;
649
651
  const trailersPath = trailers.join(".");
650
652
  if (type === ReferenceTypes.variable) {
651
- useValue = parentValue[trailersPath];
653
+ useValue = rootValue;
654
+ trailers.forEach(trailerPath => {
655
+ useValue = useValue[trailerPath];
656
+ });
652
657
  }
653
658
  else if (type === ReferenceTypes.instance) {
654
- const tmpComponent = parentValue;
659
+ const tmpComponent = rootValue;
655
660
  if (tmpComponent.typeProp === ComponentTypes.net) {
656
661
  const usedNet = this.scope.getNet(tmpComponent, new PinId(1));
657
662
  if (usedNet) {
@@ -660,20 +665,21 @@ export class ExecutionContext {
660
665
  }
661
666
  }
662
667
  else {
663
- useValue = parentValue
668
+ useValue = rootValue
664
669
  .parameters.get(trailersPath);
665
670
  }
666
671
  }
667
672
  }
668
673
  let found = false;
669
- if (parentValue !== undefined && useValue !== undefined) {
674
+ if (rootValue !== undefined && useValue !== undefined) {
670
675
  found = true;
671
676
  }
672
677
  return new AnyReference({
673
678
  found,
674
679
  type: type,
675
- parentValue,
680
+ rootValue,
676
681
  trailers,
682
+ trailerIndex: trailers.length,
677
683
  value: useValue,
678
684
  });
679
685
  }
@@ -774,13 +780,16 @@ export class ExecutionContext {
774
780
  childScope.sequence.forEach(sequenceAction => {
775
781
  const [action] = sequenceAction;
776
782
  if (action === SequenceAction.Wire) {
777
- const [, innerWireId, segments] = sequenceAction;
778
- this.scope.sequence.push([SequenceAction.Wire, wireIdOffset + innerWireId, segments]);
783
+ const [, innerWireId, segments, wire] = sequenceAction;
784
+ this.scope.sequence.push([SequenceAction.Wire, wireIdOffset + innerWireId,
785
+ segments, wire]);
779
786
  this.scope.wires.push(new Wire(segments));
780
787
  }
781
788
  else if (action === SequenceAction.WireJump) {
782
789
  const jumpWireId = wireIdOffset + sequenceAction[1];
783
- this.scope.sequence.push([SequenceAction.WireJump, jumpWireId, 1]);
790
+ const wireObject = this.scope.wires[jumpWireId];
791
+ this.scope.sequence.push([SequenceAction.WireJump, jumpWireId,
792
+ PinId.from(1), wireObject]);
784
793
  }
785
794
  else if (action === SequenceAction.At || action === SequenceAction.To) {
786
795
  this.scope.sequence.push(sequenceAction);
@@ -828,7 +837,8 @@ export class ExecutionContext {
828
837
  };
829
838
  });
830
839
  const wireId = this.scope.wires.length;
831
- this.scope.wires.push(new Wire(tmp));
840
+ const newWire = new Wire(tmp);
841
+ this.scope.wires.push(newWire);
832
842
  const output = [];
833
843
  segments.forEach(item => {
834
844
  const tmpArray = item.map(item2 => {
@@ -843,12 +853,13 @@ export class ExecutionContext {
843
853
  });
844
854
  this.log('add wire: ', output.join("|"));
845
855
  this.scope.setActive(ActiveObject.Wire, wireId);
846
- this.scope.sequence.push([SequenceAction.Wire, wireId, tmp]);
856
+ this.scope.sequence.push([SequenceAction.Wire, wireId, tmp, newWire]);
847
857
  this.scope.currentComponent.pinWires.set(this.scope.currentPin, tmp);
848
858
  if (!this.scope.currentComponent.didSetWireOrientationAngle) {
849
859
  this.applyComponentAngleFromWire(this.scope.currentComponent, this.scope.currentPin, true);
850
860
  this.scope.currentComponent.didSetWireOrientationAngle = true;
851
861
  }
862
+ return newWire;
852
863
  }
853
864
  addPoint(pointId, userDefined = true) {
854
865
  if (this.scope.instances.has(pointId)) {
package/dist/esm/graph.js CHANGED
@@ -8,7 +8,7 @@ import { Frame, FixedFrameIds, FrameParamKeys } from "./objects/Frame.js";
8
8
  import { numeric } from "./objects/ParamDefinition.js";
9
9
  import { NetTypes, TypeProps } from "./objects/types.js";
10
10
  import Matrix, { solve } from "ml-matrix";
11
- import { getPinDefinition } from "./objects/PinDefinition.js";
11
+ import { getPinDefinition, PinId } from "./objects/PinDefinition.js";
12
12
  export class NetGraph {
13
13
  logger;
14
14
  constructor(logger) {
@@ -81,8 +81,9 @@ export class NetGraph {
81
81
  break;
82
82
  }
83
83
  case SequenceAction.Wire: {
84
- const [, wireId, wireSegments] = sequenceStep;
84
+ const [, wireId, , wire] = sequenceStep;
85
85
  let useNet;
86
+ const wireSegments = wire.path;
86
87
  if (previousNode !== null) {
87
88
  const [prevNodeType, prevNodeItem] = graph.node(previousNode);
88
89
  if (prevNodeType === RenderItemType.Component) {
@@ -98,15 +99,15 @@ export class NetGraph {
98
99
  useNet = prevNodeItem.net;
99
100
  }
100
101
  }
101
- const wire = new RenderWire(useNet, numeric(0), numeric(0), wireSegments);
102
- wire.id = wireId;
103
- wire.netName = useNet.toString();
104
- const wireName = getWireName(wire.id);
105
- graph.setNode(wireName, [RenderItemType.Wire, wire, index]);
102
+ const renderWire = new RenderWire(useNet, numeric(0), numeric(0), wireSegments, wire);
103
+ renderWire.id = wireId;
104
+ renderWire.netName = useNet.toString();
105
+ const wireName = getWireName(renderWire.id);
106
+ graph.setNode(wireName, [RenderItemType.Wire, renderWire, index]);
106
107
  let tmpPreviousNode = previousNode;
107
- this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, 0, index));
108
+ this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, PinId.from(0), index));
108
109
  previousNode = wireName;
109
- previousPin = 1;
110
+ previousPin = PinId.from(1);
110
111
  const wireSegmentsInfo = wireSegments.map(item => {
111
112
  const tmp = {
112
113
  direction: item.direction,
@@ -140,7 +141,7 @@ export class NetGraph {
140
141
  wirePin = sequenceStep[2];
141
142
  }
142
143
  previousNode = wireName;
143
- previousPin = wirePin;
144
+ previousPin = PinId.from(wirePin);
144
145
  break;
145
146
  }
146
147
  case SequenceAction.Frame: {
@@ -19,6 +19,8 @@ import Big from "big.js";
19
19
  import { Logger } from "./logger.js";
20
20
  import { NetGraph } from "./graph.js";
21
21
  import { RefdesAnnotationVisitor } from "./RefdesAnnotationVisitor.js";
22
+ import { EvaluateERCRules } from "./rules-check/rules.js";
23
+ import { generateBom, generateBomCSV, saveBomOutputCsv } from "./BomGeneration.js";
22
24
  export var JSModuleType;
23
25
  (function (JSModuleType) {
24
26
  JSModuleType["CommonJs"] = "cjs";
@@ -155,7 +157,7 @@ export async function renderScript(scriptData, outputPath, options) {
155
157
  return renderScriptCustom(scriptData, outputPath, options, parseHandlers);
156
158
  }
157
159
  export async function renderScriptCustom(scriptData, outputPath, options, parseHandlers) {
158
- const { dumpNets = false, dumpData = false, showStats = false, environment, inputPath = null, updateSource = false, saveAnnotatedCopy = undefined, } = options;
160
+ const { dumpNets = false, dumpData = false, showStats = false, enableErc = false, enableBom = false, bomOutputPath = undefined, environment, inputPath = null, updateSource = false, saveAnnotatedCopy = undefined, } = options;
159
161
  const errors = [];
160
162
  const onErrorHandler = (message, context, error) => {
161
163
  if (error && error instanceof RuntimeExecutionError) {
@@ -209,10 +211,10 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
209
211
  catch (err) {
210
212
  throw new RenderError(`Error during component annotation: ${err}`, 'annotation');
211
213
  }
212
- const componentLinks = visitor.getComponentCtxLinks();
213
- const refdesVisitor = new RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
214
- await refdesVisitor.visitAsync(tree);
215
214
  if (inputPath && (updateSource || saveAnnotatedCopy !== undefined)) {
215
+ const componentLinks = visitor.getComponentCtxLinks();
216
+ const refdesVisitor = new RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
217
+ await refdesVisitor.visitAsync(tree);
216
218
  let usePath = inputPath;
217
219
  if (saveAnnotatedCopy === true) {
218
220
  const dir = path.dirname(inputPath);
@@ -223,6 +225,7 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
223
225
  else if (typeof saveAnnotatedCopy === 'string') {
224
226
  usePath = saveAnnotatedCopy;
225
227
  }
228
+ console.log('Annotations saved to ' + usePath);
226
229
  writeFileSync(usePath, refdesVisitor.getOutput());
227
230
  }
228
231
  if (dumpNets) {
@@ -238,6 +241,14 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
238
241
  if (errors.length === 0) {
239
242
  const { frameComponent } = visitor.applySheetFrameComponent();
240
243
  const { sequence, nets } = visitor.getGraph();
244
+ if (enableBom && bomOutputPath) {
245
+ const documentVariable = visitor.getScope().variables.get('document');
246
+ const bomConfig = documentVariable.bom;
247
+ const bomData = generateBom(bomConfig, visitor.getScope().getInstances());
248
+ const bomCsvOutput = generateBomCSV(bomData);
249
+ await saveBomOutputCsv(bomCsvOutput, bomOutputPath);
250
+ console.log('Generated BOM file', bomOutputPath);
251
+ }
241
252
  const tmpSequence = generateDebugSequenceAction(sequence).map(item => sequenceActionString(item));
242
253
  dumpData && writeFileSync(dumpDirectory + 'raw-sequence.txt', tmpSequence.join('\n'));
243
254
  try {
@@ -266,6 +277,15 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
266
277
  try {
267
278
  const { graph, containerFrames } = graphEngine.generateLayoutGraph(sequence, nets);
268
279
  sheetFrames = layoutEngine.runLayout(graph, containerFrames, nets);
280
+ if (enableErc) {
281
+ const ercResults = EvaluateERCRules(visitor, graph, nets);
282
+ if (ercResults.length > 0) {
283
+ console.log(`ERC found ${ercResults.length} items:`);
284
+ ercResults.forEach((item, index) => {
285
+ console.log(`${(index + 1).toString().padStart(3)}. line ${item.start.line}, column ${item.start.column}: ${item.type} - ${item.message}`);
286
+ });
287
+ }
288
+ }
269
289
  }
270
290
  catch (err) {
271
291
  throw new RenderError(`Error during layout generation: ${err}`, 'layout');
@@ -343,8 +363,8 @@ export class ParseOutputHandler {
343
363
  afterRender = false;
344
364
  }
345
365
  export class KiCadNetListOutputHandler extends ParseOutputHandler {
346
- afterRender = true;
347
- parse(visitor, outputPath, fileExtension, extra = null) {
366
+ beforeRender = true;
367
+ parse(visitor, outputPath, fileExtension) {
348
368
  if (outputPath !== null && fileExtension === "net") {
349
369
  const { tree: kiCadNetList, missingFootprints } = generateKiCadNetList(visitor.getNetList());
350
370
  missingFootprints.forEach(entry => {
@@ -51,23 +51,23 @@ export class LayoutEngine {
51
51
  const sheetFrameObjects = sheetFrames.map(sheet => {
52
52
  const items = this.flattenFrameItems(sheet);
53
53
  const components = items.filter(item => item instanceof RenderComponent);
54
- const wires = items.filter(item => item instanceof RenderWire);
54
+ const renderWires = items.filter(item => item instanceof RenderWire);
55
55
  const textObjects = items.filter(item => item instanceof RenderText);
56
56
  const frames = items.filter(item => item instanceof RenderFrame);
57
- const wireGroups = new Map();
58
- wires.forEach(wire => {
57
+ const renderWireGroups = new Map();
58
+ renderWires.forEach(wire => {
59
59
  const { netName } = wire;
60
- if (!wireGroups.has(netName)) {
61
- wireGroups.set(netName, []);
60
+ if (!renderWireGroups.has(netName)) {
61
+ renderWireGroups.set(netName, []);
62
62
  }
63
- wireGroups.get(netName).push(wire);
63
+ renderWireGroups.get(netName).push(wire);
64
64
  });
65
- const { junctions, mergedWires } = this.findJunctions(wireGroups, renderNets);
65
+ const { junctions, mergedWires } = this.findJunctions(renderWireGroups, renderNets);
66
66
  return {
67
67
  frame: sheet,
68
68
  frames,
69
69
  components,
70
- wires,
70
+ wires: renderWires,
71
71
  textObjects,
72
72
  junctions,
73
73
  mergedWires
@@ -119,12 +119,12 @@ export class LayoutEngine {
119
119
  });
120
120
  return items;
121
121
  }
122
- findJunctions(wireGroups, nets) {
122
+ findJunctions(renderWireGroups, nets) {
123
123
  const junctions = [];
124
124
  const mergedWires = [];
125
125
  const debugSegments = false;
126
- for (const [netName, wires] of wireGroups) {
127
- const allLines = wires.map(wire => {
126
+ for (const [netName, renderWires] of renderWireGroups) {
127
+ const allLines = renderWires.map(wire => {
128
128
  return wire.points.map(pt => {
129
129
  return {
130
130
  x: wire.x.add(pt.x),
@@ -843,7 +843,7 @@ export class LayoutEngine {
843
843
  item.y = fromY.sub(pinPosition.y);
844
844
  }
845
845
  else if (item instanceof RenderWire) {
846
- if (pin === 0) {
846
+ if (pin.getValue() === 0) {
847
847
  item.x = fromX;
848
848
  item.y = fromY;
849
849
  }
@@ -1017,12 +1017,14 @@ export class RenderWire extends RenderObject {
1017
1017
  points = [];
1018
1018
  netName;
1019
1019
  net;
1020
- constructor(net, x, y, segments) {
1020
+ wire;
1021
+ constructor(net, x, y, segments, wire) {
1021
1022
  super();
1022
1023
  this.net = net;
1023
1024
  this.x = x;
1024
1025
  this.y = y;
1025
1026
  this.segments = segments;
1027
+ this.wire = wire;
1026
1028
  this.refreshPoints();
1027
1029
  }
1028
1030
  refreshPoints() {
package/dist/esm/main.js CHANGED
@@ -21,7 +21,9 @@ export default async function main() {
21
21
  .option('-n, --dump-nets', 'Dump out net information')
22
22
  .option('-d, --dump-data', 'Dump data during parsing')
23
23
  .option('-s, --stats', 'Show stats during generation')
24
- .option('-x, --skip-output', 'Skip output generation');
24
+ .option('-x, --skip-output', 'Skip output generation')
25
+ .option('-e, --erc', 'Enable ERC output')
26
+ .option('-b, --bom [output-path]', 'Generate Bill of Materials in csv format');
25
27
  program.addHelpText('before', figlet.textSync('circuitscript', {
26
28
  font: 'Small Slant'
27
29
  }));
@@ -34,6 +36,9 @@ export default async function main() {
34
36
  const watchFileChanges = options.watch;
35
37
  const dumpNets = options.dumpNets;
36
38
  const dumpData = options.dumpData;
39
+ const enableErc = options.erc;
40
+ const enableBom = options.bom !== undefined;
41
+ let bomOutputPath = options.bom;
37
42
  if (options.currentDirectory) {
38
43
  throw "Parameter not supported yet";
39
44
  }
@@ -72,10 +77,21 @@ export default async function main() {
72
77
  if (options.annotatedPath !== undefined) {
73
78
  saveAnnotatedCopyPath = options.annotatedPath;
74
79
  }
80
+ if (enableBom && (bomOutputPath === true || bomOutputPath === undefined)) {
81
+ if (inputFilePath) {
82
+ bomOutputPath = inputFilePath + '.bom.csv';
83
+ }
84
+ else {
85
+ bomOutputPath = 'output.bom.csv';
86
+ }
87
+ }
75
88
  const scriptOptions = {
76
89
  dumpNets,
77
90
  dumpData,
78
91
  showStats: options.stats,
92
+ enableErc,
93
+ enableBom,
94
+ bomOutputPath,
79
95
  environment: env,
80
96
  inputPath: inputFilePath,
81
97
  updateSource,
@@ -165,6 +165,9 @@ export class ExecutionScope {
165
165
  const propertyTree = this.findPropertyKeyTree(visitor);
166
166
  lastHandler && lastHandler(propertyTree, value, valueCtx);
167
167
  }
168
+ getInstances() {
169
+ return Array.from(this.instances.values());
170
+ }
168
171
  }
169
172
  export var SequenceAction;
170
173
  (function (SequenceAction) {
@@ -28,10 +28,20 @@ export class PinId {
28
28
  }
29
29
  equals(other) {
30
30
  if (other instanceof PinId) {
31
- return this.value === other.value;
31
+ return this.value === other.value
32
+ && this.getType() === other.getType();
32
33
  }
33
34
  return this.value === other;
34
35
  }
36
+ getHashValue() {
37
+ if (this.type === PinIdType.Int) {
38
+ return 'int-' + this.value;
39
+ }
40
+ else if (this.type === PinIdType.Str) {
41
+ return 'str-' + this.value;
42
+ }
43
+ return '';
44
+ }
35
45
  static from(value) {
36
46
  if (value instanceof NumericValue) {
37
47
  return new PinId(value.toNumber());
@@ -20,9 +20,10 @@ export class AnyReference {
20
20
  found = false;
21
21
  name;
22
22
  trailers = [];
23
+ trailerIndex = -1;
23
24
  type;
24
25
  value;
25
- parentValue;
26
+ rootValue;
26
27
  referenceName = 'AnyReference';
27
28
  constructor(refType) {
28
29
  if (refType.value instanceof AnyReference
@@ -32,9 +33,10 @@ export class AnyReference {
32
33
  this.found = refType.found;
33
34
  this.name = refType.name;
34
35
  this.trailers = refType.trailers;
36
+ this.trailerIndex = refType.trailerIndex;
35
37
  this.type = refType.type ?? ReferenceTypes.unknown;
36
38
  this.value = refType.value;
37
- this.parentValue = refType.parentValue;
39
+ this.rootValue = refType.rootValue;
38
40
  }
39
41
  toString() {
40
42
  return `[${this.referenceName} name: ${this.name} trailers:${this.trailers} found: ${this.found}]`;
@@ -65,13 +67,13 @@ export class DeclaredReference extends AnyReference {
65
67
  referenceName = 'DeclaredReference';
66
68
  toDisplayString() {
67
69
  let returnValue = undefined;
68
- if (this.parentValue) {
70
+ if (this.rootValue) {
69
71
  const trailersString = this.trailers.join(".");
70
72
  if (this.type === 'instance') {
71
- returnValue = this.parentValue.parameters.get(trailersString);
73
+ returnValue = this.rootValue.parameters.get(trailersString);
72
74
  }
73
75
  else if (this.type === 'variable') {
74
- returnValue = this.parentValue[trailersString];
76
+ returnValue = this.rootValue[trailersString];
75
77
  }
76
78
  }
77
79
  else {
@@ -0,0 +1,77 @@
1
+ import { RenderItemType } from "../graph.js";
2
+ import { ERC_Rules } from "./rules.js";
3
+ export function RuleCheck_NoConnectOnConnectedPin(graph, nets) {
4
+ const allNodes = graph.nodes();
5
+ const items = [];
6
+ const netComponentPins = new Map();
7
+ const pinMapping = new Map();
8
+ const makeComponentPinHash = (instanceName, pin) => {
9
+ return instanceName + '-' + pin.getHashValue();
10
+ };
11
+ nets.forEach(item => {
12
+ const [component, pin, net] = item;
13
+ if (!netComponentPins.has(net)) {
14
+ netComponentPins.set(net, []);
15
+ }
16
+ const items = netComponentPins.get(net);
17
+ items.push([
18
+ component.instanceName,
19
+ pin
20
+ ]);
21
+ netComponentPins.set(net, items);
22
+ pinMapping.set(makeComponentPinHash(component.instanceName, pin), net);
23
+ });
24
+ allNodes.forEach(node => {
25
+ const nodeInfo = graph.node(node);
26
+ if (nodeInfo[0] === RenderItemType.Component) {
27
+ const { component } = nodeInfo[1];
28
+ if (component.hasParam('no_connect')) {
29
+ const instanceName = component.instanceName;
30
+ const edges = graph.nodeEdges(node);
31
+ const otherNodes = [];
32
+ edges.forEach(edge => {
33
+ const edgeInfo = graph.edge(edge.v, edge.w);
34
+ let targetComponentName;
35
+ let targetPin;
36
+ if (edge.v === instanceName) {
37
+ otherNodes.push(edge.w);
38
+ targetComponentName = edge.w;
39
+ targetPin = edgeInfo[3];
40
+ }
41
+ else {
42
+ targetComponentName = edge.v;
43
+ targetPin = edgeInfo[1];
44
+ }
45
+ const componentPinHash = makeComponentPinHash(targetComponentName, targetPin);
46
+ if (pinMapping.has(componentPinHash)) {
47
+ const net = pinMapping.get(componentPinHash);
48
+ const tmpNetComponentPins = netComponentPins.get(net);
49
+ const remainingItems = tmpNetComponentPins.filter(item => {
50
+ if (item[0] === instanceName) {
51
+ return false;
52
+ }
53
+ else if (item[0] === targetComponentName
54
+ && item[1].getHashValue() === targetPin.getHashValue()) {
55
+ return false;
56
+ }
57
+ return true;
58
+ });
59
+ if (remainingItems.length > 0) {
60
+ const targetInfo = graph.node(targetComponentName);
61
+ const tmpComponent = targetInfo[1];
62
+ items.push({
63
+ type: ERC_Rules.NoConnectOnConnectedPin,
64
+ instance: component,
65
+ target: {
66
+ instance: tmpComponent.component,
67
+ pin: targetPin
68
+ }
69
+ });
70
+ }
71
+ }
72
+ });
73
+ }
74
+ }
75
+ });
76
+ return items;
77
+ }
@@ -0,0 +1,70 @@
1
+ import { RuleCheck_UnconnectedPinsWires } from "./unconnected-pins.js";
2
+ import { RuleCheck_NoConnectOnConnectedPin } from "./no-connect-on-connected-pin.js";
3
+ export var ERC_Rules;
4
+ (function (ERC_Rules) {
5
+ ERC_Rules["UnconnectedPin"] = "UNCONNECTED-PIN";
6
+ ERC_Rules["UnconnectedWire"] = "UNCONNECTED-WIRE";
7
+ ERC_Rules["NoConnectOnConnectedPin"] = "NO-CONNECT-ON-CONNECTED-PIN";
8
+ })(ERC_Rules || (ERC_Rules = {}));
9
+ export function EvaluateERCRules(visitor, graph, nets) {
10
+ const ruleCheckItems = [];
11
+ const creationCtx = visitor.creationCtx;
12
+ ruleCheckItems.push(...RuleCheck_UnconnectedPinsWires(graph), ...RuleCheck_NoConnectOnConnectedPin(graph, nets));
13
+ const reportItems = [];
14
+ ruleCheckItems.forEach(item => {
15
+ const { type } = item;
16
+ switch (type) {
17
+ case ERC_Rules.UnconnectedPin:
18
+ {
19
+ const instance = item.instance;
20
+ const token = getComponentFirstCtxToken(instance);
21
+ if (token) {
22
+ reportItems.push({
23
+ type,
24
+ start: token,
25
+ message: `Unconnected pin ${item.pin} for component`
26
+ });
27
+ }
28
+ }
29
+ break;
30
+ case ERC_Rules.UnconnectedWire:
31
+ {
32
+ const wire = item.wire;
33
+ if (creationCtx.has(wire)) {
34
+ const tmpCtx = creationCtx.get(wire);
35
+ const startToken = tmpCtx.start;
36
+ reportItems.push({
37
+ type,
38
+ start: startToken,
39
+ message: `Unconnected wire end`
40
+ });
41
+ }
42
+ }
43
+ break;
44
+ case ERC_Rules.NoConnectOnConnectedPin:
45
+ {
46
+ const instance = item.instance;
47
+ const token = getComponentFirstCtxToken(instance);
48
+ if (token) {
49
+ reportItems.push({
50
+ type,
51
+ start: token,
52
+ message: `No connect on connected pin`
53
+ });
54
+ }
55
+ }
56
+ break;
57
+ }
58
+ });
59
+ const sortedReport = reportItems.toSorted((a, b) => {
60
+ return a.start.start - b.start.start;
61
+ });
62
+ return sortedReport;
63
+ }
64
+ function getComponentFirstCtxToken(instance) {
65
+ if (instance.ctxReferences.length > 0) {
66
+ const { ctx } = instance.ctxReferences[0];
67
+ return ctx.start;
68
+ }
69
+ return null;
70
+ }