circuitscript 0.0.17 → 0.0.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.
@@ -93,10 +93,15 @@ export abstract class SymbolGraphic {
93
93
  pinPosition(id: number): { x: number; y: number; angle: number; } {
94
94
  const pin = this.drawing.getPinPosition(id);
95
95
 
96
+ // Allow pin position values to be rounded to 4 d.p
97
+ const [x, y] = pin.start;
98
+ const useX = Math.round(x * 10000) / 10000;
99
+ const useY = Math.round(y * 10000 / 10000);
100
+
96
101
  if (pin) {
97
102
  return {
98
- x: pin.start[0],
99
- y: pin.start[1],
103
+ x: useX,
104
+ y: useY,
100
105
  angle: pin.angle,
101
106
  }
102
107
  }
package/src/execute.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentTypes, GlobalNames, ParamKeys, ReferenceTypes } from './globals.js';
1
+ import { BranchType, ComponentTypes, GlobalNames, NoNetText, ParamKeys, ReferenceTypes } from './globals.js';
2
2
  import { ClassComponent } from './objects/ClassComponent.js';
3
3
  import { ActiveObject, ExecutionScope, FrameAction, SequenceAction } from './objects/ExecutionScope.js';
4
4
  import { Net } from './objects/Net.js';
@@ -26,6 +26,8 @@ export class ExecutionContext {
26
26
 
27
27
  scope: ExecutionScope;
28
28
 
29
+ joinPointId = 0;
30
+
29
31
  resolveNet: (name: string, netNamespace:string) => ({
30
32
  found: boolean, net?: Net
31
33
  }) = null;
@@ -316,12 +318,22 @@ export class ExecutionContext {
316
318
  return component;
317
319
  }
318
320
 
319
- printPoint(): void {
321
+ printPoint(extra = ''): void {
322
+ let netName = NoNetText;
323
+ if (this.scope.hasNet(
324
+ this.scope.currentComponent,
325
+ this.scope.currentPin
326
+ )) {
327
+ netName = this.scope
328
+ .getNet(this.scope.currentComponent, this.scope.currentPin)
329
+ .toString();
330
+ }
331
+
320
332
  this.print(
321
- 'point: ' +
322
- this.scope.currentComponent.instanceName +
323
- ' ' +
324
- this.scope.currentPin,
333
+ (extra !== '' ? (extra + ' ') : '') + 'point: ' +
334
+ this.scope.currentComponent.instanceName +
335
+ ' ' +
336
+ this.scope.currentPin + ' ' + netName
325
337
  );
326
338
  }
327
339
 
@@ -524,116 +536,125 @@ export class ExecutionContext {
524
536
  return clonedComponent;
525
537
  }
526
538
 
527
- enterBranches(): void {
539
+ enterBranches(branchType: BranchType): void {
540
+ // Create object to track all the inner branches of
541
+ // the branch group
542
+
528
543
  this.scope.branchStack.set(this.scope.indentLevel, {
529
544
  // Tracks the position when the branch is entered
530
- entered_at: [this.scope.currentComponent, this.scope.currentPin, this.scope.currentWireId],
545
+ entered_at: [
546
+ this.scope.currentComponent,
547
+ this.scope.currentPin,
548
+ this.scope.currentWireId],
531
549
  inner_branches: new Map<number, any>(),
532
550
  current_index: null,
551
+ type: branchType,
533
552
  });
534
553
 
535
554
  this.print('enter branches');
536
555
  }
537
556
 
538
557
  exitBranches(): void {
539
- false && this.joinBranches();
540
-
541
- this.print('exit branches');
542
- }
543
-
544
- joinBranches(): void {
545
- // When exiting/leaving a group of branches
546
- const innerBranches = this.scope.branchStack.get(
558
+ const stackRef = this.scope.branchStack.get(
547
559
  this.scope.indentLevel,
548
- )['inner_branches'];
549
-
550
- const lastNets: [number, [ClassComponent, number, Net]][] = [];
560
+ );
551
561
 
552
- // Gather all the last nets that should be joined together
553
- for (const [key, value] of innerBranches) {
554
- if (value['ignore_last_net'] === false) {
555
- const [component, pin] = value['last_net'];
562
+ const { type: branchType } = stackRef;
563
+ if (branchType === BranchType.Join) {
564
+ // Move to the end location of the first branch
565
+ const { join_final_point: finalPoint } = stackRef;
566
+ const [component, pin, wireId] = finalPoint;
556
567
 
557
- let netPriority = 0;
558
- if (this.scope.hasNet(component, pin)) {
559
- netPriority = this.scope.getNet(component, pin).priority;
560
- }
568
+ this.scope.currentComponent = component;
569
+ this.scope.currentPin = pin;
570
+ this.scope.currentWireId = wireId;
561
571
 
562
- lastNets.push([netPriority, value['last_net']]);
572
+ if (wireId !== -1) {
573
+ this.scope.sequence.push([
574
+ SequenceAction.WireJump, wireId, 1
575
+ ]);
563
576
  }
564
577
  }
565
578
 
566
- if (lastNets.length > 0) {
567
- // Items in the lastNets list might not have an actual net created/defined yet
568
-
569
- // Sort the nets so that the net with the highest priority is first
570
- const sortedNets = lastNets.sort((a, b) => {
571
- if (a[0] > b[0]) {
572
- return -1;
573
- } else if (a[0] < b[0]) {
574
- return 1;
575
- } else {
576
- return 0;
577
- }
578
- });
579
-
580
- // Not always a good idea to always use the first item for combining...
581
- const [comp1, pin1] = sortedNets[0][1];
582
-
583
- const tmpList = sortedNets.slice(1);
584
- tmpList.forEach((item) => {
585
- const [, [comp2, pin2]] = item;
586
-
587
- this.atComponent(comp1, pin1, {addSequence: true});
588
- this.toComponent(comp2, pin2, {addSequence: true});
589
- });
590
-
591
- this.scope.currentComponent = comp1;
592
- this.scope.currentPin = pin1;
593
- }
579
+ this.print('exit branches');
594
580
  }
595
581
 
596
582
  enterBranch(branchIndex: number): void {
597
- this.print('enter inner branch >>>');
598
-
599
583
  // Current net before any branching is already stored in enterBranches()
600
584
  const stackRef = this.scope.branchStack.get(this.scope.indentLevel);
601
-
602
585
  stackRef['branch_index'] = branchIndex;
603
586
 
587
+ const { type: branchType } = stackRef;
588
+
604
589
  // Setup the state for the inner branch at the given index
605
590
  stackRef['inner_branches'].set(branchIndex, {
606
591
  last_net: null,
607
592
  ignore_last_net: false,
608
593
  });
609
594
 
595
+ if (branchType === BranchType.Join) {
596
+ // Clear current component, pin, wire before entering the branch
597
+ this.scope.currentComponent = null;
598
+ this.scope.currentPin = null;
599
+ this.scope.currentWireId = -1;
600
+ }
601
+
602
+ this.print(`enter inner branch of type (${branchType}) >>>`);
603
+
610
604
  this.scope.indentLevel += 1;
611
605
  }
612
606
 
613
607
  exitBranch(branchIndex: number): void {
614
608
  const stackRef = this.scope.branchStack.get(this.scope.indentLevel - 1);
615
-
609
+ const { type: branchType } = stackRef;
616
610
  // Save the last net reference
617
611
  const branchIndexRef = stackRef['inner_branches'].get(branchIndex);
618
612
  branchIndexRef['last_net'] = [
619
613
  this.scope.currentComponent,
620
614
  this.scope.currentPin,
615
+ this.scope.currentWireId
621
616
  ];
622
617
 
623
618
  stackRef['branch_index'] = null;
624
619
 
625
620
  // Restore the latest entry in the branch stack
626
- const [preBranchComponent, preBranchPin, preBranchWireId] = stackRef['entered_at'];
621
+ const [preBranchComponent, preBranchPin, preBranchWireId] =
622
+ stackRef['entered_at'];
627
623
 
628
624
  this.scope.indentLevel -= 1;
629
625
 
630
626
  this.print('exit inner branch <<<');
631
627
 
632
- // Do not duplicate any net symbol since this is a branch
633
- this.atComponent(preBranchComponent, preBranchPin, {addSequence: true});
628
+ if (branchType === BranchType.Branch) {
629
+ // Do not duplicate any net symbol since this is a branch
630
+ this.atComponent(preBranchComponent, preBranchPin, { addSequence: true });
631
+
632
+ if (preBranchWireId !== -1) {
633
+ // If previous node is a wire, then jump to END of wire
634
+ this.scope.sequence.push([SequenceAction.WireJump, preBranchWireId, 1]);
635
+ }
636
+ } else if (branchType === BranchType.Join) {
637
+ if (branchIndex === 0) {
638
+ // First join branch will determine the final join location
634
639
 
635
- if (preBranchWireId !== -1){
636
- this.scope.sequence.push([SequenceAction.WireJump, preBranchWireId]);
640
+ // Add point to current location
641
+ this.addPoint(`_join.${this.name}.${this.joinPointId}`, false);
642
+
643
+ this.joinPointId += 1;
644
+
645
+ stackRef['join_final_point'] = [
646
+ this.scope.currentComponent,
647
+ this.scope.currentPin,
648
+ this.scope.currentWireId
649
+ ];
650
+
651
+ } else {
652
+ const { join_final_point: finalPoint } = stackRef;
653
+ const [joinComponent, joinPin, joinWireId] = finalPoint;
654
+
655
+ // Link the current component to the join component and join pin
656
+ this.toComponent(joinComponent, joinPin, { addSequence: true });
657
+ }
637
658
  }
638
659
  }
639
660
 
@@ -748,7 +769,7 @@ export class ExecutionContext {
748
769
  { netNamespace });
749
770
 
750
771
  this.print(`done call function '${functionName}'`);
751
-
772
+
752
773
  return functionResult;
753
774
  } else {
754
775
  throw `Invalid function '${functionName}'`;
@@ -855,7 +876,7 @@ export class ExecutionContext {
855
876
  // Wire IDs in wire jumps need to be updated.
856
877
  const jumpWireId = wireIdOffset + sequenceAction[1];
857
878
  this.scope.sequence.push(
858
- [SequenceAction.WireJump, jumpWireId]
879
+ [SequenceAction.WireJump, jumpWireId, 1]
859
880
  );
860
881
  } else if (action === SequenceAction.At || action === SequenceAction.To) {
861
882
  const tmpComponent: ClassComponent = sequenceAction[1];
@@ -895,9 +916,24 @@ export class ExecutionContext {
895
916
  }
896
917
  });
897
918
 
898
- this.scope.currentComponent = currentComponent;
899
- this.scope.currentPin = currentPin;
919
+ if (childScope.currentComponent === childScope.componentRoot) {
920
+ // If child scope is current at the root node, then use the
921
+ // location in the parent scope as the current component
922
+ // since that would be equivalent
923
+ this.scope.currentComponent = currentComponent;
924
+ this.scope.currentPin = currentPin;
925
+ this.scope.currentWireId = currentWireId;
900
926
 
927
+ } else {
928
+ // Otherwise move the current scope to the current node within
929
+ // the child scope
930
+ this.scope.currentComponent = childScope.currentComponent;
931
+ this.scope.currentPin = childScope.currentPin;
932
+ this.scope.currentWireId = childScope.currentWireId + wireIdOffset;
933
+ }
934
+
935
+ this.printPoint('resume at');
936
+
901
937
  this.print('-- nets --');
902
938
 
903
939
  // dump the list of nets in the current scope
@@ -947,17 +983,18 @@ export class ExecutionContext {
947
983
  )
948
984
  }
949
985
 
950
- addPoint(pointId: string): ComponentPin {
986
+ addPoint(pointId: string, userDefined = true): ComponentPin {
951
987
  if (this.scope.instances.has(pointId)) {
952
988
  this.print('Warning: ' + pointId + ' is being redefined');
953
989
  }
954
990
 
955
- const componentPoint = ClassComponent.simple("point." + pointId, 1, "point");
991
+ const useName = userDefined ? 'point.' + pointId : pointId;
992
+ const componentPoint = ClassComponent.simple(useName, 1, "point");
956
993
  componentPoint.displayProp = "point";
957
994
  componentPoint.typeProp = ComponentTypes.point;
958
995
 
959
996
  this.scope.instances.set(pointId, componentPoint);
960
- this.toComponent(componentPoint, 1, {addSequence: true});
997
+ this.toComponent(componentPoint, 1, { addSequence: true });
961
998
 
962
999
  return this.getCurrentPoint();
963
1000
  }
package/src/export.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentTypes } from "./globals.js";
1
+ import { ComponentTypes, NoNetText } from "./globals.js";
2
2
  import { NumericValue } from "./objects/ParamDefinition.js";
3
3
  import { NetListItem } from "./visitor.js";
4
4
 
@@ -39,7 +39,7 @@ export function generateKiCADNetList(netlist: NetListItem[]): string {
39
39
  const netInfo = pins[key];
40
40
  const netName = netInfo.netName;
41
41
 
42
- if (netName === 'NO_NET'){
42
+ if (netName === NoNetText){
43
43
  continue;
44
44
  }
45
45
 
package/src/globals.ts CHANGED
@@ -9,6 +9,7 @@ export enum GlobalNames {
9
9
  symbol = 'symbol',
10
10
  }
11
11
 
12
+ export const NoNetText = 'NO_NET';
12
13
 
13
14
  export enum ParamKeys {
14
15
 
@@ -56,4 +57,9 @@ export enum ReferenceTypes {
56
57
  value = 'value',
57
58
  variable = 'variable',
58
59
  instance = 'instance',
60
+ }
61
+
62
+ export enum BranchType {
63
+ Branch = 1,
64
+ Join = 2,
59
65
  }
package/src/layout.ts CHANGED
@@ -121,12 +121,29 @@ export class LayoutEngine {
121
121
  wireGroups.get(netName).push(wire);
122
122
  });
123
123
 
124
+ const { junctions, mergedWires } = this.findJunctions(wireGroups);
125
+
126
+ return {
127
+ components: placedComponents,
128
+ wires: placedWires,
129
+ mergedWires,
130
+ junctions,
131
+
132
+ frameObjects,
133
+ textObjects,
134
+ };
135
+ }
136
+
137
+ findJunctions(wireGroups: Map<string, RenderWire[]>): {
138
+ junctions: RenderJunction[],
139
+ mergedWires: MergedWire[],
140
+ } {
124
141
  const junctions: RenderJunction[] = [];
125
-
126
- const mergedWires:MergedWire[] = [];
127
-
142
+
143
+ const mergedWires: MergedWire[] = [];
144
+
128
145
  for (const [key, wires] of wireGroups) {
129
-
146
+
130
147
  // Create array of all wires with the same net name
131
148
  const allLines = wires.map(wire => {
132
149
  return wire.points.map(pt => {
@@ -136,28 +153,23 @@ export class LayoutEngine {
136
153
  }
137
154
  });
138
155
  });
139
-
156
+
140
157
  const { intersectPoints, segments } = Geometry.mergeWires(allLines);
141
158
  mergedWires.push({
142
159
  netName: key,
143
160
  segments,
144
161
  intersectPoints,
145
162
  });
146
-
163
+
147
164
  intersectPoints.forEach(([x, y]) => {
148
165
  junctions.push(new RenderJunction(x, y));
149
166
  });
150
167
  }
151
168
 
152
169
  return {
153
- components: placedComponents,
154
- wires: placedWires,
155
- mergedWires,
156
170
  junctions,
157
-
158
- frameObjects,
159
- textObjects,
160
- };
171
+ mergedWires
172
+ }
161
173
  }
162
174
 
163
175
  placeFrames(graph: graphlib.Graph, subgraphInfo: SubGraphInfo[],
@@ -635,7 +647,7 @@ export class LayoutEngine {
635
647
  }
636
648
 
637
649
  if (action === SequenceAction.To) {
638
- graph.setEdge(previousNode, tmpInstanceName,
650
+ this.setGraphEdge(graph, previousNode, tmpInstanceName,
639
651
  makeEdgeValue(previousNode, previousPin, tmpInstanceName, pin, i));
640
652
  }
641
653
 
@@ -649,9 +661,8 @@ export class LayoutEngine {
649
661
 
650
662
  const wire = new RenderWire(0, 0, wireSegments);
651
663
  wire.id = wireId;
652
-
653
664
  let useNetName = null;
654
-
665
+
655
666
  if (previousNode !== null) {
656
667
  const [prevNodeType, prevNodeItem] = graph.node(previousNode);
657
668
  if (prevNodeType === RenderItemType.Component) {
@@ -674,9 +685,9 @@ export class LayoutEngine {
674
685
  graph.setNode(wireName, [RenderItemType.Wire, wire, i]);
675
686
 
676
687
  // Connect previous node to pin:0 of the wire
677
- graph.setEdge(previousNode, wireName,
688
+ this.setGraphEdge(graph, previousNode, wireName,
678
689
  makeEdgeValue(previousNode, previousPin, wireName, 0, i));
679
-
690
+
680
691
  previousNode = wireName;
681
692
  previousPin = 1;
682
693
 
@@ -707,10 +718,17 @@ export class LayoutEngine {
707
718
 
708
719
  } else if (action === SequenceAction.WireJump) {
709
720
  this.print(...sequence[i]);
710
- const [, wireId] = sequence[i] as [SequenceAction.WireJump, number];
711
- previousNode = getWireName(wireId);
712
- previousPin = 1;
721
+ const wireId = sequence[i][1] as number;
722
+ const wireName = getWireName(wireId);
723
+
724
+ let wirePin = 1;
713
725
 
726
+ if (sequence[i].length === 3) {
727
+ wirePin = sequence[i][2] as number;
728
+ }
729
+
730
+ previousNode = wireName;
731
+ previousPin = wirePin;
714
732
  } else if (action === SequenceAction.Frame){
715
733
  const [, frameObject, frameAction] = sequence[i];
716
734
 
@@ -754,6 +772,11 @@ export class LayoutEngine {
754
772
  }
755
773
  }
756
774
 
775
+ setGraphEdge(graph: graphlib.Graph, node1: string, node2: string,
776
+ edgeValue: EdgeValue): void {
777
+ graph.setEdge(node1, node2, edgeValue);
778
+ }
779
+
757
780
  sizeSubGraphs(graph: graphlib.Graph): SubGraphInfo[] {
758
781
 
759
782
  // Layouts out all nodes within a subgraph and determines the size
@@ -966,13 +989,11 @@ export class LayoutEngine {
966
989
  const [x1, y1] = getNodePositionAtPin(node1, pin1);
967
990
  const [x2, y2] = getNodePositionAtPin(node2, pin2);
968
991
  if (x1 !== x2 && y1 !== y2) {
969
-
970
992
  if (node1 instanceof RenderWire &&
971
993
  node2 instanceof RenderComponent) {
972
994
 
973
- this.layoutWarnings.push('component ' +
974
- node2.component.instanceName +
975
- ' may not be placed correctly');
995
+ const refdes = node2.component.assignedRefDes;
996
+ this.layoutWarnings.push(`component ${refdes} may not be placed correctly`);
976
997
  }
977
998
  }
978
999
  }
@@ -1189,10 +1210,10 @@ export class LayoutEngine {
1189
1210
  item.y = fromY - pinPosition.y;
1190
1211
 
1191
1212
  } else if (item instanceof RenderWire){
1192
- if (pin === 0){
1213
+ if (pin === 0) { // Start of the wire
1193
1214
  item.x = fromX;
1194
1215
  item.y = fromY;
1195
- } else {
1216
+ } else { // End of wire
1196
1217
  const wireEnd = item.getWireEnd();
1197
1218
  item.x = fromX - wireEnd.x;
1198
1219
  item.y = fromY - wireEnd.y;
@@ -1281,8 +1302,12 @@ function getNeighbours(graph: graphlib.Graph, nodeIds: string[]): [from: string,
1281
1302
  }, [] as [from: string, to: string][]);
1282
1303
  }
1283
1304
 
1284
- function makeEdgeValue(instanceName1: string, instancePin1: number, instanceName2: string, instancePin2: number, priority: number):
1285
- [instance1: string, instancePin1: number, instance2: string, instancePin2: number, priority: number] {
1305
+ type EdgeValue = [instance1: string, instancePin1: number,
1306
+ instance2: string, instancePin2: number, priority: number];
1307
+
1308
+ function makeEdgeValue(instanceName1: string, instancePin1: number,
1309
+ instanceName2: string, instancePin2: number, priority: number)
1310
+ : EdgeValue {
1286
1311
  return [instanceName1, instancePin1, instanceName2, instancePin2, priority];
1287
1312
  // return `${instanceName1}:pin:${instancePin1} -- ${instanceName2}:pin:${instancePin2}`;
1288
1313
  }
@@ -165,12 +165,20 @@ export class ExecutionScope {
165
165
  }
166
166
 
167
167
  export enum SequenceAction {
168
+ // Link current insertion point to component pin
168
169
  To = 'to',
170
+
171
+ // Move insertion point at component pin
169
172
  At = 'at',
173
+
174
+ // Link current insertion point with wire of given segments
170
175
  Wire = 'wire',
171
176
 
177
+ // Jump to wire with target ID. Pin 0 of wire is the start of the
178
+ // wire, pin 1 is the other end of the wire.
172
179
  WireJump = 'wire-jump',
173
180
 
181
+ // Creates a new frame group
174
182
  Frame = 'frame',
175
183
  }
176
184
 
@@ -187,7 +195,7 @@ export enum ActiveObject {
187
195
 
188
196
  export type SequenceItem =
189
197
  [SequenceAction.To | SequenceAction.At, ClassComponent, number, LayoutDirection?, string?]
190
- | [SequenceAction.Wire, number, WireSegment[]]
191
- | [SequenceAction.WireJump, number]
198
+ | [SequenceAction.Wire, wireId: number, WireSegment[]]
199
+ | [SequenceAction.WireJump, wireId: number, pinId: number]
192
200
  | [SequenceAction.Frame, Frame, "enter" | "exit"]
193
201
  ;
package/src/visitor.ts CHANGED
@@ -62,7 +62,7 @@ import { ExecutionScope } from './objects/ExecutionScope.js';
62
62
  import { CFunction, CFunctionOptions, CallableParameter, ComplexType, ComponentPin,
63
63
  ComponentPinNet, FunctionDefinedParameter, ReferenceType, UndeclaredReference, ValueType } from './objects/types.js';
64
64
  import { Logger } from './logger.js';
65
- import { ComponentTypes } from './globals.js';
65
+ import { BranchType, ComponentTypes, NoNetText } from './globals.js';
66
66
  import { Net } from './objects/Net.js';
67
67
  import { SubExpressionCommand, SymbolDrawingCommands } from './draw_symbols.js';
68
68
  import { parseFileWithVisitor } from './parser.js';
@@ -353,9 +353,20 @@ export class MainVisitor extends ParseTreeVisitor<any> {
353
353
  }
354
354
 
355
355
  visitBranch_blocks(ctx: Branch_blocksContext): ComponentPin {
356
- this.getExecutor().enterBranches();
357
-
358
356
  const branches = ctx.branch_block_inner_list();
357
+ let branchType = BranchType.Branch;
358
+
359
+ if (branches.length > 0){
360
+ const firstBranch = branches[0];
361
+ if (firstBranch.Branch()){
362
+ branchType = BranchType.Branch
363
+ } else if (firstBranch.Join()){
364
+ branchType = BranchType.Join;
365
+ }
366
+ }
367
+
368
+ this.getExecutor().enterBranches(branchType);
369
+
359
370
  branches.forEach((branch, index) => {
360
371
  this.getExecutor().enterBranch(index);
361
372
 
@@ -733,7 +744,7 @@ export class MainVisitor extends ParseTreeVisitor<any> {
733
744
 
734
745
  // Function execution is completed, get the last executor
735
746
  const lastExecution = executionStack.pop();
736
-
747
+
737
748
  // Merge what ever was created in the scope with the outer scope
738
749
  const nextLastExecution = executionStack[executionStack.length - 1];
739
750
  nextLastExecution.mergeScope(
@@ -1396,8 +1407,8 @@ export class MainVisitor extends ParseTreeVisitor<any> {
1396
1407
  const result = [];
1397
1408
 
1398
1409
  for (const [pinId, pin] of instance.pins) {
1399
- let netName = 'NO_NET';
1400
- let netBaseName = 'NO_NET';
1410
+ let netName = NoNetText;
1411
+ let netBaseName = NoNetText;
1401
1412
 
1402
1413
  if (scope.hasNet(instance, pinId)) {
1403
1414
  const netObject = scope.getNet(instance, pinId);