Repository navigation
Expand file tree
/
Copy pathassembler.py
More file actions
159 lines (114 loc) · 6.33 KB
/
Copy pathassembler.py
File metadata and controls
159 lines (114 loc) · 6.33 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import numpy as np
import sys
import math
NUMBER_OF_NOPS_AFTER_MATRIX_OPERATION = 9
operation_name_to_opcode = {
"nop": "000",
"tensor_core": "001",
"burst": "010",
"reset": "011",
"matrix_add": "100",
"matrix_scale": "101",
"matrix_relu": "110",
"currently_bursting": "111"
}
def number_into_signed_kbit_binary(number: str, k):
number = int(number)
if number < -1 * (2**(k-1)) or number > (2**(k-1))-1:
raise Exception("code has out of bounds number")
return np.binary_repr(number, k)
def number_into_unsigned_kbit_binary(number: str, k):
number = int(number)
if number < 0 or number > (2**k)-1:
raise Exception("code has out of bounds number")
return np.binary_repr(number, k)
def main():
if len(sys.argv) > 1:
assembly_file = sys.argv[1]
else:
assembly_file = "assembly_code.asm"
with open(assembly_file, "r") as f:
assembly_code_lines = f.readlines()
machine_code = []
for line_index, assembly_code_line in enumerate(assembly_code_lines):
line_index += 1 # this is to make the index start from 1 and not start from 0
assembly_code_tokens = assembly_code_line.strip().split(" ")
if not assembly_code_tokens or not assembly_code_tokens[0]:
continue
operation_name = assembly_code_tokens[0]
should_have_matrix_operation_nops_after = False
burst_load_matrix1_address = None
burst_load_matrix2_address = None
burst_store_address = None
store_or_load = None
current_machine_code_line = ""
# PARSE THE DIFFERENT INSTRUCTION FORMATS
if (operation_name in ["nop", "reset"]):
current_machine_code_line += "0" * 48
current_machine_code_line += "0"*13
current_machine_code_line += operation_name_to_opcode[operation_name]
elif (operation_name == "burst"):
current_machine_code_line += "0" * 48
store_or_load = assembly_code_tokens[1]
if store_or_load != "store_and_load":
raise Exception(f"Only accepts store_and_load as an acceptable argument on line {line_index}")
current_machine_code_line += "0"*2
current_machine_code_line += "0"*11
current_machine_code_line += operation_name_to_opcode["burst"]
burst_store_address = int(assembly_code_tokens[2])
burst_load_matrix1_address = int(assembly_code_tokens[3])
burst_load_matrix2_address = int(assembly_code_tokens[4])
elif (operation_name in ["matrix_multiply"]):
current_machine_code_line += "0" * 48
current_machine_code_line += "0"*13
current_machine_code_line += operation_name_to_opcode["tensor_core"]
should_have_matrix_operation_nops_after = True
elif (operation_name == "matrix_add"):
matrix_output_address = 9 * int(assembly_code_tokens[1])
matrix_input1_address = 9 * int(assembly_code_tokens[2])
matrix_input2_address = 9 * int(assembly_code_tokens[3])
current_machine_code_line += number_into_unsigned_kbit_binary(matrix_output_address, k=16)
current_machine_code_line += number_into_unsigned_kbit_binary(matrix_input2_address, k=16)
current_machine_code_line += number_into_unsigned_kbit_binary(matrix_input1_address, k=16)
current_machine_code_line += "0"*13
current_machine_code_line += operation_name_to_opcode["matrix_add"]
elif (operation_name == "matrix_scale"):
current_machine_code_line += "0" * 32
matrix_address = 9 * int(assembly_code_tokens[1])
scale_factor = int(round(math.log2(float(assembly_code_tokens[2]))))
current_machine_code_line += number_into_unsigned_kbit_binary(matrix_address, k=16)
current_machine_code_line += "0"*5
current_machine_code_line += number_into_signed_kbit_binary(scale_factor, k=8)
current_machine_code_line += operation_name_to_opcode["matrix_scale"]
elif (operation_name == "matrix_relu"):
current_machine_code_line += "0" * 32
matrix_address = 9 * int(assembly_code_tokens[1])
current_machine_code_line += number_into_unsigned_kbit_binary(matrix_address, k=16)
current_machine_code_line += "0"*13
current_machine_code_line += operation_name_to_opcode["matrix_relu"]
else:
raise Exception(f"operation name {operation_name} on line {line_index} is not supported")
machine_code.append(format(int(current_machine_code_line, 2), "016X") +'\n')
if should_have_matrix_operation_nops_after:
for i in range(NUMBER_OF_NOPS_AFTER_MATRIX_OPERATION):
machine_code.append(format(int("0"*64, 2), "016X") + '\n')
if burst_load_matrix1_address is not None and burst_load_matrix2_address is not None:
for index in range(9):
current_machine_code_line = ""
current_machine_code_line += number_into_unsigned_kbit_binary(9*burst_store_address + index, k=16)
if 2*index+1 < 9:
current_machine_code_line += number_into_unsigned_kbit_binary(9*burst_load_matrix1_address + 2*index+1, k=16)
else:
current_machine_code_line += number_into_unsigned_kbit_binary(9*burst_load_matrix2_address + 2*index+1 - 9, k=16)
if 2*index < 9:
current_machine_code_line += number_into_unsigned_kbit_binary(9*burst_load_matrix1_address + 2*index, k=16)
else:
current_machine_code_line += number_into_unsigned_kbit_binary(9*burst_load_matrix2_address + 2*index - 9, k=16)
current_machine_code_line += "1"*2
current_machine_code_line += "0"*11
current_machine_code_line += operation_name_to_opcode["currently_bursting"]
machine_code.append(format(int(current_machine_code_line, 2), "016X") + '\n')
with open("machine_code", 'w+') as f:
f.writelines(machine_code)
if __name__ == "__main__":
main()