nodalis-compiler 1.0.0

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 (37) hide show
  1. package/README.md +134 -0
  2. package/package.json +59 -0
  3. package/src/compilers/CPPCompiler.js +272 -0
  4. package/src/compilers/Compiler.js +108 -0
  5. package/src/compilers/JSCompiler.js +293 -0
  6. package/src/compilers/iec-parser/parser.js +4254 -0
  7. package/src/compilers/st-parser/expressionConverter.js +155 -0
  8. package/src/compilers/st-parser/gcctranspiler.js +237 -0
  9. package/src/compilers/st-parser/jstranspiler.js +254 -0
  10. package/src/compilers/st-parser/parser.js +367 -0
  11. package/src/compilers/st-parser/tokenizer.js +78 -0
  12. package/src/compilers/support/generic/json.hpp +25526 -0
  13. package/src/compilers/support/generic/modbus.cpp +378 -0
  14. package/src/compilers/support/generic/modbus.h +124 -0
  15. package/src/compilers/support/generic/nodalis.cpp +421 -0
  16. package/src/compilers/support/generic/nodalis.h +798 -0
  17. package/src/compilers/support/generic/opcua.cpp +267 -0
  18. package/src/compilers/support/generic/opcua.h +50 -0
  19. package/src/compilers/support/generic/open62541.c +151897 -0
  20. package/src/compilers/support/generic/open62541.h +50357 -0
  21. package/src/compilers/support/jint/nodalis/Nodalis.sln +28 -0
  22. package/src/compilers/support/jint/nodalis/NodalisEngine/ModbusClient.cs +200 -0
  23. package/src/compilers/support/jint/nodalis/NodalisEngine/NodalisEngine.cs +817 -0
  24. package/src/compilers/support/jint/nodalis/NodalisEngine/NodalisEngine.csproj +16 -0
  25. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCClient.cs +172 -0
  26. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCServer.cs +275 -0
  27. package/src/compilers/support/jint/nodalis/NodalisPLC/NodalisPLC.csproj +19 -0
  28. package/src/compilers/support/jint/nodalis/NodalisPLC/Program.cs +197 -0
  29. package/src/compilers/support/jint/nodalis/NodalisPLC/bootstrap.bat +5 -0
  30. package/src/compilers/support/jint/nodalis/NodalisPLC/bootstrap.sh +5 -0
  31. package/src/compilers/support/jint/nodalis/build.bat +25 -0
  32. package/src/compilers/support/jint/nodalis/build.sh +31 -0
  33. package/src/compilers/support/nodejs/IOClient.js +110 -0
  34. package/src/compilers/support/nodejs/modbus.js +115 -0
  35. package/src/compilers/support/nodejs/nodalis.js +662 -0
  36. package/src/compilers/support/nodejs/opcua.js +194 -0
  37. package/src/nodalis.js +174 -0
