circuitscript 0.0.22 → 0.0.25
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 +487 -0
- package/dist/cjs/SemanticTokenVisitor.js +218 -0
- package/dist/cjs/SymbolValidatorVisitor.js +233 -0
- package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
- package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
- package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
- package/dist/cjs/draw_symbols.js +819 -0
- package/dist/cjs/execute.js +778 -0
- package/{src/export.ts → dist/cjs/export.js} +34 -56
- package/dist/cjs/fonts.js +4 -0
- package/dist/cjs/geometry.js +450 -0
- package/dist/cjs/globals.js +60 -0
- package/dist/cjs/helpers.js +269 -0
- package/dist/cjs/index.js +31 -0
- package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
- package/dist/cjs/lexer.js +111 -0
- package/dist/cjs/logger.js +17 -0
- package/dist/cjs/main.js +82 -0
- package/dist/cjs/objects/ClassComponent.js +145 -0
- package/dist/cjs/objects/ExecutionScope.js +135 -0
- package/dist/cjs/objects/Frame.js +22 -0
- package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
- package/dist/cjs/objects/ParamDefinition.js +42 -0
- package/dist/cjs/objects/PinDefinition.js +31 -0
- package/dist/cjs/objects/PinTypes.js +11 -0
- package/dist/cjs/objects/Wire.js +9 -0
- package/dist/cjs/objects/types.js +15 -0
- package/dist/cjs/parser.js +70 -0
- package/dist/cjs/regenerate-tests.js +23 -0
- package/dist/cjs/render.js +155 -0
- package/{src/server.ts → dist/cjs/server.js} +15 -21
- package/dist/cjs/sizing.js +105 -0
- package/{src/utils.ts → dist/cjs/utils.js} +25 -35
- package/dist/cjs/validate.js +81 -0
- package/dist/cjs/visitor.js +844 -0
- package/dist/esm/BaseVisitor.mjs +488 -0
- package/dist/esm/SemanticTokenVisitor.mjs +215 -0
- package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
- package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
- package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
- package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
- package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
- package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
- package/{build/src/export.js → dist/esm/export.mjs} +2 -2
- package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
- package/dist/esm/helpers.mjs +252 -0
- package/dist/esm/index.mjs +15 -0
- package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
- package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
- package/{build/src/main.js → dist/esm/main.mjs} +9 -14
- package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
- package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
- package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
- package/dist/esm/objects/types.mjs +12 -0
- package/dist/esm/parser.mjs +64 -0
- package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
- package/{build/src/render.js → dist/esm/render.mjs} +7 -24
- package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
- package/{src/main.ts → dist/esm/validate.mjs} +31 -62
- package/dist/esm/visitor.mjs +838 -0
- package/dist/types/BaseVisitor.d.ts +69 -0
- package/dist/types/SemanticTokenVisitor.d.ts +36 -0
- package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
- package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
- package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
- package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
- package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
- package/{build/src → dist/types}/execute.d.ts +6 -9
- package/{build/src → dist/types}/geometry.d.ts +5 -1
- package/dist/types/helpers.d.ts +40 -0
- package/dist/types/index.d.ts +15 -0
- package/{build/src → dist/types}/layout.d.ts +10 -10
- package/{build/src → dist/types}/lexer.d.ts +2 -2
- package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
- package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
- package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
- package/{build/src → dist/types}/objects/types.d.ts +5 -0
- package/dist/types/parser.d.ts +25 -0
- package/{build/src → dist/types}/render.d.ts +1 -1
- package/{build/src → dist/types}/sizing.d.ts +3 -1
- package/dist/types/validate.d.ts +2 -0
- package/dist/types/visitor.d.ts +80 -0
- package/libs/lib.cst +0 -2
- package/package.json +38 -15
- package/.editorconfig +0 -15
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -27
- package/.gitlab-ci.yml +0 -81
- package/.prettierignore +0 -8
- package/.prettierrc +0 -16
- package/__tests__/expectedResults.ts +0 -657
- package/__tests__/helpers.ts +0 -82
- package/__tests__/parseScripts.ts +0 -593
- package/__tests__/renderData/script1.cst +0 -58
- package/__tests__/renderData/script1.cst.svg +0 -1
- package/__tests__/renderData/script2.cst +0 -16
- package/__tests__/renderData/script2.cst.svg +0 -1
- package/__tests__/renderData/script3.cst +0 -30
- package/__tests__/renderData/script3.cst.svg +0 -1
- package/__tests__/renderData/script4.cst +0 -54
- package/__tests__/renderData/script4.cst.svg +0 -1
- package/__tests__/renderData/script5.cst +0 -23
- package/__tests__/renderData/script5.cst.svg +0 -1
- package/__tests__/renderData/script6.cst +0 -28
- package/__tests__/renderData/script6.cst.svg +0 -1
- package/__tests__/renderData/script7.cst +0 -26
- package/__tests__/renderData/script7.cst.svg +0 -1
- package/__tests__/renderData/script8.cst +0 -37
- package/__tests__/renderData/script8.cst.svg +0 -1
- package/__tests__/testCLI.ts +0 -68
- package/__tests__/testMathOps.ts +0 -36
- package/__tests__/testMergeWires.ts +0 -141
- package/__tests__/testParse.ts +0 -263
- package/__tests__/testRender.ts +0 -38
- package/build/src/antlr/CircuitScriptLexer.js +0 -287
- package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
- package/build/src/antlr/CircuitScriptParser.js +0 -4841
- package/build/src/helpers.d.ts +0 -1
- package/build/src/helpers.js +0 -73
- package/build/src/objects/types.js +0 -6
- package/build/src/parser.js +0 -69
- package/build/src/visitor.d.ts +0 -133
- package/build/src/visitor.js +0 -1154
- package/documentation.md +0 -238
- package/examples/example_arduino_uno.cst +0 -1146
- package/examples/example_garden_pump.cst +0 -567
- package/examples/lib.cst +0 -185
- package/jest.config.js +0 -23
- package/refresh.html +0 -42
- package/server.cjs +0 -50
- package/src/antlr/CircuitScript.g4 +0 -209
- package/src/antlr/CircuitScriptLexer.ts +0 -317
- package/src/antlr/CircuitScriptParser.ts +0 -4979
- package/src/antlr/CircuitScriptVisitor.ts +0 -420
- package/src/draw_symbols.ts +0 -1085
- package/src/execute.ts +0 -1227
- package/src/fonts.ts +0 -1
- package/src/geometry.ts +0 -638
- package/src/globals.ts +0 -67
- package/src/helpers.ts +0 -114
- package/src/lexer.ts +0 -151
- package/src/logger.ts +0 -17
- package/src/objects/ClassComponent.ts +0 -223
- package/src/objects/ExecutionScope.ts +0 -201
- package/src/objects/Frame.ts +0 -20
- package/src/objects/ParamDefinition.ts +0 -49
- package/src/objects/PinDefinition.ts +0 -49
- package/src/objects/PinTypes.ts +0 -7
- package/src/objects/Wire.ts +0 -19
- package/src/objects/types.ts +0 -66
- package/src/parser.ts +0 -106
- package/src/regenerate-tests.ts +0 -25
- package/src/render.ts +0 -260
- package/src/sizing.ts +0 -96
- package/src/visitor.ts +0 -1691
- package/tsconfig.json +0 -27
- package/tsconfig.release.json +0 -8
- /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
- /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
- /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
- /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
- /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
- /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
- /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
- /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
- /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
- /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
- /package/{build/src → dist/types}/export.d.ts +0 -0
- /package/{build/src → dist/types}/fonts.d.ts +0 -0
- /package/{build/src → dist/types}/globals.d.ts +0 -0
- /package/{build/src → dist/types}/logger.d.ts +0 -0
- /package/{build/src → dist/types}/main.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
- /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
- /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
- /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
- /package/{build/src → dist/types}/server.d.ts +0 -0
- /package/{build/src → dist/types}/utils.d.ts +0 -0
package/src/execute.ts
DELETED
|
@@ -1,1227 +0,0 @@
|
|
|
1
|
-
import { BlockTypes, ComponentTypes, GlobalNames, NoNetText, ParamKeys, ReferenceTypes } from './globals.js';
|
|
2
|
-
import { ClassComponent } from './objects/ClassComponent.js';
|
|
3
|
-
import { ActiveObject, ExecutionScope, FrameAction, SequenceAction } from './objects/ExecutionScope.js';
|
|
4
|
-
import { Net } from './objects/Net.js';
|
|
5
|
-
import { ParamDefinition } from './objects/ParamDefinition.js';
|
|
6
|
-
import { PinDefinition, PortSide } from './objects/PinDefinition.js';
|
|
7
|
-
import { CFunction, CFunctionResult, CallableParameter, ComponentPin, ReferenceType } from './objects/types.js';
|
|
8
|
-
import { Wire, WireSegment } from './objects/Wire.js';
|
|
9
|
-
import { Logger } from './logger.js';
|
|
10
|
-
import { Frame } from './objects/Frame.js';
|
|
11
|
-
|
|
12
|
-
export class ExecutionContext {
|
|
13
|
-
// Contains the current running state of the circuit web
|
|
14
|
-
|
|
15
|
-
name: string; // Local name of the execution context.
|
|
16
|
-
|
|
17
|
-
// Namespace of current execution context, used for
|
|
18
|
-
// building the specific name of instances
|
|
19
|
-
namespace: string;
|
|
20
|
-
|
|
21
|
-
// Namespace for building nets, split away from instance namespace so
|
|
22
|
-
// that the net names generated are cleaner.
|
|
23
|
-
netNamespace: string;
|
|
24
|
-
|
|
25
|
-
executionLevel: number;
|
|
26
|
-
|
|
27
|
-
scope: ExecutionScope;
|
|
28
|
-
|
|
29
|
-
tmpPointId = 0; // Counter for points created within the context
|
|
30
|
-
|
|
31
|
-
resolveNet: (name: string, netNamespace:string) => ({
|
|
32
|
-
found: boolean, net?: Net
|
|
33
|
-
}) = null;
|
|
34
|
-
|
|
35
|
-
// If true, then do no evaluate further expressions.
|
|
36
|
-
// Used for function state control
|
|
37
|
-
stopFurtherExpressions = false;
|
|
38
|
-
|
|
39
|
-
// Return result of the context
|
|
40
|
-
returnValue = null;
|
|
41
|
-
|
|
42
|
-
// If true, then do not print any messages
|
|
43
|
-
silent = false;
|
|
44
|
-
|
|
45
|
-
logger: Logger;
|
|
46
|
-
|
|
47
|
-
__functionCache = {};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
constructor(
|
|
51
|
-
name: string,
|
|
52
|
-
namespace: string,
|
|
53
|
-
netNamespace: string,
|
|
54
|
-
executionLevel = 0,
|
|
55
|
-
indentLevel = 0,
|
|
56
|
-
silent = false,
|
|
57
|
-
logger: Logger
|
|
58
|
-
) {
|
|
59
|
-
this.name = name;
|
|
60
|
-
this.namespace = namespace;
|
|
61
|
-
this.netNamespace = netNamespace;
|
|
62
|
-
|
|
63
|
-
this.executionLevel = executionLevel;
|
|
64
|
-
this.logger = logger;
|
|
65
|
-
|
|
66
|
-
this.scope = ExecutionScope.create();
|
|
67
|
-
this.scope.indentLevel = indentLevel;
|
|
68
|
-
|
|
69
|
-
this.setupRoot();
|
|
70
|
-
|
|
71
|
-
this.silent = silent;
|
|
72
|
-
|
|
73
|
-
this.print(
|
|
74
|
-
'create new execution context',
|
|
75
|
-
this.namespace,
|
|
76
|
-
this.name,
|
|
77
|
-
this.scope.indentLevel,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
print(...params: any[]): void {
|
|
82
|
-
const indentOutput = ''.padStart(this.scope.indentLevel * 4, ' ');
|
|
83
|
-
const indentLevelText = this.scope.indentLevel
|
|
84
|
-
.toString()
|
|
85
|
-
.padStart(3, ' ');
|
|
86
|
-
|
|
87
|
-
const args = ['[' + indentLevelText + ']', indentOutput, ...params];
|
|
88
|
-
|
|
89
|
-
this.logger.add(args.join(' '));
|
|
90
|
-
|
|
91
|
-
if (this.silent) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
console.log.apply(null, args);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private setupRoot(): void {
|
|
98
|
-
// Setup the root node in the scope
|
|
99
|
-
const componentRoot = ClassComponent.simple(
|
|
100
|
-
GlobalNames.__root,
|
|
101
|
-
1,
|
|
102
|
-
'__root',
|
|
103
|
-
);
|
|
104
|
-
componentRoot.typeProp = ComponentTypes.net;
|
|
105
|
-
|
|
106
|
-
this.scope.instances.set(GlobalNames.__root, componentRoot);
|
|
107
|
-
|
|
108
|
-
this.scope.currentComponent = componentRoot;
|
|
109
|
-
this.scope.currentPin = componentRoot.getDefaultPin();
|
|
110
|
-
|
|
111
|
-
this.scope.componentRoot = componentRoot;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
instanceExists(instanceName: string): boolean {
|
|
116
|
-
return this.scope.instances.has(instanceName);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
getComponent(instanceName: string): ClassComponent {
|
|
120
|
-
return this.scope.instances.get(instanceName);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
getUniqueInstanceName(className: string): string {
|
|
124
|
-
let extraPrefix = '';
|
|
125
|
-
|
|
126
|
-
switch (className) {
|
|
127
|
-
case GlobalNames.DefaultResistor:
|
|
128
|
-
extraPrefix = 'R_';
|
|
129
|
-
break;
|
|
130
|
-
case GlobalNames.DefaultCapacitor:
|
|
131
|
-
extraPrefix = 'C_';
|
|
132
|
-
break;
|
|
133
|
-
case GlobalNames.DefaultInductor:
|
|
134
|
-
extraPrefix = 'L_';
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const tmpName = extraPrefix + 'COMP_' + this.scope.unnamedCounter;
|
|
139
|
-
this.scope.unnamedCounter += 1;
|
|
140
|
-
|
|
141
|
-
return tmpName;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
getUniqueNetName(): string {
|
|
145
|
-
const tmpName = 'NET_' + this.scope.netCounter;
|
|
146
|
-
this.scope.netCounter++;
|
|
147
|
-
return tmpName;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
getCurrentPoint(): ComponentPin {
|
|
151
|
-
return [this.scope.currentComponent, this.scope.currentPin];
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private linkComponentPinNet(
|
|
155
|
-
component1: ClassComponent,
|
|
156
|
-
component1Pin: number,
|
|
157
|
-
component2: ClassComponent,
|
|
158
|
-
component2Pin: number,
|
|
159
|
-
): Net {
|
|
160
|
-
const net1_exists = this.scope.hasNet(component1, component1Pin);
|
|
161
|
-
const net2_exists = this.scope.hasNet(component2, component2Pin);
|
|
162
|
-
|
|
163
|
-
const net1 = net1_exists
|
|
164
|
-
? this.scope.getNet(component1, component1Pin)
|
|
165
|
-
: null;
|
|
166
|
-
const net2 = net2_exists
|
|
167
|
-
? this.scope.getNet(component2, component2Pin)
|
|
168
|
-
: null;
|
|
169
|
-
|
|
170
|
-
this.print('link nets', component1, component1Pin, net1,
|
|
171
|
-
'to', component2, component2Pin, net2);
|
|
172
|
-
|
|
173
|
-
let returnNet: Net;
|
|
174
|
-
|
|
175
|
-
if (net1 === null && net2 === null) {
|
|
176
|
-
// Both nets do not exist yet, so create a new one
|
|
177
|
-
// that both will use.
|
|
178
|
-
const tmpNet = new Net(this.netNamespace, this.getUniqueNetName());
|
|
179
|
-
|
|
180
|
-
this.scope.setNet(component1, component1Pin, tmpNet);
|
|
181
|
-
this.scope.setNet(component2, component2Pin, tmpNet);
|
|
182
|
-
|
|
183
|
-
returnNet = tmpNet;
|
|
184
|
-
|
|
185
|
-
} else if (net1 === null && net2 !== null) {
|
|
186
|
-
// If net1 does not exist, but net2 exists
|
|
187
|
-
this.scope.setNet(component1, component1Pin, net2);
|
|
188
|
-
returnNet = net2;
|
|
189
|
-
|
|
190
|
-
} else if (net1 !== null && net2 === null) {
|
|
191
|
-
// If net1 exists, but net2 does not exist
|
|
192
|
-
this.scope.setNet(component2, component2Pin, net1);
|
|
193
|
-
returnNet = net1;
|
|
194
|
-
|
|
195
|
-
} else {
|
|
196
|
-
if (net1 !== net2) {
|
|
197
|
-
returnNet = this.mergeNets(net1, net2);
|
|
198
|
-
} else {
|
|
199
|
-
// Otherwise, both nets are the same.
|
|
200
|
-
return net1;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return returnNet;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
private mergeNets(net1: Net, net2: Net): Net {
|
|
208
|
-
// By default merge net2 into net1, net2 will no longer be used.
|
|
209
|
-
if (net1 === net2) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
let tmpNet: Net;
|
|
214
|
-
|
|
215
|
-
// Check priority to ensure that net1 always
|
|
216
|
-
// has the higher priority. Swap both nets
|
|
217
|
-
// if this is not the case.
|
|
218
|
-
if (net2.priority > net1.priority) {
|
|
219
|
-
tmpNet = net1;
|
|
220
|
-
net1 = net2;
|
|
221
|
-
net2 = tmpNet;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Get all (component, pin) pairs that are linked to net2
|
|
225
|
-
// and change them to net1
|
|
226
|
-
const scopeNets = this.scope.getNets();
|
|
227
|
-
scopeNets.forEach(([component, pin, net]) => {
|
|
228
|
-
if (Net.isSame(net, net2)) {
|
|
229
|
-
this.scope.setNet(component, pin, net1);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
return net1;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
createComponent(
|
|
237
|
-
instanceName: string,
|
|
238
|
-
pins: PinDefinition[],
|
|
239
|
-
params: ParamDefinition[],
|
|
240
|
-
props: {
|
|
241
|
-
arrange?: Map<string, number[]>,
|
|
242
|
-
display?: string,
|
|
243
|
-
type?: string,
|
|
244
|
-
width?: number
|
|
245
|
-
}
|
|
246
|
-
): ClassComponent {
|
|
247
|
-
|
|
248
|
-
const numPins = pins.length;
|
|
249
|
-
const component = new ClassComponent(
|
|
250
|
-
instanceName,
|
|
251
|
-
numPins,
|
|
252
|
-
GlobalNames.symbol,
|
|
253
|
-
);
|
|
254
|
-
pins.forEach((pin) => {
|
|
255
|
-
component.pins.set(pin.id, pin);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
const paramsMap = new Map<string, any>();
|
|
259
|
-
|
|
260
|
-
params.forEach((param) => {
|
|
261
|
-
component.parameters.set(param.paramName, param.paramValue);
|
|
262
|
-
paramsMap.set(param.paramName, param.paramValue);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
if (paramsMap.has(ParamKeys.__is_net)) {
|
|
266
|
-
const netName = paramsMap.get(ParamKeys.net_name);
|
|
267
|
-
const priority = paramsMap.get(ParamKeys.priority);
|
|
268
|
-
|
|
269
|
-
// Check if the net exists
|
|
270
|
-
const result = this.resolveNet(netName, this.netNamespace);
|
|
271
|
-
let tmpNet: Net;
|
|
272
|
-
|
|
273
|
-
if (result.found) {
|
|
274
|
-
tmpNet = result.net;
|
|
275
|
-
this.print('net found', tmpNet.namespace, tmpNet.name);
|
|
276
|
-
|
|
277
|
-
} else {
|
|
278
|
-
tmpNet = new Net(this.netNamespace, netName, priority);
|
|
279
|
-
this.print('net not found, added net instance',
|
|
280
|
-
tmpNet.namespace, tmpNet.name);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Assume net is on 1 pin for now
|
|
284
|
-
this.scope.setNet(component, 1, tmpNet);
|
|
285
|
-
this.print('set net', netName, 'component', component);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const {arrange = null} = props;
|
|
289
|
-
|
|
290
|
-
component.arrangeProps = arrange;
|
|
291
|
-
component.displayProp = props.display ?? null;
|
|
292
|
-
component.widthProp = props.width ?? null;
|
|
293
|
-
component.typeProp = props.type ?? null;
|
|
294
|
-
|
|
295
|
-
// Determine the side for each pin and update the
|
|
296
|
-
// pin definition
|
|
297
|
-
const portSides = getPortSide(component.pins, arrange);
|
|
298
|
-
portSides.forEach(({ pinId, side, position }) => {
|
|
299
|
-
if (component.pins.has(pinId)){
|
|
300
|
-
const tmpPin = component.pins.get(pinId);
|
|
301
|
-
tmpPin.side = side;
|
|
302
|
-
tmpPin.position = position;
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
this.scope.instances.set(instanceName, component);
|
|
307
|
-
|
|
308
|
-
const pinsOutput = pins.map((pin) => {
|
|
309
|
-
return pin.id + ':' + pin.name;
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
this.print(
|
|
313
|
-
'add symbol',
|
|
314
|
-
instanceName,
|
|
315
|
-
'[' + pinsOutput.join(', ') + ']',
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
return component;
|
|
319
|
-
}
|
|
320
|
-
|
|
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
|
-
|
|
332
|
-
this.print(
|
|
333
|
-
(extra !== '' ? (extra + ' ') : '') + 'point: ' +
|
|
334
|
-
this.scope.currentComponent.instanceName +
|
|
335
|
-
' ' +
|
|
336
|
-
this.scope.currentPin + ' ' + netName
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
addComponentExisting(component: ClassComponent, pin: number): ComponentPin {
|
|
341
|
-
const startPin = pin;
|
|
342
|
-
const nextPin = component.getNextPinAfter(startPin);
|
|
343
|
-
|
|
344
|
-
// Add to sequence
|
|
345
|
-
this.toComponent(component, startPin, {addSequence: true});
|
|
346
|
-
|
|
347
|
-
this.print('move to next pin: ' + nextPin);
|
|
348
|
-
this.atComponent(component, nextPin, {
|
|
349
|
-
addSequence: true
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
this.printPoint();
|
|
353
|
-
|
|
354
|
-
return this.getCurrentPoint();
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
toComponent(
|
|
358
|
-
component: ClassComponent,
|
|
359
|
-
pinId: number | null,
|
|
360
|
-
options?: {
|
|
361
|
-
addSequence?: boolean,
|
|
362
|
-
cloneNetComponent?: boolean,
|
|
363
|
-
}): ComponentPin {
|
|
364
|
-
this.print('to component');
|
|
365
|
-
|
|
366
|
-
const { addSequence = false, cloneNetComponent = false } = options ?? {};
|
|
367
|
-
|
|
368
|
-
if (cloneNetComponent && this.isNetOnlyComponent(component)) {
|
|
369
|
-
component = this.cloneComponent(component);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (!(component instanceof ClassComponent)){
|
|
373
|
-
throw "Not a valid component!";
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (pinId === null) {
|
|
377
|
-
pinId = component.getDefaultPin();
|
|
378
|
-
} else {
|
|
379
|
-
|
|
380
|
-
if (component.hasPin(pinId)) {
|
|
381
|
-
pinId = component.getPin(pinId);
|
|
382
|
-
} else {
|
|
383
|
-
console.trace();
|
|
384
|
-
throw (
|
|
385
|
-
'Invalid pin number ' +
|
|
386
|
-
pinId +
|
|
387
|
-
' in ' +
|
|
388
|
-
component.instanceName
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (
|
|
394
|
-
this.scope.hasNet(
|
|
395
|
-
this.scope.currentComponent,
|
|
396
|
-
this.scope.currentPin,
|
|
397
|
-
)
|
|
398
|
-
) {
|
|
399
|
-
this.print(
|
|
400
|
-
'net: ',
|
|
401
|
-
this.scope
|
|
402
|
-
.getNet(this.scope.currentComponent, this.scope.currentPin)
|
|
403
|
-
.toString(),
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
const linkedNet = this.linkComponentPinNet(
|
|
408
|
-
this.scope.currentComponent,
|
|
409
|
-
this.scope.currentPin,
|
|
410
|
-
component,
|
|
411
|
-
pinId,
|
|
412
|
-
);
|
|
413
|
-
|
|
414
|
-
this.scope.currentComponent = component;
|
|
415
|
-
this.scope.currentPin = pinId;
|
|
416
|
-
|
|
417
|
-
this.scope.clearActive();
|
|
418
|
-
|
|
419
|
-
if (addSequence) {
|
|
420
|
-
if (this.scope.sequence.length > 0) {
|
|
421
|
-
|
|
422
|
-
// Prevent component pin from being connected to multiple
|
|
423
|
-
// wires at the same time. This happens if the user tries
|
|
424
|
-
// to add the same (non-net) component at multiple places.
|
|
425
|
-
if (component.pinWires.has(pinId) && component.typeProp !== ComponentTypes.point) {
|
|
426
|
-
// throw "Component pin already connected to wire"
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// Check if the previous entry is a wire
|
|
430
|
-
const [entryType, , segments]: [SequenceAction, number, WireSegment[]] =
|
|
431
|
-
this.scope.sequence[this.scope.sequence.length - 1];
|
|
432
|
-
|
|
433
|
-
if (entryType === SequenceAction.Wire && isWireSegmentsEndAuto(segments)) {
|
|
434
|
-
segments[segments.length - 1].until = [
|
|
435
|
-
component, pinId
|
|
436
|
-
];
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
component.pinWires.set(pinId, segments);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
this.scope.sequence.push([SequenceAction.To, component,
|
|
443
|
-
pinId, linkedNet]);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
this.printPoint();
|
|
447
|
-
|
|
448
|
-
return this.getCurrentPoint();
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
atComponent(
|
|
452
|
-
component: ClassComponent,
|
|
453
|
-
pinId: number | null,
|
|
454
|
-
options?: {
|
|
455
|
-
addSequence?: boolean,
|
|
456
|
-
cloneNetComponent?: boolean,
|
|
457
|
-
}): ComponentPin {
|
|
458
|
-
this.print('at component');
|
|
459
|
-
|
|
460
|
-
const { addSequence = false, cloneNetComponent = false } = options ?? {};
|
|
461
|
-
|
|
462
|
-
if (cloneNetComponent && this.isNetOnlyComponent(component)) {
|
|
463
|
-
component = this.cloneComponent(component);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
this.scope.currentComponent = component;
|
|
467
|
-
|
|
468
|
-
let usePinId: number;
|
|
469
|
-
if (pinId === null) {
|
|
470
|
-
usePinId = component.getDefaultPin();
|
|
471
|
-
} else {
|
|
472
|
-
if (component.hasPin(pinId)) {
|
|
473
|
-
usePinId = component.getPin(pinId);
|
|
474
|
-
} else {
|
|
475
|
-
throw 'Invalid pin number ' + pinId + ' in ' + component;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (usePinId) {
|
|
480
|
-
this.scope.currentPin = usePinId;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Insertion point is currently at a component pin, so clear
|
|
484
|
-
// any wire/frame selected.
|
|
485
|
-
this.scope.clearActive();
|
|
486
|
-
|
|
487
|
-
if (addSequence) {
|
|
488
|
-
this.scope.sequence.push([SequenceAction.At,
|
|
489
|
-
component, usePinId]);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
this.printPoint();
|
|
493
|
-
|
|
494
|
-
return this.getCurrentPoint();
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
private isNetOnlyComponent(component: ClassComponent): boolean {
|
|
498
|
-
return isNetComponent(component) && !isLabelComponent(component);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
private cloneComponent(component: ClassComponent): ClassComponent {
|
|
502
|
-
// This creates a clone from a given net component, assume only
|
|
503
|
-
// has 1 pin
|
|
504
|
-
|
|
505
|
-
let clonedComponent: ClassComponent = null;
|
|
506
|
-
|
|
507
|
-
// If is a net component and not a label component, then
|
|
508
|
-
// create a new copy of the same net component.
|
|
509
|
-
if (!this.scope.copyIDs.has(component.instanceName)) {
|
|
510
|
-
this.scope.copyIDs.set(component.instanceName, 0);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const idNum = this.scope.copyIDs.get(component.instanceName);
|
|
514
|
-
clonedComponent = component.clone();
|
|
515
|
-
clonedComponent._copyID = idNum;
|
|
516
|
-
clonedComponent._copyFrom = component;
|
|
517
|
-
|
|
518
|
-
// Set linkIDs to the next value to use
|
|
519
|
-
this.scope.copyIDs.set(component.instanceName, idNum + 1);
|
|
520
|
-
|
|
521
|
-
const cloneInstanceName = component.instanceName + ':' + idNum;
|
|
522
|
-
|
|
523
|
-
// Add the cloned component
|
|
524
|
-
this.scope.instances.set(cloneInstanceName,
|
|
525
|
-
clonedComponent);
|
|
526
|
-
clonedComponent.instanceName = cloneInstanceName;
|
|
527
|
-
|
|
528
|
-
// Link pin of cloned component onto the same net
|
|
529
|
-
this.linkComponentPinNet(
|
|
530
|
-
component, 1,
|
|
531
|
-
clonedComponent, 1
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
this.print('created clone of net component:', cloneInstanceName);
|
|
535
|
-
|
|
536
|
-
return clonedComponent;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
enterBlocks(blockType: BlockTypes): void {
|
|
540
|
-
// Create object to track all the inner blocks of
|
|
541
|
-
// the block group
|
|
542
|
-
|
|
543
|
-
if (blockType === BlockTypes.Point) {
|
|
544
|
-
this.addPoint(`_point.${this.name}.${this.tmpPointId}`, false);
|
|
545
|
-
this.tmpPointId += 1;
|
|
546
|
-
} else if (blockType === BlockTypes.Parallel) {
|
|
547
|
-
this.addPoint(`_parallel.${this.name}.${this.tmpPointId}`, false);
|
|
548
|
-
this.tmpPointId += 1;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
this.scope.blockStack.set(this.scope.indentLevel, {
|
|
552
|
-
// Tracks the position when the block is entered
|
|
553
|
-
entered_at: [
|
|
554
|
-
this.scope.currentComponent,
|
|
555
|
-
this.scope.currentPin,
|
|
556
|
-
this.scope.currentWireId],
|
|
557
|
-
inner_blocks: new Map<number, any>(),
|
|
558
|
-
current_index: null,
|
|
559
|
-
type: blockType,
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
this.print('enter blocks');
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
exitBlocks(): void {
|
|
566
|
-
const stackRef = this.scope.blockStack.get(
|
|
567
|
-
this.scope.indentLevel,
|
|
568
|
-
);
|
|
569
|
-
|
|
570
|
-
const { type: blockType } = stackRef;
|
|
571
|
-
|
|
572
|
-
if (blockType === BlockTypes.Join || blockType === BlockTypes.Parallel) {
|
|
573
|
-
// Move to the end location of the first block
|
|
574
|
-
const { final_point: finalPoint } = stackRef;
|
|
575
|
-
const [component, pin, wireId] = finalPoint;
|
|
576
|
-
|
|
577
|
-
this.scope.currentComponent = component;
|
|
578
|
-
this.scope.currentPin = pin;
|
|
579
|
-
this.scope.currentWireId = wireId;
|
|
580
|
-
|
|
581
|
-
if (wireId !== -1) {
|
|
582
|
-
this.scope.sequence.push([
|
|
583
|
-
SequenceAction.WireJump, wireId, 1
|
|
584
|
-
]);
|
|
585
|
-
}
|
|
586
|
-
} else if (blockType === BlockTypes.Point) {
|
|
587
|
-
const { entered_at: [component, pin,] } =
|
|
588
|
-
stackRef;
|
|
589
|
-
|
|
590
|
-
// Preblock location should be a created point without any wires
|
|
591
|
-
this.atComponent(component, pin, { addSequence: true });
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
this.print('exit blocks');
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
enterBlock(blockIndex: number): void {
|
|
598
|
-
// Current net before any blocks is already stored in enterBlocks()
|
|
599
|
-
const stackRef = this.scope.blockStack.get(this.scope.indentLevel);
|
|
600
|
-
stackRef['block_index'] = blockIndex;
|
|
601
|
-
|
|
602
|
-
const { type: blockType } = stackRef;
|
|
603
|
-
|
|
604
|
-
// Setup the state for the inner block at the given index
|
|
605
|
-
stackRef['inner_blocks'].set(blockIndex, {
|
|
606
|
-
last_net: null,
|
|
607
|
-
ignore_last_net: false,
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
if (blockType === BlockTypes.Join || blockType === BlockTypes.Point) {
|
|
611
|
-
// Clear current component, pin, wire before entering the block
|
|
612
|
-
this.scope.currentComponent = null;
|
|
613
|
-
this.scope.currentPin = null;
|
|
614
|
-
this.scope.currentWireId = -1;
|
|
615
|
-
} else if (blockType === BlockTypes.Parallel) {
|
|
616
|
-
// Move to starting point of the parallel blocks
|
|
617
|
-
const { entered_at: [component, pin,] } = stackRef;
|
|
618
|
-
this.atComponent(component, pin, { addSequence: true });
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
this.print(`enter inner block of type (${blockType}) >>>`);
|
|
622
|
-
|
|
623
|
-
this.scope.indentLevel += 1;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
exitBlock(blockIndex: number): void {
|
|
627
|
-
const stackRef = this.scope.blockStack.get(this.scope.indentLevel - 1);
|
|
628
|
-
const { type: blockType } = stackRef;
|
|
629
|
-
|
|
630
|
-
// Save the last net reference
|
|
631
|
-
const blockIndexRef = stackRef['inner_blocks'].get(blockIndex);
|
|
632
|
-
blockIndexRef['last_net'] = [
|
|
633
|
-
this.scope.currentComponent,
|
|
634
|
-
this.scope.currentPin,
|
|
635
|
-
this.scope.currentWireId
|
|
636
|
-
];
|
|
637
|
-
|
|
638
|
-
stackRef['block_index'] = null;
|
|
639
|
-
this.scope.indentLevel -= 1;
|
|
640
|
-
|
|
641
|
-
this.print('exit inner block <<<');
|
|
642
|
-
|
|
643
|
-
if (blockType === BlockTypes.Branch) {
|
|
644
|
-
|
|
645
|
-
// Restore the latest entry in the branch stack
|
|
646
|
-
const { entered_at: [component, pin, wireId] } =
|
|
647
|
-
stackRef;
|
|
648
|
-
|
|
649
|
-
// Do not duplicate any net symbol since this is a branch
|
|
650
|
-
this.atComponent(component, pin, { addSequence: true });
|
|
651
|
-
|
|
652
|
-
if (wireId !== -1) {
|
|
653
|
-
// If previous node is a wire, then jump to END of wire
|
|
654
|
-
this.scope.sequence.push([SequenceAction.WireJump, wireId, 1]);
|
|
655
|
-
}
|
|
656
|
-
} else if (blockType === BlockTypes.Join || blockType === BlockTypes.Parallel) {
|
|
657
|
-
if (blockIndex === 0) {
|
|
658
|
-
// First join block will determine the final join location
|
|
659
|
-
|
|
660
|
-
const pointIdName = (blockType === BlockTypes.Join) ? '_join' : '_parallel';
|
|
661
|
-
|
|
662
|
-
// Add point to current location, start with _join keyword to
|
|
663
|
-
// indicate that this is a point for join keyword
|
|
664
|
-
this.addPoint(`${pointIdName}.${this.name}.${this.tmpPointId}`, false);
|
|
665
|
-
this.tmpPointId += 1;
|
|
666
|
-
|
|
667
|
-
stackRef['final_point'] = [
|
|
668
|
-
this.scope.currentComponent,
|
|
669
|
-
this.scope.currentPin,
|
|
670
|
-
this.scope.currentWireId
|
|
671
|
-
];
|
|
672
|
-
|
|
673
|
-
} else {
|
|
674
|
-
const { final_point: finalPoint } = stackRef;
|
|
675
|
-
const [component, pin,] = finalPoint;
|
|
676
|
-
|
|
677
|
-
// Link the current component to the join component and join pin
|
|
678
|
-
this.toComponent(component, pin, { addSequence: true });
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
atPointBlock(): void {
|
|
684
|
-
const [component, pin,] = this.getPointBlockLocation();
|
|
685
|
-
this.atComponent(component, pin, {
|
|
686
|
-
addSequence: true
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
toPointBlock(): void {
|
|
691
|
-
// Point has been specifically created for block, wireId should be -1
|
|
692
|
-
const [component, pin,] = this.getPointBlockLocation();
|
|
693
|
-
this.toComponent(component, pin, {
|
|
694
|
-
addSequence: true
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
getPointBlockLocation(): [component: ClassComponent, pin: number, wireId: number] {
|
|
699
|
-
// Returns the position at the nearest `point:` block, searches within
|
|
700
|
-
// previous block stacks
|
|
701
|
-
this.print('get block point');
|
|
702
|
-
|
|
703
|
-
for (let i = 0; i < this.scope.indentLevel; i++) {
|
|
704
|
-
const stackRef = this.scope.blockStack.get(this.scope.indentLevel - 1 - i);
|
|
705
|
-
const { entered_at } = stackRef;
|
|
706
|
-
const component: ClassComponent = entered_at[0];
|
|
707
|
-
|
|
708
|
-
if (component.instanceName.startsWith('_point.')) {
|
|
709
|
-
return entered_at;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
this.print('did not find block point');
|
|
714
|
-
|
|
715
|
-
return null;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
breakBranch(): void {
|
|
719
|
-
this.print('break branch');
|
|
720
|
-
// Mark that the branch stack at the current indent level
|
|
721
|
-
// should be ignored
|
|
722
|
-
|
|
723
|
-
const branchesInfo = this.scope.blockStack.get(
|
|
724
|
-
this.scope.indentLevel - 1,
|
|
725
|
-
);
|
|
726
|
-
const branchIndex = branchesInfo['block_index'];
|
|
727
|
-
|
|
728
|
-
const branchIndexRef = branchesInfo['inner_blocks'].get(branchIndex);
|
|
729
|
-
branchIndexRef['ignore_last_net'] = true;
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
createFunction(functionName: string, __runFunc: CFunction): void {
|
|
733
|
-
this.scope.functions.set(functionName, __runFunc);
|
|
734
|
-
this.__functionCache[functionName] = __runFunc;
|
|
735
|
-
this.print(`defined new function '${functionName}'`);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
hasFunction(functionName: string): boolean {
|
|
739
|
-
return this.scope.functions.has(functionName);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
getFunction(functionName: string): CFunction {
|
|
743
|
-
return this.scope.functions.get(functionName);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
resolveVariable(executionStack: ExecutionContext[], idName: string):
|
|
747
|
-
ReferenceType {
|
|
748
|
-
// this.print('resolve variable', idName);
|
|
749
|
-
const reversed = [...executionStack].reverse();
|
|
750
|
-
|
|
751
|
-
for (let i = 0; i < reversed.length; i++) {
|
|
752
|
-
const context = reversed[i];
|
|
753
|
-
if (context.hasFunction(idName)) {
|
|
754
|
-
return {
|
|
755
|
-
found: true,
|
|
756
|
-
value: context.getFunction(idName),
|
|
757
|
-
type: ReferenceTypes.function,
|
|
758
|
-
name: idName,
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
} else if (context.scope.variables.has(idName)) {
|
|
762
|
-
return {
|
|
763
|
-
found: true,
|
|
764
|
-
value: context.scope.variables.get(idName),
|
|
765
|
-
type: ReferenceTypes.variable,
|
|
766
|
-
name: idName,
|
|
767
|
-
};
|
|
768
|
-
|
|
769
|
-
} else if (context.scope.instances.has(idName)) {
|
|
770
|
-
return {
|
|
771
|
-
found: true,
|
|
772
|
-
value: context.scope.instances.get(idName),
|
|
773
|
-
type: ReferenceTypes.instance,
|
|
774
|
-
name: idName,
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
return {
|
|
780
|
-
found: false,
|
|
781
|
-
name: idName,
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
callFunction(
|
|
786
|
-
functionName: string,
|
|
787
|
-
functionParams: CallableParameter[],
|
|
788
|
-
executionStack: ExecutionContext[],
|
|
789
|
-
netNamespace: string,
|
|
790
|
-
): CFunctionResult {
|
|
791
|
-
let __runFunc: CFunction | null = null;
|
|
792
|
-
|
|
793
|
-
// Function is not cached yet, so look for it
|
|
794
|
-
if (this.__functionCache[functionName] === undefined){
|
|
795
|
-
if (this.hasFunction(functionName)) {
|
|
796
|
-
__runFunc = this.getFunction(functionName);
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// If the function does not exist in the current execution context,
|
|
800
|
-
// then try to search in the upper execution context
|
|
801
|
-
if (__runFunc === null) {
|
|
802
|
-
this.print(`searching for function ${functionName} in upper context`)
|
|
803
|
-
|
|
804
|
-
const tmpResolveResult =
|
|
805
|
-
this.resolveVariable(executionStack, functionName);
|
|
806
|
-
|
|
807
|
-
if (tmpResolveResult.found) {
|
|
808
|
-
__runFunc = tmpResolveResult.value;
|
|
809
|
-
} else {
|
|
810
|
-
throw `Invalid function ${functionName}`;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
this.print('save function to cache:', functionName);
|
|
814
|
-
this.__functionCache[functionName] = __runFunc;
|
|
815
|
-
|
|
816
|
-
} else {
|
|
817
|
-
this.print('found function in cache:', functionName);
|
|
818
|
-
__runFunc = this.__functionCache[functionName];
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
if (__runFunc !== null) {
|
|
822
|
-
this.print(`call function '${functionName}'`);
|
|
823
|
-
|
|
824
|
-
const functionResult = __runFunc(
|
|
825
|
-
functionParams,
|
|
826
|
-
{ netNamespace });
|
|
827
|
-
|
|
828
|
-
this.print(`done call function '${functionName}'`);
|
|
829
|
-
|
|
830
|
-
return functionResult;
|
|
831
|
-
} else {
|
|
832
|
-
throw `Invalid function '${functionName}'`;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
mergeScope(childScope: ExecutionScope, namespace: string): void {
|
|
837
|
-
this.print('-- merging scope to parent --');
|
|
838
|
-
|
|
839
|
-
// Save these position first, because this needs to be restored
|
|
840
|
-
// after the merge operation
|
|
841
|
-
const currentComponent = this.scope.currentComponent;
|
|
842
|
-
const currentPin = this.scope.currentPin;
|
|
843
|
-
const currentWireId = this.scope.currentWireId;
|
|
844
|
-
|
|
845
|
-
// move all instances into the parent scope first, with a namespace extension
|
|
846
|
-
const tmpInstances = childScope.instances;
|
|
847
|
-
const tmpNets = childScope.getNets();
|
|
848
|
-
|
|
849
|
-
for (const [instanceName, component] of tmpInstances) {
|
|
850
|
-
// Rename instance names with the addition of the namespace
|
|
851
|
-
const newInstanceName = `${namespace}.${instanceName}`;
|
|
852
|
-
component.instanceName = newInstanceName;
|
|
853
|
-
|
|
854
|
-
// Do not add root and gnd components of child scope to the
|
|
855
|
-
// parent scope
|
|
856
|
-
if (component === childScope.componentGnd ||
|
|
857
|
-
component === childScope.componentRoot){
|
|
858
|
-
continue;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
if (!this.scope.instances.has(newInstanceName)) {
|
|
862
|
-
this.scope.instances.set(newInstanceName, component);
|
|
863
|
-
} else {
|
|
864
|
-
throw "Invalid instance name to merge into parent scope!";
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Merge all nets into parent scope
|
|
869
|
-
tmpNets.forEach(([component, pin, net]) => {
|
|
870
|
-
this.scope.setNet(component, pin, net);
|
|
871
|
-
});
|
|
872
|
-
|
|
873
|
-
// If true, then then __root component of the child_scope will
|
|
874
|
-
// be connected to the current component/pin of the parent
|
|
875
|
-
const linkRootComponent = true;
|
|
876
|
-
|
|
877
|
-
const tmpRoot = childScope.componentRoot;
|
|
878
|
-
|
|
879
|
-
if (linkRootComponent) {
|
|
880
|
-
// Join the child_scope's __root net to the current component / pin
|
|
881
|
-
|
|
882
|
-
// Get the net of the root scope first
|
|
883
|
-
const netConnectedToRoot = childScope.getNet(tmpRoot, 1);
|
|
884
|
-
|
|
885
|
-
if (netConnectedToRoot !== null){
|
|
886
|
-
// Only if the child scope root component is connected
|
|
887
|
-
// to a net, then merge them together.
|
|
888
|
-
let currentNet = this.scope.getNet(
|
|
889
|
-
currentComponent, currentPin
|
|
890
|
-
);
|
|
891
|
-
|
|
892
|
-
if (currentNet === null){
|
|
893
|
-
// Current net does not exist yet, so create it
|
|
894
|
-
const tmpNet = new Net(this.netNamespace,
|
|
895
|
-
this.getUniqueNetName());
|
|
896
|
-
|
|
897
|
-
this.scope.setNet(
|
|
898
|
-
currentComponent, currentPin, netConnectedToRoot);
|
|
899
|
-
currentNet = tmpNet
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
netConnectedToRoot.priority = currentNet.priority - 1;
|
|
903
|
-
|
|
904
|
-
// Connect current component to the root component, since the
|
|
905
|
-
// net priority of the current component and pin is higher,
|
|
906
|
-
// then the root component's net will be merged in.
|
|
907
|
-
this.toComponent(tmpRoot, 1);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// Merge the sequences together, need to renumber the wire ids.
|
|
912
|
-
const wireIdOffset = this.scope.wires.length;
|
|
913
|
-
|
|
914
|
-
// Need to renumber the frame ids too.
|
|
915
|
-
const frameIdOffset = this.scope.frames.length;
|
|
916
|
-
|
|
917
|
-
let incrementGndLinkId = 0;
|
|
918
|
-
|
|
919
|
-
childScope.sequence.forEach(sequenceAction => {
|
|
920
|
-
const [action] = sequenceAction;
|
|
921
|
-
|
|
922
|
-
if (action === SequenceAction.Wire) {
|
|
923
|
-
// Need to have new IDs for wires
|
|
924
|
-
const [, innerWireId, segments] = sequenceAction;
|
|
925
|
-
|
|
926
|
-
this.scope.sequence.push(
|
|
927
|
-
[SequenceAction.Wire, wireIdOffset + innerWireId, segments]
|
|
928
|
-
);
|
|
929
|
-
|
|
930
|
-
this.scope.wires.push(new Wire(segments));
|
|
931
|
-
|
|
932
|
-
} else if (action === SequenceAction.WireJump) {
|
|
933
|
-
// Wire IDs in wire jumps need to be updated.
|
|
934
|
-
const jumpWireId = wireIdOffset + sequenceAction[1];
|
|
935
|
-
this.scope.sequence.push(
|
|
936
|
-
[SequenceAction.WireJump, jumpWireId, 1]
|
|
937
|
-
);
|
|
938
|
-
} else if (action === SequenceAction.At || action === SequenceAction.To) {
|
|
939
|
-
const tmpComponent: ClassComponent = sequenceAction[1];
|
|
940
|
-
|
|
941
|
-
// Check if the component is a gnd component
|
|
942
|
-
if (isNetComponent(tmpComponent) && tmpComponent.parameters.get(ParamKeys.net_name) === 'gnd') {
|
|
943
|
-
// Is a gnd net
|
|
944
|
-
tmpComponent._copyID = gndCopyIdOffset + incrementGndLinkId;
|
|
945
|
-
incrementGndLinkId += 1;
|
|
946
|
-
|
|
947
|
-
} else if (tmpComponent === tmpRoot) {
|
|
948
|
-
// If this sequence action contains the root component,
|
|
949
|
-
// then replace it with a corresponding sequence action.
|
|
950
|
-
// If current wire id is set, then use a wire jump sequence
|
|
951
|
-
// action, otherwise use at/to action.
|
|
952
|
-
|
|
953
|
-
if (currentWireId !== -1){
|
|
954
|
-
sequenceAction = [SequenceAction.WireJump, currentWireId];
|
|
955
|
-
|
|
956
|
-
} else {
|
|
957
|
-
// If is the root component, then replace it by the current
|
|
958
|
-
// component and pin
|
|
959
|
-
sequenceAction = [action, currentComponent, currentPin];
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
this.scope.sequence.push(sequenceAction);
|
|
963
|
-
|
|
964
|
-
} else if (action === SequenceAction.Frame){
|
|
965
|
-
const frame: Frame = sequenceAction[1];
|
|
966
|
-
const frameAction: string = sequenceAction[2];
|
|
967
|
-
if (frameAction === FrameAction.Enter){
|
|
968
|
-
frame.frameId += frameIdOffset;
|
|
969
|
-
this.scope.frames.push(frame);
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
this.scope.sequence.push(sequenceAction);
|
|
973
|
-
}
|
|
974
|
-
});
|
|
975
|
-
|
|
976
|
-
if (childScope.currentComponent === childScope.componentRoot) {
|
|
977
|
-
// If child scope is current at the root node, then use the
|
|
978
|
-
// location in the parent scope as the current component
|
|
979
|
-
// since that would be equivalent
|
|
980
|
-
this.scope.currentComponent = currentComponent;
|
|
981
|
-
this.scope.currentPin = currentPin;
|
|
982
|
-
this.scope.currentWireId = currentWireId;
|
|
983
|
-
|
|
984
|
-
} else {
|
|
985
|
-
// Otherwise move the current scope to the current node within
|
|
986
|
-
// the child scope
|
|
987
|
-
this.scope.currentComponent = childScope.currentComponent;
|
|
988
|
-
this.scope.currentPin = childScope.currentPin;
|
|
989
|
-
this.scope.currentWireId = childScope.currentWireId + wireIdOffset;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
this.printPoint('resume at');
|
|
993
|
-
|
|
994
|
-
this.print('-- nets --');
|
|
995
|
-
|
|
996
|
-
// dump the list of nets in the current scope
|
|
997
|
-
const currentNets = this.scope.getNets();
|
|
998
|
-
|
|
999
|
-
currentNets.reduce((accum, [,,net]) => {
|
|
1000
|
-
if (accum.indexOf(net) === -1){
|
|
1001
|
-
accum.push(net);
|
|
1002
|
-
this.print(`${net.namespace}${net.name} ${net.priority}`);
|
|
1003
|
-
}
|
|
1004
|
-
return accum;
|
|
1005
|
-
}, []);
|
|
1006
|
-
|
|
1007
|
-
this.print('-- done merging scope --');
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
addWire(segments: [string, number?][]): void {
|
|
1011
|
-
|
|
1012
|
-
if (this.scope.currentComponent === null) {
|
|
1013
|
-
throw "No current component";
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
const tmp = segments.map(item => {
|
|
1017
|
-
const [direction, value=null] = item;
|
|
1018
|
-
return {
|
|
1019
|
-
direction,
|
|
1020
|
-
value
|
|
1021
|
-
} as WireSegment
|
|
1022
|
-
});
|
|
1023
|
-
|
|
1024
|
-
// This ID is used to identify/jump to wires later
|
|
1025
|
-
const wireId = this.scope.wires.length;
|
|
1026
|
-
|
|
1027
|
-
this.scope.wires.push(new Wire(tmp));
|
|
1028
|
-
|
|
1029
|
-
const output = [];
|
|
1030
|
-
segments.forEach(item => {
|
|
1031
|
-
output.push(item.join(","));
|
|
1032
|
-
});
|
|
1033
|
-
|
|
1034
|
-
this.print('add wire: ', output.join("|"));
|
|
1035
|
-
|
|
1036
|
-
this.scope.setActive(ActiveObject.Wire, wireId);
|
|
1037
|
-
this.scope.sequence.push([SequenceAction.Wire, wireId, tmp]);
|
|
1038
|
-
|
|
1039
|
-
// if (this.scope.currentComponent.pinWires.has(this.scope.currentPin)) {
|
|
1040
|
-
// throw "Component pin already connected to wire"
|
|
1041
|
-
// }
|
|
1042
|
-
|
|
1043
|
-
this.scope.currentComponent.pinWires.set(
|
|
1044
|
-
this.scope.currentPin, tmp
|
|
1045
|
-
)
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
addPoint(pointId: string, userDefined = true): ComponentPin {
|
|
1049
|
-
if (this.scope.instances.has(pointId)) {
|
|
1050
|
-
this.print('Warning: ' + pointId + ' is being redefined');
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
const useName = userDefined ? 'point.' + pointId : pointId;
|
|
1054
|
-
const componentPoint = ClassComponent.simple(useName, 1, "point");
|
|
1055
|
-
componentPoint.displayProp = "point";
|
|
1056
|
-
componentPoint.typeProp = ComponentTypes.point;
|
|
1057
|
-
|
|
1058
|
-
this.scope.instances.set(pointId, componentPoint);
|
|
1059
|
-
this.toComponent(componentPoint, 1, { addSequence: true });
|
|
1060
|
-
|
|
1061
|
-
return this.getCurrentPoint();
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
setProperty(nameWithProp: string, value: any): void {
|
|
1065
|
-
this.print('set property', nameWithProp, 'value', value);
|
|
1066
|
-
|
|
1067
|
-
let idName: string;
|
|
1068
|
-
let paramName: string;
|
|
1069
|
-
|
|
1070
|
-
let useActive = false;
|
|
1071
|
-
|
|
1072
|
-
if (nameWithProp.startsWith('..')){
|
|
1073
|
-
useActive = true;
|
|
1074
|
-
paramName = nameWithProp.substring(2);
|
|
1075
|
-
} else {
|
|
1076
|
-
const parts = nameWithProp.split(".");
|
|
1077
|
-
idName = parts[0];
|
|
1078
|
-
paramName = parts[1];
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
if (useActive && this.scope.currentFrameId !== -1) {
|
|
1082
|
-
// If there is some frame selected, then update frame params
|
|
1083
|
-
this.scope.frames[this.scope.currentFrameId - 1]
|
|
1084
|
-
.parameters.set(paramName, value);
|
|
1085
|
-
} else {
|
|
1086
|
-
idName = this.scope.currentComponent.instanceName;
|
|
1087
|
-
|
|
1088
|
-
// Check if instance exists
|
|
1089
|
-
if (this.scope.instances.has(idName)) {
|
|
1090
|
-
const component = this.scope.instances.get(idName);
|
|
1091
|
-
component.parameters.set(paramName, value);
|
|
1092
|
-
|
|
1093
|
-
} else if (this.scope.variables.has(idName)) {
|
|
1094
|
-
throw "Not implemented yet!";
|
|
1095
|
-
} else {
|
|
1096
|
-
throw "Unknown identifier: " + idName;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
setCurrentComponentStyle(styles: { [key: string]: number | string }): void {
|
|
1102
|
-
// Add onto to the current component styles
|
|
1103
|
-
for (const key in styles) {
|
|
1104
|
-
this.scope.currentComponent.styles[key] = styles[key];
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
enterFrame(): number {
|
|
1109
|
-
// Frame 0 is the 'base' frame
|
|
1110
|
-
const frameId = this.scope.frames.length + 1;
|
|
1111
|
-
const frameObject = new Frame(frameId);
|
|
1112
|
-
this.scope.frames.push(frameObject);
|
|
1113
|
-
|
|
1114
|
-
this.scope.sequence.push([SequenceAction.Frame,
|
|
1115
|
-
frameObject, FrameAction.Enter]);
|
|
1116
|
-
|
|
1117
|
-
this.scope.currentFrameId = frameId;
|
|
1118
|
-
this.scope.setActive(ActiveObject.Frame, frameId);
|
|
1119
|
-
|
|
1120
|
-
// TODO: allow frame properties to be set in double dot expressions
|
|
1121
|
-
// TODO: also allow frames to be assigned in variables for reuse?
|
|
1122
|
-
|
|
1123
|
-
return frameId;
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
exitFrame(frameId: number): void {
|
|
1127
|
-
const frame = this.scope.frames[frameId-1];
|
|
1128
|
-
this.scope.sequence.push([SequenceAction.Frame,
|
|
1129
|
-
frame, FrameAction.Exit]);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
function isWireSegmentsEndAuto(segments:WireSegment[]): boolean {
|
|
1134
|
-
if (segments.length > 0){
|
|
1135
|
-
if (segments[segments.length -1].value === null){
|
|
1136
|
-
return true;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
return false;
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
export function isNetComponent(component: ClassComponent): boolean {
|
|
1144
|
-
// Returns true if the component is a net component
|
|
1145
|
-
return component.parameters.has(ParamKeys.__is_net);
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
export function isLabelComponent(component: ClassComponent): boolean {
|
|
1149
|
-
return component.parameters.has(ParamKeys.__is_label);
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
export function getPortSide(pins: Map<number, PinDefinition>, arrangeProps: null | Map<string, number[]>): PortSideItem[] {
|
|
1153
|
-
// Takes the arrangeProps and determines how to arrange pins in the symbol.
|
|
1154
|
-
|
|
1155
|
-
const result = [];
|
|
1156
|
-
|
|
1157
|
-
if (arrangeProps === null) {
|
|
1158
|
-
|
|
1159
|
-
let counter = 0;
|
|
1160
|
-
for (const [pinId] of pins) {
|
|
1161
|
-
result.push({
|
|
1162
|
-
pinId,
|
|
1163
|
-
side: counter % 2 === 0 ? PortSide.WEST : PortSide.EAST,
|
|
1164
|
-
order: counter,
|
|
1165
|
-
position: Math.floor(counter/2),
|
|
1166
|
-
});
|
|
1167
|
-
counter++;
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
} else {
|
|
1171
|
-
let counter = pins.size;
|
|
1172
|
-
const existingPinIds = Array.from(pins.keys());
|
|
1173
|
-
|
|
1174
|
-
for (const [key, items] of arrangeProps) {
|
|
1175
|
-
let useItems;
|
|
1176
|
-
if (!Array.isArray(items)){
|
|
1177
|
-
useItems = [items];
|
|
1178
|
-
} else {
|
|
1179
|
-
// Do no mutate original array
|
|
1180
|
-
useItems = [...items];
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
let useSide = PortSide.WEST;
|
|
1184
|
-
if (key === 'left') {
|
|
1185
|
-
useSide = PortSide.WEST;
|
|
1186
|
-
} else if (key === 'right') {
|
|
1187
|
-
useSide = PortSide.EAST;
|
|
1188
|
-
} else if (key === 'top') {
|
|
1189
|
-
useSide = PortSide.NORTH;
|
|
1190
|
-
} else if (key === 'bottom') {
|
|
1191
|
-
useSide = PortSide.SOUTH;
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
let position = 0;
|
|
1195
|
-
|
|
1196
|
-
useItems.forEach(item => {
|
|
1197
|
-
if (typeof item === 'object'){
|
|
1198
|
-
if (item.blank){
|
|
1199
|
-
position += item.blank;
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
// Only use the pin if it exists!
|
|
1204
|
-
if (existingPinIds.indexOf(item) !== -1) {
|
|
1205
|
-
result.push({
|
|
1206
|
-
pinId: item,
|
|
1207
|
-
side: useSide,
|
|
1208
|
-
position,
|
|
1209
|
-
order: counter
|
|
1210
|
-
});
|
|
1211
|
-
counter--;
|
|
1212
|
-
position += 1;
|
|
1213
|
-
}
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
return result;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
type PortSideItem = {
|
|
1222
|
-
pinId: number,
|
|
1223
|
-
side: string,
|
|
1224
|
-
order: number,
|
|
1225
|
-
position: number,
|
|
1226
|
-
};
|
|
1227
|
-
|