-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgenerate-usse.py
87 lines (76 loc) · 3.76 KB
/
generate-usse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from yaml import load, Loader
from enum import Enum
class Protection(Enum):
NONE = 0
SAFE = 1
DEBUG = 2
protection = Protection.DEBUG
bit_types = """
typedef uint64_t Instruction;
typedef uint64_t Param;
"""
debug = '#include <stdexcept>\n\n' if protection == Protection.DEBUG else ''
with open('external/usse-decoder-gen/grammar.yaml', 'r') as stream:
instructions = load(stream, Loader=Loader)
header = '#pragma once\n\n#include <cstdint>\n\nnamespace usse {' + bit_types + '\n'
source = '#include <gxp/instructions.h>\n\n' + debug + 'namespace usse {\n'
for instruction_name, instruction in instructions.items():
members = instruction['members']
first = True
declaration = 'Instruction make' + instruction_name + '('
parameters = ''
function = '\t\tInstruction inst = 0;\n'
index = 64
for member in members:
member_name = list(member)[0]
member_info = member[member_name]
if type(member_info) is str:
index -= len(member_info)
function += '\t\tinst |= 0b' + member_info + 'ull << ' + str(index) + 'u;\n'
elif type(member_info) is int:
index -= member_info
if not first:
parameters += ',\n\t\t'
parameters += 'Param/*' + str(member_info) + '*/ ' + member_name
first = False
if protection == Protection.DEBUG:
function += '\t\tif ((' + member_name + ' & ~0b' + ('1' * member_info) + 'ull) != 0)\n'\
+ '\t\t\tthrow std::runtime_error("Instruction field ' + member_name\
+ ' for ' + instruction_name + ' out of bounds.' + '");\n'
if protection == Protection.NONE:
function += '\t\tinst |= ' + member_name + ' << ' + str(index) + 'u;\n'
else:
function += '\t\tinst |= (' + member_name + ' & 0b'\
+ ('1' * member_info) + 'ull) << ' + str(index) + 'u;\n'
else:
if 'offset' in member_info:
index = member_info['offset']
else:
index -= member_info['size']
if 'match' in member_info:
function += '\t\tinst |= 0b' + member_info['match'] + 'ull << ' + str(index) + 'u;\n'
else:
if not first:
parameters += ',\n\t\t'
parameters += 'Param/*' + str(member_info['size']) + '*/ ' + member_name
first = False
if protection == Protection.DEBUG:
function += '\t\tif ((' + member_name + ' & ~0b' + ('1' * member_info['size']) + 'ull) != 0)\n'\
+ '\t\t\tthrow std::runtime_error("Instruction field ' + member_name \
+ ' for ' + instruction_name + ' out of bounds.' + '");\n'
if protection == Protection.NONE:
function += '\t\tinst |= ' + member_name + ' << ' + str(index) + 'u;\n'
else:
function += '\t\tinst |= (' + member_name + ' & 0b'\
+ ('1' * member_info['size']) + 'ull) << ' + str(index) + 'u;\n'
if parameters:
declaration += '\n\t\t' + parameters
declaration += ')'
header += '\t' + declaration + ';\n\n'
source += '\t' + declaration + ' {\n' + function + '\t\treturn inst;\n\t}\n\n'
header += '}\n'
source += '}\n'
with open('src/gxp/include/gxp/instructions.h', 'w+') as header_out:
header_out.write(header)
with open('src/gxp/src/instructions.cpp', 'w+') as source_out:
source_out.write(source)