@@ -0,0 +1,817 @@
1
+ #nullable enable
2
+
3
+ // Copyright [2025] Nathan Skipper
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+
17
+ /// <summary>
18
+ /// Nodalis Framework for .NET
19
+ /// </summary>
20
+
21
+ using System;
22
+ using System.Collections.Generic;
23
+ using System.Text.Json;
24
+ using Jint;
25
+ using Jint.Native;
26
+ using Jint.Native.Object;
27
+ using Jint.Native.Function;
28
+ using Jint.Runtime.Interop;
29
+ using Jint.Runtime;
30
+ namespace Nodalis
31
+ {
32
+ public class StaticStore
33
+ {
34
+ private readonly Dictionary<string, JsValue> _store = new();
35
+
36
+ public bool TryGetValue(string key, out JsValue value) =>
37
+ _store.TryGetValue(key, out value);
38
+
39
+ public JsValue this[string key]
40
+ {
41
+ get => _store[key];
42
+ set => _store[key] = value;
43
+ }
44
+ }
45
+
46
+
47
+ public enum IOType { Input, Output }
48
+
49
+ public class IOMap
50
+ {
51
+ public string localAddress;
52
+ public string remoteAddress;
53
+ public string moduleID;
54
+ public string modulePort;
55
+ public string protocol;
56
+ public IOType direction;
57
+ public int width;
58
+ public int interval;
59
+ public long lastPoll = 0;
60
+ public Dictionary<string, string>? protocolProperties;
61
+ public IOMap(string json)
62
+ {
63
+ var dict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(json);
64
+ localAddress = dict["InternalAddress"];
65
+ remoteAddress = dict["RemoteAddress"];
66
+ moduleID = dict["ModuleID"];
67
+ modulePort = dict["ModulePort"];
68
+ protocol = dict["Protocol"];
69
+ direction = localAddress.StartsWith("%Q") ? IOType.Output : IOType.Input;
70
+ width = int.Parse(dict["RemoteSize"]);
71
+ interval = int.Parse(dict["PollTime"]);
72
+ if (dict.TryGetValue("ProtocolProperties", out var nestedJson))
73
+ {
74
+ try
75
+ {
76
+ protocolProperties = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(nestedJson);
77
+ }
78
+ catch
79
+ {
80
+ protocolProperties = null;
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ public abstract class IOClient
87
+ {
88
+ public bool connected = false;
89
+ public string protocol;
90
+ public string moduleID;
91
+ protected List<IOMap> mappings = new();
92
+ protected long lastAttempt = 0;
93
+
94
+ protected IOClient(string protocol)
95
+ {
96
+ this.protocol = protocol;
97
+ }
98
+
99
+ public void AddMapping(IOMap map)
100
+ {
101
+ if (!mappings.Exists(m => m.localAddress == map.localAddress))
102
+ {
103
+ if (mappings.Count == 0)
104
+ {
105
+ moduleID = map.moduleID;
106
+
107
+ }
108
+ mappings.Add(map);
109
+ }
110
+ }
111
+
112
+ public bool HasMapping(string localAddress) => mappings.Exists(m => m.localAddress == localAddress);
113
+
114
+ public void Poll(NodalisEngine engine)
115
+ {
116
+ foreach (var map in mappings)
117
+ {
118
+ if (engine.ElapsedMilliseconds - map.lastPoll >= map.interval)
119
+ {
120
+ map.lastPoll = engine.ElapsedMilliseconds;
121
+ try
122
+ {
123
+ if (map.direction == IOType.Output)
124
+ {
125
+ switch (map.width)
126
+ {
127
+ case 1: WriteBit(map.remoteAddress, engine.ReadBit(map.localAddress) ? 1 : 0); break;
128
+ case 8: WriteByte(map.remoteAddress, engine.ReadByte(map.localAddress)); break;
129
+ case 16: WriteWord(map.remoteAddress, engine.ReadWord(map.localAddress)); break;
130
+ case 32: WriteDWord(map.remoteAddress, engine.ReadDWord(map.localAddress)); break;
131
+ }
132
+ }
133
+ else
134
+ {
135
+ switch (map.width)
136
+ {
137
+ case 1: if (ReadBit(map.remoteAddress, out var bit)) engine.WriteBit(map.localAddress, bit != 0); break;
138
+ case 8: if (ReadByte(map.remoteAddress, out var b)) engine.WriteByte(map.localAddress, b); break;
139
+ case 16: if (ReadWord(map.remoteAddress, out var w)) engine.WriteWord(map.localAddress, w); break;
140
+ case 32: if (ReadDWord(map.remoteAddress, out var d)) engine.WriteDWord(map.localAddress, d); break;
141
+ }
142
+ }
143
+ }
144
+ catch { }
145
+ }
146
+ }
147
+ }
148
+
149
+ public abstract void Connect();
150
+ public abstract bool ReadBit(string address, out int result);
151
+ public abstract bool WriteBit(string address, int value);
152
+ public abstract bool ReadByte(string address, out byte result);
153
+ public abstract bool WriteByte(string address, byte value);
154
+ public abstract bool ReadWord(string address, out ushort result);
155
+ public abstract bool WriteWord(string address, ushort value);
156
+ public abstract bool ReadDWord(string address, out uint result);
157
+ public abstract bool WriteDWord(string address, uint value);
158
+ }
159
+
160
+ public class FunctionBlock
161
+ {
162
+ private readonly ObjectInstance _jsObj;
163
+ private readonly Engine _engine;
164
+
165
+ public FunctionBlock(Engine engine, string className)
166
+ {
167
+ _engine = engine;
168
+ var constructor = engine.GetValue(className);
169
+ _jsObj = engine.Invoke(constructor).AsObject();
170
+ }
171
+
172
+ public void Set(string name, object value) =>
173
+ _jsObj.Set(name, JsValue.FromObject(_engine, value), throwOnError: true);
174
+
175
+ public T Get<T>(string name) =>
176
+ _jsObj.Get(name).ToObject() is T t ? t : default;
177
+
178
+ public void Call()
179
+ {
180
+ var callFn = _jsObj.Get("call");
181
+ _engine.Invoke(callFn, _jsObj);
182
+ }
183
+ }
184
+
185
+
186
+ public abstract partial class NodalisEngine
187
+ {
188
+ private readonly StaticStore _staticStore = new();
189
+ protected readonly Engine JsEngine = new Engine(cfg => { cfg.AllowClr(); });
190
+ private readonly List<IOClient> Clients = new();
191
+ private readonly DateTime StartTime = DateTime.UtcNow;
192
+
193
+ public long ElapsedMilliseconds => (long)(DateTime.UtcNow - StartTime).TotalMilliseconds;
194
+
195
+ public NodalisEngine()
196
+ {
197
+ InjectBindings();
198
+ }
199
+
200
+ public void Load(string code) => JsEngine.Execute(code);
201
+ public void Setup() => JsEngine.Invoke("setup");
202
+ public void Execute() => JsEngine.Invoke("run");
203
+ public FunctionBlock CreateFunctionBlock(string name)
204
+ {
205
+ return new FunctionBlock(JsEngine, name);
206
+ }
207
+
208
+ public void MapIO(string json)
209
+ {
210
+ try
211
+ {
212
+ var map = new IOMap(json);
213
+ var client = Clients.Find(c => c.HasMapping(map.localAddress) || c.moduleID == map.moduleID);
214
+ if (client == null)
215
+ {
216
+ client = CreateClient(map);
217
+ if (client != null)
218
+ {
219
+ client.Connect();
220
+ Clients.Add(client);
221
+ }
222
+ }
223
+ else client.AddMapping(map);
224
+ }
225
+ catch (Exception ex) { Console.WriteLine($"mapIO error: {ex.Message}"); }
226
+ }
227
+
228
+ public void SuperviseIO()
229
+ {
230
+ foreach (var client in Clients)
231
+ {
232
+ client.Poll(this);
233
+ }
234
+ }
235
+
236
+ protected virtual IOClient? CreateClient(IOMap map)
237
+ {
238
+ IOClient client = null;
239
+ if (map.protocol == "MODBUS-TCP")
240
+ client = new ModbusClient();
241
+ else if (map.protocol == "OPCUA")
242
+ client = new OPCClient();
243
+ if (client != null)
244
+ {
245
+ client.AddMapping(map);
246
+ }
247
+ return client;
248
+ }
249
+
250
+ public static bool GetBit(uint value, int bit)
251
+ {
252
+ return (value & (1u << bit)) != 0;
253
+ }
254
+
255
+ public static void SetBit(ref uint value, int bit, bool state)
256
+ {
257
+ value = state ? (value | (1u << bit)) : (value & ~(1u << bit));
258
+ }
259
+
260
+ public static bool GetBit<T>(RefVar<T> var, int bit) where T : struct
261
+ {
262
+ uint val = Convert.ToUInt32(var.Value);
263
+ return (val & (1u << bit)) != 0;
264
+ }
265
+
266
+ public static void SetBit<T>(ref RefVar<T> var, int bit, bool state) where T : struct
267
+ {
268
+ uint val = Convert.ToUInt32(var.Value);
269
+ val = state ? (val | (1u << bit)) : (val & ~(1u << bit));
270
+ var.Value = (T)Convert.ChangeType(val, typeof(T));
271
+ }
272
+
273
+ public abstract bool ReadBit(string address);
274
+ public abstract void WriteBit(string address, bool value);
275
+ public abstract byte ReadByte(string address);
276
+ public abstract void WriteByte(string address, byte value);
277
+ public abstract ushort ReadWord(string address);
278
+ public abstract void WriteWord(string address, ushort value);
279
+ public abstract uint ReadDWord(string address);
280
+ public abstract void WriteDWord(string address, uint value);
281
+
282
+ public object CreateReference(string address)
283
+ {
284
+ address = address.ToUpperInvariant();
285
+
286
+ Type type = typeof(bool);
287
+ if (address.Contains(".")) type = typeof(bool);
288
+ else if (address.Contains("W")) type = typeof(ushort);
289
+ else if (address.Contains("D")) type = typeof(uint);
290
+ else if (address.Contains("X")) type = typeof(byte);
291
+
292
+ var refVarType = typeof(RefVar<>).MakeGenericType(type);
293
+ var instance = Activator.CreateInstance(refVarType, this, address);
294
+ return instance;
295
+ }
296
+
297
+ private void InjectBindings()
298
+ {
299
+ JsEngine.SetValue("readBit", new Func<string, bool>(ReadBit));
300
+ JsEngine.SetValue("writeBit", new Action<string, bool>(WriteBit));
301
+ JsEngine.SetValue("readByte", new Func<string, byte>(ReadByte));
302
+ JsEngine.SetValue("writeByte", new Action<string, byte>(WriteByte));
303
+ JsEngine.SetValue("readWord", new Func<string, ushort>(ReadWord));
304
+ JsEngine.SetValue("writeWord", new Action<string, ushort>(WriteWord));
305
+ JsEngine.SetValue("readDWord", new Func<string, uint>(ReadDWord));
306
+ JsEngine.SetValue("writeDWord", new Action<string, uint>(WriteDWord));
307
+ JsEngine.SetValue("elapsed", new Func<long>(() => ElapsedMilliseconds));
308
+ JsEngine.SetValue("mapIO", new Action<string>(MapIO));
309
+ JsEngine.SetValue("superviseIO", new Action(SuperviseIO));
310
+ JsEngine.SetValue("writeDWord", new Action<string, uint>(WriteDWord));
311
+ JsEngine.SetValue("log", new Action<string>(Console.WriteLine));
312
+ JsEngine.SetValue("error", new Action<string>(Console.Error.WriteLine));
313
+
314
+ JsEngine.SetValue("getBit", new ClrFunctionInstance(JsEngine, "getBit", (thisObj, args) =>
315
+ {
316
+ if (args[0].IsObject())
317
+ {
318
+ var jsObj = args[0].AsObject();
319
+ var refObj = jsObj.ToObject();
320
+ if (refObj != null && refObj.GetType().IsGenericType && refObj.GetType().GetGenericTypeDefinition() == typeof(RefVar<>))
321
+ {
322
+
323
+ var bit = (int)args[1].AsNumber();
324
+ var method = typeof(NodalisEngine).GetMethod("GetBit").MakeGenericMethod(refObj.GetType().GetGenericArguments()[0]);
325
+ return (bool)method.Invoke(null, new[] { refObj, bit });
326
+ }
327
+ else
328
+ {
329
+ return false;
330
+ }
331
+ }
332
+ else
333
+ {
334
+ var value = (uint)args[0].AsNumber();
335
+ var bit = (int)args[1].AsNumber();
336
+ return GetBit(value, bit);
337
+ }
338
+ }));
339
+
340
+ JsEngine.SetValue("setBit", new ClrFunctionInstance(JsEngine, "setBit", (thisObj, args) =>
341
+ {
342
+ if (args[0].ToObject() is RefVar<bool> refVar)
343
+ {
344
+ var jsObj = args[0].AsObject();
345
+ var refObj = jsObj.ToObject();
346
+ var bit = (int)args[1].AsNumber();
347
+ var state = args[2].AsBoolean();
348
+ var method = typeof(NodalisEngine).GetMethod("SetBit", new[] { refObj.GetType(), typeof(int), typeof(bool) });
349
+ if (method != null)
350
+ {
351
+ var parameters = new object[] { refObj, bit, state };
352
+ method.Invoke(null, parameters);
353
+ }
354
+ return JsValue.Undefined;
355
+ }
356
+ else
357
+ {
358
+ var value = (uint)args[0].AsNumber();
359
+ var bit = (int)args[1].AsNumber();
360
+ var state = args[2].AsBoolean();
361
+ SetBit(ref value, bit, state);
362
+ return JsValue.FromObject(JsEngine, value);
363
+ }
364
+ }));
365
+
366
+ JsEngine.SetValue("createReference", new Func<string, object>(CreateReference));
367
+
368
+
369
+ JsEngine.SetValue("newStatic", new ClrFunctionInstance(JsEngine, "newStatic", (thisObj, args) =>
370
+ {
371
+ var key = args[0].AsString();
372
+ var jsCtor = args[1];
373
+
374
+ if (!_staticStore.TryGetValue(key, out var instance))
375
+ {
376
+ var jsInstance = JsEngine.Invoke(jsCtor);
377
+ _staticStore[key] = jsInstance;
378
+ return jsInstance;
379
+ }
380
+
381
+ return (JsValue)_staticStore[key];
382
+ }));
383
+
384
+ JsEngine.SetValue("resolve", new ClrFunctionInstance(JsEngine, "resolve", (thisObj, args) =>
385
+ {
386
+ var val = args[0].ToObject();
387
+ if (val != null && val.GetType().IsGenericType &&
388
+ val.GetType().GetGenericTypeDefinition() == typeof(RefVar<>))
389
+ {
390
+ var valueProp = val.GetType().GetProperty("Value");
391
+ return JsValue.FromObject(JsEngine, valueProp.GetValue(val));
392
+ }
393
+ return args[0];
394
+ }));
395
+
396
+ var types = new[] {
397
+ typeof(TON), typeof(TOF), typeof(TP), typeof(AND), typeof(OR), typeof(NOT), typeof(XOR),
398
+ typeof(NAND), typeof(NOR), typeof(SR), typeof(RS), typeof(R_TRIG), typeof(F_TRIG),
399
+ typeof(CTU), typeof(CTD), typeof(CTUD), typeof(EQ), typeof(NE), typeof(LT),
400
+ typeof(GT), typeof(GE), typeof(LE), typeof(MOVE), typeof(SEL), typeof(MUX),
401
+ typeof(MIN), typeof(MAX), typeof(LIMIT), typeof(ASSIGNMENT)
402
+ };
403
+ foreach (var t in types)
404
+ JsEngine.SetValue(t.Name, TypeReference.CreateTypeReference(JsEngine, t));
405
+ }
406
+ }
407
+
408
+
409
+ public class RefVar<T> where T : struct
410
+ {
411
+ public static implicit operator T(RefVar<T> r)
412
+ {
413
+ return r.Value;
414
+ }
415
+
416
+ private readonly NodalisEngine _engine;
417
+ private readonly string _address;
418
+
419
+ public RefVar(NodalisEngine engine, string address)
420
+ {
421
+ _engine = engine;
422
+ _address = address;
423
+ }
424
+
425
+ public T Value
426
+ {
427
+ get => Read();
428
+ set => Write(value);
429
+ }
430
+
431
+ public string Address => _address;
432
+
433
+ private T Read()
434
+ {
435
+ if (typeof(T) == typeof(bool))
436
+ return (T)(object)_engine.ReadBit(_address);
437
+ if (typeof(T) == typeof(byte))
438
+ return (T)(object)_engine.ReadByte(_address);
439
+ if (typeof(T) == typeof(ushort))
440
+ return (T)(object)_engine.ReadWord(_address);
441
+ if (typeof(T) == typeof(uint))
442
+ return (T)(object)_engine.ReadDWord(_address);
443
+ throw new NotSupportedException($"Unsupported RefVar type: {typeof(T)}");
444
+ }
445
+
446
+ private void Write(T value)
447
+ {
448
+ if (typeof(T) == typeof(bool))
449
+ _engine.WriteBit(_address, (bool)(object)value);
450
+ else if (typeof(T) == typeof(byte))
451
+ _engine.WriteByte(_address, (byte)(object)value);
452
+ else if (typeof(T) == typeof(ushort))
453
+ _engine.WriteWord(_address, (ushort)(object)value);
454
+ else if (typeof(T) == typeof(uint))
455
+ _engine.WriteDWord(_address, (uint)(object)value);
456
+ else throw new NotSupportedException($"Unsupported RefVar type: {typeof(T)}");
457
+ }
458
+ }
459
+
460
+ public class TON
461
+ {
462
+ public bool IN;
463
+ public long PT;
464
+ public bool Q;
465
+ public long ET;
466
+ private long start = 0;
467
+
468
+ public void call()
469
+ {
470
+ if (IN)
471
+ {
472
+ if (start == 0) start = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
473
+ ET = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - start;
474
+ Q = ET >= PT;
475
+ }
476
+ else
477
+ {
478
+ start = 0;
479
+ ET = 0;
480
+ Q = false;
481
+ }
482
+ }
483
+ }
484
+
485
+ public class TOF
486
+ {
487
+ public bool IN;
488
+ public long PT;
489
+ public bool Q;
490
+ public long ET;
491
+ private long start = 0;
492
+
493
+ public void call()
494
+ {
495
+ if (IN)
496
+ {
497
+ Q = true;
498
+ start = 0;
499
+ ET = 0;
500
+ }
501
+ else if (Q)
502
+ {
503
+ if (start == 0) start = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
504
+ ET = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - start;
505
+ if (ET >= PT) Q = false;
506
+ }
507
+ }
508
+ }
509
+
510
+ public class TP
511
+ {
512
+ public bool IN;
513
+ public long PT;
514
+ public bool Q;
515
+ public long ET;
516
+ private bool lastIN = false;
517
+ private long start = 0;
518
+
519
+ public void call()
520
+ {
521
+ Q = false;
522
+ if (!lastIN && IN)
523
+ {
524
+ lastIN = IN;
525
+ ET = 0;
526
+ start = 0;
527
+ }
528
+ if (IN)
529
+ {
530
+ Q = true;
531
+ }
532
+ else if (lastIN && !IN)
533
+ {
534
+ if (start == 0) start = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
535
+ ET = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - start;
536
+ if (PT >= ET) Q = true;
537
+ else lastIN = false;
538
+ }
539
+ }
540
+ }
541
+
542
+ public class AND
543
+ {
544
+ public bool IN1;
545
+ public bool IN2;
546
+ public bool OUT;
547
+ public void call() => OUT = IN1 && IN2;
548
+ }
549
+
550
+ public class OR
551
+ {
552
+ public bool IN1;
553
+ public bool IN2;
554
+ public bool OUT;
555
+ public void call() => OUT = IN1 || IN2;
556
+ }
557
+
558
+ public class NOT
559
+ {
560
+ public bool IN;
561
+ public bool OUT;
562
+ public void call() => OUT = !IN;
563
+ }
564
+
565
+ public class XOR
566
+ {
567
+ public bool IN1;
568
+ public bool IN2;
569
+ public bool OUT;
570
+ public void call() => OUT = IN1 ^ IN2;
571
+ }
572
+
573
+ public class NAND
574
+ {
575
+ public bool IN1;
576
+ public bool IN2;
577
+ public bool OUT;
578
+ public void call() => OUT = !(IN1 && IN2);
579
+ }
580
+
581
+ public class NOR
582
+ {
583
+ public bool IN1;
584
+ public bool IN2;
585
+ public bool OUT;
586
+ public void call() => OUT = !(IN1 || IN2);
587
+ }
588
+
589
+ public class SR
590
+ {
591
+ public bool S1;
592
+ public bool R;
593
+ public bool Q1;
594
+ public void call()
595
+ {
596
+ if (R) Q1 = false;
597
+ if (S1) Q1 = true;
598
+ }
599
+ }
600
+
601
+ public class RS
602
+ {
603
+ public bool S;
604
+ public bool R1;
605
+ public bool Q1;
606
+ public void call()
607
+ {
608
+ if (S) Q1 = true;
609
+ if (R1) Q1 = false;
610
+ }
611
+ }
612
+
613
+ public class R_TRIG
614
+ {
615
+ public bool CLK;
616
+ public bool OUT;
617
+ private bool last;
618
+ public void call()
619
+ {
620
+ OUT = CLK && !last;
621
+ last = CLK;
622
+ }
623
+ }
624
+
625
+ public class F_TRIG
626
+ {
627
+ public bool CLK;
628
+ public bool OUT;
629
+ private bool last;
630
+ public void call()
631
+ {
632
+ OUT = !CLK && last;
633
+ last = CLK;
634
+ }
635
+ }
636
+
637
+ public class CTU
638
+ {
639
+ public bool CU;
640
+ public bool R;
641
+ public ushort PV;
642
+ public ushort CV;
643
+ public bool Q;
644
+ private bool lastCU;
645
+
646
+ public void call()
647
+ {
648
+ if (R)
649
+ CV = 0;
650
+ else if (CU && !lastCU)
651
+ CV++;
652
+ Q = CV >= PV;
653
+ lastCU = CU;
654
+ }
655
+ }
656
+
657
+ public class CTD
658
+ {
659
+ public bool CD;
660
+ public bool LD;
661
+ public ushort PV;
662
+ public ushort CV;
663
+ public bool Q;
664
+ private bool lastCD;
665
+
666
+ public void call()
667
+ {
668
+ if (LD)
669
+ CV = PV;
670
+ else if (CD && !lastCD && CV > 0)
671
+ CV--;
672
+ Q = CV == 0;
673
+ lastCD = CD;
674
+ }
675
+ }
676
+
677
+ public class CTUD
678
+ {
679
+ public bool CU;
680
+ public bool CD;
681
+ public bool R;
682
+ public bool LD;
683
+ public ushort PV;
684
+ public ushort CV;
685
+ public bool QU;
686
+ public bool QD;
687
+ private bool lastCU;
688
+ private bool lastCD;
689
+
690
+ public void call()
691
+ {
692
+ if (R)
693
+ CV = 0;
694
+ else if (LD)
695
+ CV = PV;
696
+ else
697
+ {
698
+ if (CU && !lastCU) CV++;
699
+ if (CD && !lastCD && CV > 0) CV--;
700
+ }
701
+ QU = CV >= PV;
702
+ QD = CV == 0;
703
+ lastCU = CU;
704
+ lastCD = CD;
705
+ }
706
+ }
707
+
708
+ public class EQ
709
+ {
710
+ public uint IN1;
711
+ public uint IN2;
712
+ public bool OUT;
713
+ public void call() => OUT = IN1 == IN2;
714
+ }
715
+
716
+ public class NE
717
+ {
718
+ public uint IN1;
719
+ public uint IN2;
720
+ public bool OUT;
721
+ public void call() => OUT = IN1 != IN2;
722
+ }
723
+
724
+ public class LT
725
+ {
726
+ public uint IN1;
727
+ public uint IN2;
728
+ public bool OUT;
729
+ public void call() => OUT = IN1 < IN2;
730
+ }
731
+
732
+ public class GT
733
+ {
734
+ public uint IN1;
735
+ public uint IN2;
736
+ public bool OUT;
737
+ public void call() => OUT = IN1 > IN2;
738
+ }
739
+
740
+ public class GE
741
+ {
742
+ public uint IN1;
743
+ public uint IN2;
744
+ public bool OUT;
745
+ public void call() => OUT = IN1 >= IN2;
746
+ }
747
+
748
+ public class LE
749
+ {
750
+ public uint IN1;
751
+ public uint IN2;
752
+ public bool OUT;
753
+ public void call() => OUT = IN1 <= IN2;
754
+ }
755
+
756
+ public class MOVE
757
+ {
758
+ public uint IN;
759
+ public uint OUT;
760
+ public void call() => OUT = IN;
761
+ }
762
+
763
+ public class SEL
764
+ {
765
+ public bool G;
766
+ public uint IN0;
767
+ public uint IN1;
768
+ public uint OUT;
769
+ public void call() => OUT = G ? IN1 : IN0;
770
+ }
771
+
772
+ public class MUX
773
+ {
774
+ public bool K;
775
+ public uint IN0;
776
+ public uint IN1;
777
+ public uint OUT;
778
+ public void call() => OUT = K ? IN1 : IN0;
779
+ }
780
+
781
+ public class MIN
782
+ {
783
+ public uint IN1;
784
+ public uint IN2;
785
+ public uint OUT;
786
+ public void call() => OUT = Math.Min(IN1, IN2);
787
+ }
788
+
789
+ public class MAX
790
+ {
791
+ public uint IN1;
792
+ public uint IN2;
793
+ public uint OUT;
794
+ public void call() => OUT = Math.Max(IN1, IN2);
795
+ }
796
+
797
+ public class LIMIT
798
+ {
799
+ public uint MN;
800
+ public uint IN;
801
+ public uint MX;
802
+ public uint OUT;
803
+ public void call()
804
+ {
805
+ if (IN < MN) OUT = MN;
806
+ else if (IN > MX) OUT = MX;
807
+ else OUT = IN;
808
+ }
809
+ }
810
+
811
+ public class ASSIGNMENT
812
+ {
813
+ public bool IN;
814
+ public bool OUT;
815
+ public void call() => OUT = IN;
816
+ }
817
+ }