fprime-gds 4.0.0a8__py3-none-any.whl → 4.0.0a10__py3-none-any.whl
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.
- fprime_gds/common/fpy/README.md +56 -0
- fprime_gds/common/fpy/SPEC.md +69 -0
- fprime_gds/common/fpy/bytecode/__init__.py +0 -0
- fprime_gds/common/fpy/bytecode/directives.py +490 -0
- fprime_gds/common/fpy/codegen.py +1687 -0
- fprime_gds/common/fpy/grammar.lark +88 -0
- fprime_gds/common/fpy/main.py +40 -0
- fprime_gds/common/fpy/parser.py +239 -0
- fprime_gds/common/templates/cmd_template.py +8 -0
- fprime_gds/executables/cli.py +31 -16
- fprime_gds/executables/data_product_writer.py +66 -30
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/METADATA +2 -1
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/RECORD +18 -12
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/entry_points.txt +1 -1
- fprime_gds/common/fpy/serialize_bytecode.py +0 -229
- fprime_gds/common/fpy/types.py +0 -203
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/WHEEL +0 -0
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/licenses/LICENSE.txt +0 -0
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/licenses/NOTICE.txt +0 -0
- {fprime_gds-4.0.0a8.dist-info → fprime_gds-4.0.0a10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
# Fpy Advanced Sequencing Language Version 0.1
|
2
|
+
The Fpy advanced sequencing language is a combination of a high-level scripting language and a low-level bytecode language for running complex command sequences on spacecraft flight software.
|
3
|
+
## Fpy Syntax
|
4
|
+
### Modules, components, channels, commands and types
|
5
|
+
You can imagine the Fpy syntax as Python with the following mappings:
|
6
|
+
1. FPrime modules become Python namespaces
|
7
|
+
2. FPrime components become Python classes
|
8
|
+
3. FPrime types (structs, arrays and enums) become Python classes
|
9
|
+
4. FPrime component instances become Python object instances
|
10
|
+
5. FPrime commands become member functions of Python object instances
|
11
|
+
6. FPrime telemetry channels become member properties of Python object instances
|
12
|
+
|
13
|
+
FPrime declaration:
|
14
|
+
```
|
15
|
+
module Ref {
|
16
|
+
passive component ExampleComponent {
|
17
|
+
telemetry testChannel: U8
|
18
|
+
sync command TEST_COMMAND(arg: string size 40)
|
19
|
+
}
|
20
|
+
|
21
|
+
instance exampleInstance: ExampleComponent base id 0x01
|
22
|
+
}
|
23
|
+
```
|
24
|
+
Fpy usage:
|
25
|
+
```py
|
26
|
+
# reference a telemetry channel
|
27
|
+
Ref.exampleInstance.testChannel
|
28
|
+
# call a command
|
29
|
+
Ref.exampleInstance.TEST_COMMAND("arg value")
|
30
|
+
```
|
31
|
+
|
32
|
+
|
33
|
+
FPrime declaration:
|
34
|
+
```
|
35
|
+
struct ExampleStruct {
|
36
|
+
member: F32
|
37
|
+
}
|
38
|
+
|
39
|
+
enum TestEnum {
|
40
|
+
ONE
|
41
|
+
TWO
|
42
|
+
THREE
|
43
|
+
}
|
44
|
+
|
45
|
+
array TestArray = [3] U8
|
46
|
+
```
|
47
|
+
|
48
|
+
Fpy usage:
|
49
|
+
```py
|
50
|
+
# construct a struct
|
51
|
+
ExampleStruct(0.0)
|
52
|
+
# reference an enum const
|
53
|
+
TestEnum.THREE
|
54
|
+
# construct an array
|
55
|
+
TestArray(1, 2, 3)
|
56
|
+
```
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Nothing type is a type whose set of values is an empty set
|
2
|
+
Unit type is a type whose set of values is a set with one element
|
3
|
+
|
4
|
+
# `if` statement
|
5
|
+
|
6
|
+
## Syntactical and semantic checks
|
7
|
+
|
8
|
+
`"if" condition ":" INDENT stmt* DEDENT ("elif" condition ":" INDENT stmt* DEDENT)* ["else" ":" INDENT stmt* DEDENT]`
|
9
|
+
|
10
|
+
1. where `condition` is an expression which evaluates to a boolean
|
11
|
+
2. where `stmt` is a statement
|
12
|
+
|
13
|
+
## Code generation
|
14
|
+
|
15
|
+
1. `if` generates `IF`, followed by the generated code for the first body, followed by `GOTO` to the end of the if statement
|
16
|
+
2. `elif` generates `IF`, followed by the generated code for its body, followed by `GOTO` to the end of the if statement
|
17
|
+
3. `else` generates the code for its body
|
18
|
+
|
19
|
+
# `not` boolean operator
|
20
|
+
|
21
|
+
## Syntactical and semantic checks
|
22
|
+
|
23
|
+
`"not" value` evaluates to a boolean at runtime
|
24
|
+
|
25
|
+
1. where `value` is an expression which evaluates to a boolean
|
26
|
+
|
27
|
+
## Code generation
|
28
|
+
|
29
|
+
1. `not` generates `NOT`
|
30
|
+
|
31
|
+
# `and` and `or` boolean operators
|
32
|
+
|
33
|
+
## Syntactical and semantic checks
|
34
|
+
|
35
|
+
`value (op value)+` evaluates to a boolean at runtime
|
36
|
+
|
37
|
+
1. where `op: "and"|"or"`
|
38
|
+
2. where `value` is an expression which evaluates to a boolean
|
39
|
+
|
40
|
+
## Code generation
|
41
|
+
|
42
|
+
1. Each `and` or `or` between two `value`s generates an `AND` or `OR`, respectively
|
43
|
+
|
44
|
+
# Infix comparisons
|
45
|
+
|
46
|
+
## Syntactical and semantic checks
|
47
|
+
|
48
|
+
`lhs op rhs` evaluates to a boolean at runtime
|
49
|
+
|
50
|
+
1. where `op: ">" | "<" | "<=" | ">=" | "==" | "!="`
|
51
|
+
2. and `lhs`, `rhs` are expressions which evaluate to a number
|
52
|
+
|
53
|
+
If either `lhs` or `rhs` evaluate to a float:
|
54
|
+
3. both `lhs` and `rhs` must evaluate to floats of the same bit width
|
55
|
+
|
56
|
+
Otherwise, `lhs` and `rhs` evaluate to integer values. All comparisons between integer values are valid.
|
57
|
+
|
58
|
+
## Code generation
|
59
|
+
|
60
|
+
### Equality comparisons
|
61
|
+
|
62
|
+
1. `==` or `!=` between two floats generates `FEQ` or `FNE`, respectively
|
63
|
+
2. `==` or `!=` between two ints generates `IEQ` or `INE`, respectively
|
64
|
+
|
65
|
+
### Inequality comparisons
|
66
|
+
|
67
|
+
1. `>`, `<`, `<=`, or `>=` between two floats generates `FGT`, `FLT`, `FLE` or `FGE`, respectively
|
68
|
+
2. `>`, `<`, `<=`, or `>=` between two unsigned ints generates `UGT`, `ULT`, `ULE` or `UGE`, respectively
|
69
|
+
2. `>`, `<`, `<=`, or `>=` between two ints, where at least one is signed, generates `SGT`, `SLT`, `SLE` or `SGE`, respectively
|
File without changes
|
@@ -0,0 +1,490 @@
|
|
1
|
+
from dataclasses import astuple, dataclass
|
2
|
+
from pathlib import Path
|
3
|
+
import struct
|
4
|
+
from typing import ClassVar
|
5
|
+
import zlib
|
6
|
+
from fprime.common.models.serialize.time_type import TimeType
|
7
|
+
from fprime.common.models.serialize.numerical_types import (
|
8
|
+
U32Type,
|
9
|
+
U16Type,
|
10
|
+
U64Type,
|
11
|
+
U8Type,
|
12
|
+
I64Type,
|
13
|
+
)
|
14
|
+
from fprime.common.models.serialize.bool_type import BoolType
|
15
|
+
from enum import Enum
|
16
|
+
|
17
|
+
FwSizeType = U64Type
|
18
|
+
FwChanIdType = U32Type
|
19
|
+
FwPrmIdType = U32Type
|
20
|
+
FwOpcodeType = U32Type
|
21
|
+
|
22
|
+
MAX_SERIALIZABLE_REGISTER_SIZE = 512 - 4 - 4
|
23
|
+
|
24
|
+
|
25
|
+
class DirectiveOpcode(Enum):
|
26
|
+
INVALID = 0
|
27
|
+
WAIT_REL = 1
|
28
|
+
WAIT_ABS = 2
|
29
|
+
SET_SER_REG = 3
|
30
|
+
GOTO = 4
|
31
|
+
IF = 5
|
32
|
+
NO_OP = 6
|
33
|
+
GET_TLM = 7
|
34
|
+
GET_PRM = 8
|
35
|
+
CMD = 9
|
36
|
+
SET_REG = 10
|
37
|
+
DESER_SER_REG_8 = 11
|
38
|
+
DESER_SER_REG_4 = 12
|
39
|
+
DESER_SER_REG_2 = 13
|
40
|
+
DESER_SER_REG_1 = 14
|
41
|
+
# binary reg op directives
|
42
|
+
# all of these are handled at the CPP level by one BinaryRegOpDirective
|
43
|
+
# boolean ops
|
44
|
+
OR = 15
|
45
|
+
AND = 16
|
46
|
+
# integer equalities
|
47
|
+
IEQ = 17
|
48
|
+
INE = 18
|
49
|
+
# unsigned integer inequalities
|
50
|
+
ULT = 19
|
51
|
+
ULE = 20
|
52
|
+
UGT = 21
|
53
|
+
UGE = 22
|
54
|
+
# signed integer inequalities
|
55
|
+
SLT = 23
|
56
|
+
SLE = 24
|
57
|
+
SGT = 25
|
58
|
+
SGE = 26
|
59
|
+
# floating point equalities
|
60
|
+
FEQ = 27
|
61
|
+
FNE = 28
|
62
|
+
# floating point inequalities
|
63
|
+
FLT = 29
|
64
|
+
FLE = 30
|
65
|
+
FGT = 31
|
66
|
+
FGE = 32
|
67
|
+
# end binary reg op directives
|
68
|
+
|
69
|
+
# unary reg op dirs
|
70
|
+
NOT = 33
|
71
|
+
# floating point extension and truncation
|
72
|
+
FPEXT = 34
|
73
|
+
FPTRUNC = 35
|
74
|
+
# floating point conversion to signed/unsigned integer,
|
75
|
+
# and vice versa
|
76
|
+
FPTOSI = 36
|
77
|
+
FPTOUI = 37
|
78
|
+
SITOFP = 38
|
79
|
+
UITOFP = 39
|
80
|
+
# end unary reg op dirs
|
81
|
+
|
82
|
+
EXIT = 40
|
83
|
+
|
84
|
+
|
85
|
+
class Directive:
|
86
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.INVALID
|
87
|
+
|
88
|
+
def serialize(self) -> bytes:
|
89
|
+
arg_bytes = self.serialize_args()
|
90
|
+
|
91
|
+
output = U8Type(self.opcode.value).serialize()
|
92
|
+
output += U16Type(len(arg_bytes)).serialize()
|
93
|
+
output += arg_bytes
|
94
|
+
|
95
|
+
return output
|
96
|
+
|
97
|
+
def serialize_args(self) -> bytes:
|
98
|
+
raise NotImplementedError("serialize_args not implemented")
|
99
|
+
|
100
|
+
|
101
|
+
HEADER_FORMAT = "!BBBBBHI"
|
102
|
+
HEADER_SIZE = struct.calcsize(HEADER_FORMAT)
|
103
|
+
|
104
|
+
|
105
|
+
@dataclass
|
106
|
+
class Header:
|
107
|
+
majorVersion: int
|
108
|
+
minorVersion: int
|
109
|
+
patchVersion: int
|
110
|
+
schemaVersion: int
|
111
|
+
argumentCount: int
|
112
|
+
statementCount: int
|
113
|
+
bodySize: int
|
114
|
+
|
115
|
+
|
116
|
+
FOOTER_FORMAT = "!I"
|
117
|
+
FOOTER_SIZE = struct.calcsize(FOOTER_FORMAT)
|
118
|
+
|
119
|
+
|
120
|
+
@dataclass
|
121
|
+
class Footer:
|
122
|
+
crc: int
|
123
|
+
|
124
|
+
|
125
|
+
def serialize_directives(dirs: list[Directive], output: Path = None):
|
126
|
+
output_bytes = bytes()
|
127
|
+
|
128
|
+
for dir in dirs:
|
129
|
+
output_bytes += dir.serialize()
|
130
|
+
|
131
|
+
header = Header(0, 0, 0, 1, 0, len(dirs), len(output_bytes))
|
132
|
+
output_bytes = struct.pack(HEADER_FORMAT, *astuple(header)) + output_bytes
|
133
|
+
|
134
|
+
crc = zlib.crc32(output_bytes) % (1 << 32)
|
135
|
+
footer = Footer(crc)
|
136
|
+
output_bytes += struct.pack(FOOTER_FORMAT, *astuple(footer))
|
137
|
+
|
138
|
+
if output is None:
|
139
|
+
output = input.with_suffix(".bin")
|
140
|
+
|
141
|
+
output.write_bytes(output_bytes)
|
142
|
+
|
143
|
+
|
144
|
+
@dataclass
|
145
|
+
class WaitRelDirective(Directive):
|
146
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.WAIT_REL
|
147
|
+
seconds: int
|
148
|
+
useconds: int
|
149
|
+
|
150
|
+
def serialize_args(self) -> bytes:
|
151
|
+
return U32Type(self.seconds).serialize() + U32Type(self.useconds).serialize()
|
152
|
+
|
153
|
+
|
154
|
+
@dataclass
|
155
|
+
class WaitAbsDirective(Directive):
|
156
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.WAIT_ABS
|
157
|
+
wakeup_time: TimeType
|
158
|
+
|
159
|
+
def serialize_args(self) -> bytes:
|
160
|
+
return self.wakeup_time.serialize()
|
161
|
+
|
162
|
+
|
163
|
+
@dataclass
|
164
|
+
class SetSerRegDirective(Directive):
|
165
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SET_SER_REG
|
166
|
+
|
167
|
+
index: int
|
168
|
+
"""U8: The index of the local variable to set."""
|
169
|
+
value: bytes
|
170
|
+
"""[Fpy.MAX_SERIALIZABLE_REGISTER_SIZE] U8: The value of the local variable."""
|
171
|
+
|
172
|
+
def serialize_args(self) -> bytes:
|
173
|
+
data = bytearray()
|
174
|
+
data.extend(U8Type(self.index).serialize())
|
175
|
+
data.extend(self.value)
|
176
|
+
return bytes(data)
|
177
|
+
|
178
|
+
|
179
|
+
@dataclass
|
180
|
+
class GotoDirective(Directive):
|
181
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GOTO
|
182
|
+
statement_index: int
|
183
|
+
"""U32: The statement index to execute next."""
|
184
|
+
|
185
|
+
def serialize_args(self) -> bytes:
|
186
|
+
return U32Type(self.statement_index).serialize()
|
187
|
+
|
188
|
+
|
189
|
+
@dataclass
|
190
|
+
class IfDirective(Directive):
|
191
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.IF
|
192
|
+
conditional_reg: int
|
193
|
+
"""U8: The register to branch based off of (interpreted as a C++ boolean)."""
|
194
|
+
false_goto_stmt_index: int
|
195
|
+
"""U32: The statement index to go to if the register is false."""
|
196
|
+
|
197
|
+
def serialize_args(self) -> bytes:
|
198
|
+
return (
|
199
|
+
U8Type(self.conditional_reg).serialize()
|
200
|
+
+ U32Type(self.false_goto_stmt_index).serialize()
|
201
|
+
)
|
202
|
+
|
203
|
+
|
204
|
+
@dataclass
|
205
|
+
class NoOpDirective(Directive):
|
206
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.NO_OP
|
207
|
+
|
208
|
+
def serialize_args(self) -> bytes:
|
209
|
+
return bytes()
|
210
|
+
|
211
|
+
|
212
|
+
@dataclass
|
213
|
+
class GetTlmDirective(Directive):
|
214
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GET_TLM
|
215
|
+
value_dest_sreg: int
|
216
|
+
"""U8: The local variable to store the telemetry value in."""
|
217
|
+
time_dest_sreg: int
|
218
|
+
"""U8: The local variable to store the telemetry time in."""
|
219
|
+
chan_id: int
|
220
|
+
"""FwChanIdType: The telemetry channel ID to get."""
|
221
|
+
|
222
|
+
def serialize_args(self) -> bytes:
|
223
|
+
data = bytearray()
|
224
|
+
data.extend(U8Type(self.value_dest_sreg).serialize())
|
225
|
+
data.extend(U8Type(self.time_dest_sreg).serialize())
|
226
|
+
data.extend(FwChanIdType(self.chan_id).serialize())
|
227
|
+
return bytes(data)
|
228
|
+
|
229
|
+
|
230
|
+
@dataclass
|
231
|
+
class GetPrmDirective(Directive):
|
232
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GET_PRM
|
233
|
+
dest_sreg_index: int
|
234
|
+
"""U8: The local variable to store the parameter value in."""
|
235
|
+
prm_id: int
|
236
|
+
"""FwPrmIdType: The parameter ID to get the value of."""
|
237
|
+
|
238
|
+
def serialize_args(self) -> bytes:
|
239
|
+
return (
|
240
|
+
U8Type(self.dest_sreg_index).serialize()
|
241
|
+
+ FwPrmIdType(self.prm_id).serialize()
|
242
|
+
)
|
243
|
+
|
244
|
+
|
245
|
+
@dataclass
|
246
|
+
class CmdDirective(Directive):
|
247
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.CMD
|
248
|
+
op_code: int
|
249
|
+
"""FwOpcodeType: The opcode of the command."""
|
250
|
+
arg_buf: bytes
|
251
|
+
"""[Fpy.MAX_SERIALIZABLE_REGISTER_SIZE] U8: The argument buffer of the command."""
|
252
|
+
|
253
|
+
def serialize_args(self) -> bytes:
|
254
|
+
data = bytearray()
|
255
|
+
data.extend(FwOpcodeType(self.op_code).serialize())
|
256
|
+
data.extend(self.arg_buf)
|
257
|
+
return bytes(data)
|
258
|
+
|
259
|
+
|
260
|
+
@dataclass
|
261
|
+
class _DeserSerRegDirective(Directive):
|
262
|
+
"""
|
263
|
+
Deserializes up to 8 bytes from a local variable into a register.
|
264
|
+
"""
|
265
|
+
|
266
|
+
src_sreg_idx: int
|
267
|
+
"""U8: The local variable to deserialize from."""
|
268
|
+
src_offset: int
|
269
|
+
"""FwSizeType: The starting offset to deserialize from."""
|
270
|
+
dest_reg: int
|
271
|
+
"""U8: The destination register to deserialize into."""
|
272
|
+
|
273
|
+
def serialize_args(self) -> bytes:
|
274
|
+
data = bytearray()
|
275
|
+
data.extend(U8Type(self.src_sreg_idx).serialize())
|
276
|
+
data.extend(FwSizeType(self.src_offset).serialize())
|
277
|
+
data.extend(U8Type(self.dest_reg).serialize())
|
278
|
+
return bytes(data)
|
279
|
+
|
280
|
+
|
281
|
+
class DeserSerReg8Directive(_DeserSerRegDirective):
|
282
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_8
|
283
|
+
|
284
|
+
|
285
|
+
class DeserSerReg4Directive(_DeserSerRegDirective):
|
286
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_4
|
287
|
+
|
288
|
+
|
289
|
+
class DeserSerReg2Directive(_DeserSerRegDirective):
|
290
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_2
|
291
|
+
|
292
|
+
|
293
|
+
class DeserSerReg1Directive(_DeserSerRegDirective):
|
294
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_1
|
295
|
+
|
296
|
+
|
297
|
+
@dataclass
|
298
|
+
class SetRegDirective(Directive):
|
299
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SET_REG
|
300
|
+
|
301
|
+
dest: int
|
302
|
+
"""U8: The register to store the value in."""
|
303
|
+
value: int
|
304
|
+
"""I64: The value to store in the register."""
|
305
|
+
|
306
|
+
def serialize_args(self) -> bytes:
|
307
|
+
return U8Type(self.dest).serialize() + I64Type(self.value).serialize()
|
308
|
+
|
309
|
+
|
310
|
+
@dataclass
|
311
|
+
class _BinaryRegOpDirective(Directive):
|
312
|
+
lhs: int
|
313
|
+
"""U8: The left-hand side register for comparison."""
|
314
|
+
rhs: int
|
315
|
+
"""U8: The right-hand side register for comparison."""
|
316
|
+
res: int
|
317
|
+
"""U8: The destination register for the boolean result."""
|
318
|
+
|
319
|
+
def serialize_args(self) -> bytes:
|
320
|
+
data = bytearray()
|
321
|
+
data.extend(U8Type(self.lhs).serialize())
|
322
|
+
data.extend(U8Type(self.rhs).serialize())
|
323
|
+
data.extend(U8Type(self.res).serialize())
|
324
|
+
return bytes(data)
|
325
|
+
|
326
|
+
|
327
|
+
class OrDirective(_BinaryRegOpDirective):
|
328
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.OR
|
329
|
+
|
330
|
+
|
331
|
+
class AndDirective(_BinaryRegOpDirective):
|
332
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.AND
|
333
|
+
|
334
|
+
|
335
|
+
class IntEqualDirective(_BinaryRegOpDirective):
|
336
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.IEQ
|
337
|
+
|
338
|
+
|
339
|
+
class IntNotEqualDirective(_BinaryRegOpDirective):
|
340
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.INE
|
341
|
+
|
342
|
+
|
343
|
+
class UnsignedLessThanDirective(_BinaryRegOpDirective):
|
344
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.ULT
|
345
|
+
|
346
|
+
|
347
|
+
class UnsignedLessThanOrEqualDirective(_BinaryRegOpDirective):
|
348
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.ULE
|
349
|
+
|
350
|
+
|
351
|
+
class UnsignedGreaterThanDirective(_BinaryRegOpDirective):
|
352
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UGT
|
353
|
+
|
354
|
+
|
355
|
+
class UnsignedGreaterThanOrEqualDirective(_BinaryRegOpDirective):
|
356
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UGE
|
357
|
+
|
358
|
+
|
359
|
+
class SignedLessThanDirective(_BinaryRegOpDirective):
|
360
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SLT
|
361
|
+
|
362
|
+
|
363
|
+
class SignedLessThanOrEqualDirective(_BinaryRegOpDirective):
|
364
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SLE
|
365
|
+
|
366
|
+
|
367
|
+
class SignedGreaterThanDirective(_BinaryRegOpDirective):
|
368
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SGT
|
369
|
+
|
370
|
+
|
371
|
+
class SignedGreaterThanOrEqualDirective(_BinaryRegOpDirective):
|
372
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SGE
|
373
|
+
|
374
|
+
|
375
|
+
class FloatGreaterThanOrEqualDirective(_BinaryRegOpDirective):
|
376
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FGE
|
377
|
+
|
378
|
+
|
379
|
+
class FloatLessThanOrEqualDirective(_BinaryRegOpDirective):
|
380
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FLE
|
381
|
+
|
382
|
+
|
383
|
+
class FloatLessThanDirective(_BinaryRegOpDirective):
|
384
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FLT
|
385
|
+
|
386
|
+
|
387
|
+
class FloatGreaterThanDirective(_BinaryRegOpDirective):
|
388
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FGT
|
389
|
+
|
390
|
+
|
391
|
+
class FloatEqualDirective(_BinaryRegOpDirective):
|
392
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FEQ
|
393
|
+
|
394
|
+
|
395
|
+
class FloatNotEqualDirective(_BinaryRegOpDirective):
|
396
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FNE
|
397
|
+
|
398
|
+
|
399
|
+
@dataclass
|
400
|
+
class _UnaryRegOpDirective(Directive):
|
401
|
+
src: int
|
402
|
+
res: int
|
403
|
+
|
404
|
+
def serialize_args(self) -> bytes:
|
405
|
+
data = bytearray()
|
406
|
+
data.extend(U8Type(self.src).serialize())
|
407
|
+
data.extend(U8Type(self.res).serialize())
|
408
|
+
return bytes(data)
|
409
|
+
|
410
|
+
|
411
|
+
@dataclass
|
412
|
+
class NotDirective(_UnaryRegOpDirective):
|
413
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.NOT
|
414
|
+
|
415
|
+
|
416
|
+
@dataclass
|
417
|
+
class FloatTruncateDirective(_UnaryRegOpDirective):
|
418
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTRUNC
|
419
|
+
|
420
|
+
|
421
|
+
@dataclass
|
422
|
+
class FloatExtendDirective(_UnaryRegOpDirective):
|
423
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPEXT
|
424
|
+
|
425
|
+
|
426
|
+
@dataclass
|
427
|
+
class FloatToSignedIntDirective(_UnaryRegOpDirective):
|
428
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTOSI
|
429
|
+
|
430
|
+
|
431
|
+
@dataclass
|
432
|
+
class SignedIntToFloatDirective(_UnaryRegOpDirective):
|
433
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SITOFP
|
434
|
+
|
435
|
+
|
436
|
+
@dataclass
|
437
|
+
class FloatToUnsignedIntDirective(_UnaryRegOpDirective):
|
438
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTOUI
|
439
|
+
|
440
|
+
|
441
|
+
@dataclass
|
442
|
+
class UnsignedIntToFloatDirective(_UnaryRegOpDirective):
|
443
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UITOFP
|
444
|
+
|
445
|
+
|
446
|
+
@dataclass
|
447
|
+
class ExitDirective(Directive):
|
448
|
+
opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.EXIT
|
449
|
+
success: bool
|
450
|
+
|
451
|
+
def serialize_args(self):
|
452
|
+
return BoolType(self.success).serialize()
|
453
|
+
|
454
|
+
|
455
|
+
INT_EQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
|
456
|
+
"==": IntEqualDirective,
|
457
|
+
"!=": IntNotEqualDirective,
|
458
|
+
}
|
459
|
+
|
460
|
+
FLOAT_EQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
|
461
|
+
"==": FloatEqualDirective,
|
462
|
+
"!=": FloatNotEqualDirective,
|
463
|
+
}
|
464
|
+
|
465
|
+
|
466
|
+
INT_SIGNED_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
|
467
|
+
">": SignedGreaterThanDirective,
|
468
|
+
"<": SignedLessThanDirective,
|
469
|
+
">=": SignedGreaterThanOrEqualDirective,
|
470
|
+
"<=": SignedLessThanOrEqualDirective,
|
471
|
+
}
|
472
|
+
INT_UNSIGNED_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
|
473
|
+
">": UnsignedGreaterThanDirective,
|
474
|
+
"<": UnsignedLessThanDirective,
|
475
|
+
">=": UnsignedGreaterThanOrEqualDirective,
|
476
|
+
"<=": UnsignedLessThanOrEqualDirective,
|
477
|
+
}
|
478
|
+
FLOAT_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
|
479
|
+
">": FloatGreaterThanDirective,
|
480
|
+
"<": FloatLessThanDirective,
|
481
|
+
">=": FloatGreaterThanOrEqualDirective,
|
482
|
+
"<=": FloatLessThanOrEqualDirective,
|
483
|
+
}
|
484
|
+
|
485
|
+
BINARY_COMPARISON_DIRECTIVES = {}
|
486
|
+
BINARY_COMPARISON_DIRECTIVES.update(INT_EQUALITY_DIRECTIVES)
|
487
|
+
BINARY_COMPARISON_DIRECTIVES.update(INT_SIGNED_INEQUALITY_DIRECTIVES)
|
488
|
+
BINARY_COMPARISON_DIRECTIVES.update(INT_UNSIGNED_INEQUALITY_DIRECTIVES)
|
489
|
+
BINARY_COMPARISON_DIRECTIVES.update(FLOAT_EQUALITY_DIRECTIVES)
|
490
|
+
BINARY_COMPARISON_DIRECTIVES.update(FLOAT_INEQUALITY_DIRECTIVES)
|