Repository navigation
Expand file tree
/
Copy pathMPSoCConfig.py
More file actions
321 lines (264 loc) · 11.1 KB
/
Copy pathMPSoCConfig.py
File metadata and controls
321 lines (264 loc) · 11.1 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
import os
from sortedcontainers import SortedDict
class MPSoCConfig:
# Portas físicas do roteador (índice da porta no traffic_router.txt)
EAST0 = 0
EAST1 = 1
WEST0 = 2
WEST1 = 3
NORTH0 = 4
NORTH1 = 5
SOUTH0 = 6
SOUTH1 = 7
LOCAL0 = 8
LOCAL1 = 9
NPORT = 10
PORT_NAMES = ("EAST 0", "EAST 1", "WEST 0", "WEST 1", "NORTH 0",
"NORTH 1", "SOUTH 0", "SOUTH 1", "LOCAL 0", "LOCAL 1")
# Canais
LOW = 0x100
HIGH = 0
# Tipos de PE
GLOBAL_MASTER = 0
CLUSTER_MASTER = 1
SLAVE = 2
# Constantes de Direção (Variáveis de Classe)
EAST_IN_HIGH = 0
EAST_OUT_HIGH = 1
WEST_IN_HIGH = 2
WEST_OUT_HIGH = 3
NORTH_IN_HIGH = 4
NORTH_OUT_HIGH = 5
SOUTH_IN_HIGH = 6
SOUTH_OUT_HIGH = 7
EAST_IN_LOW = 8
EAST_OUT_LOW = 9
WEST_IN_LOW = 10
WEST_OUT_LOW = 11
NORTH_IN_LOW = 12
NORTH_OUT_LOW = 13
SOUTH_IN_LOW = 14
SOUTH_OUT_LOW = 15
LOCAL_IN = 16
LOCAL_OUT = 17
# Constantes de Roteamento
HAMILTONIAN = 0
XY = 1
def __init__(self, debug_file_path):
self.debug_file_path = debug_file_path
# Inicializando variáveis de instância padrão
self.router_addressing = 0
self.mpsoc_x = 0
self.mpsoc_y = 0
self.cluster_x = 0
self.cluster_y = 0
self.manager_position_x = 0
self.manager_position_y = 0
self.global_position_x = 0
self.global_position_y = 0
self.global_manager_cluster = 0
self.flit_size = 0
self.clock_period_in_ns = 0
self.channel_number = 2
self.services_hash = SortedDict()
self.task_name_hash = SortedDict()
self.app_name_hash = SortedDict()
self.service_reference = []
self.task_allocation_services = []
self.task_terminated_services = []
# Abre o arquivo em modo leitura de texto garantindo o encoding UTF-8
try:
with open(debug_file_path+"/platform.cfg", "r", encoding="utf-8") as platform_file:
for line in platform_file:
config_info = line.strip().split()
if not config_info:
continue
match config_info[0]:
case "router_addressing":
if config_info[1].upper() == "XY":
self.router_addressing = self.XY
else:
self.router_addressing = self.HAMILTONIAN
case "mpsoc_x":
self.mpsoc_x = int(config_info[1])
case "mpsoc_y":
self.mpsoc_y = int(config_info[1])
case "cluster_x":
self.cluster_x = int(config_info[1])
case "cluster_y":
self.cluster_y = int(config_info[1])
case "manager_position_x":
self.manager_position_x = int(config_info[1])
case "manager_position_y":
self.manager_position_y = int(config_info[1])
case "global_manager_cluster":
self.global_manager_cluster = int(config_info[1])
case "flit_size":
self.flit_size = int(config_info[1])
case "clock_period_ns":
self.clock_period_in_ns = int(config_info[1])
case "channel_number":
self.channel_number = int(config_info[1])
case "BEGIN_task_name_relation":
# Passamos o OBJETO do arquivo, não a string do caminho
self.initialize_task_naming(platform_file)
case "BEGIN_app_name_relation":
self.initialize_app_naming(platform_file)
case _:
pass
except FileNotFoundError:
print("Erro")
self.discovery_global_xy_position()
self.initialize_services(debug_file_path + "/services.cfg")
def initialize_task_naming(self, platform_file):
"""Lê as tarefas diretamente do objeto de arquivo aberto."""
self.task_name_hash = SortedDict()
# Continua iterando sobre as linhas do MESMO arquivo aberto no __init__
for line in platform_file:
line = line.strip()
if line == "END_task_name_relation":
break # Sai do loop e devolve o controle para o __init__
if line == "":
continue
task_name_id = line.split(" ")
if len(task_name_id) >= 2:
task_name = task_name_id[0]
try:
task_id = int(task_name_id[1])
self.task_name_hash[task_id] = task_name
except ValueError:
# Ignora caso o ID não seja um número válido
continue
def initialize_app_naming(self, platform_file):
"""Lê a relação nome<TAB>ID das aplicações (até END_app_name_relation)."""
self.app_name_hash = SortedDict()
for line in platform_file:
fields = line.split()
if fields == ["END_app_name_relation"]:
break
if len(fields) >= 2:
try:
self.app_name_hash[int(fields[1])] = fields[0]
except ValueError:
continue
def initialize_services(self, services_file_path):
"""Lê os serviços (nome e código decimal) do arquivo services.cfg."""
self.services_hash = SortedDict()
self.task_allocation_services = []
self.task_terminated_services = []
try:
with open(services_file_path, "r", encoding="utf-8") as services_file:
for line in services_file:
service_info = line.strip().split()
if len(service_info) < 2:
continue
try:
values = [int(value) for value in service_info[1:]]
except ValueError:
# Ignora caso o código não seja um número válido
continue
# Linhas especiais com a lista de serviços de alocação/término de tarefa
match service_info[0]:
case "$TASK_ALLOCATION_SERVICE":
self.task_allocation_services.extend(values)
case "$TASK_TERMINATED_SERVICE":
self.task_terminated_services.extend(values)
case _:
self.services_hash[values[0]] = service_info[0]
except FileNotFoundError:
print("Erro")
self.service_reference = list(self.services_hash.keys())
def discovery_global_xy_position(self):
"""Descobre a posição XY do gerente global a partir do cluster configurado."""
if self.cluster_x == 0 or self.mpsoc_x == 0:
return
cluster_master = self.global_manager_cluster + 1
x_master = 0
y_master = 0
while cluster_master > 0:
if self.mpsoc_x % (cluster_master * self.cluster_x) == 0:
x_master = cluster_master - 1
else:
y_master += 1
cluster_master -= self.mpsoc_x // self.cluster_x
self.global_position_x = x_master * self.cluster_x + self.manager_position_x
self.global_position_y = y_master * self.cluster_y + self.manager_position_y
# ==========================================
# PORTAS E CANAIS
# ==========================================
@staticmethod
def get_channel(port):
"""Portas pares (EAST0, WEST0, NORTH0, SOUTH0, LOCAL0) são do canal HIGH."""
return MPSoCConfig.HIGH if port % 2 == 0 else MPSoCConfig.LOW
@staticmethod
def get_port_string(port):
if 0 <= port < MPSoCConfig.NPORT:
return MPSoCConfig.PORT_NAMES[port]
return None
# ==========================================
# SERVIÇOS
# ==========================================
def get_string_service_name(self, service):
return self.services_hash.get(service, "---")
def get_service_value(self, name):
for service_value, service_name in self.services_hash.items():
if service_name == name:
return service_value
return -1
# ==========================================
# ENDEREÇAMENTO (XY <-> HAMILTONIANO)
# ==========================================
def xy_to_ham_addr(self, xy_addr):
xy_addr &= 0xFFFF # limpa o header
y = xy_addr & 0xFF
x = xy_addr >> 8
if y % 2 == 1:
return (y * self.mpsoc_x) + (self.mpsoc_x - x) - 1
return (y * self.mpsoc_x) + x
def ham_to_xy_addr(self, ham_addr):
ham_addr &= 0xFF # limpa o header
y, addr = divmod(ham_addr, self.mpsoc_x)
x = self.mpsoc_x - addr - 1 if y % 2 == 1 else addr
return (x << 8) | y
def ham_address_to_xy_label(self, ham_addr):
xy_addr = self.ham_to_xy_addr(ham_addr)
return f"{xy_addr >> 8}x{xy_addr & 0xFF}"
def xy_label_to_ham_address(self, xy_label):
x, y = (int(value) for value in xy_label.split("x"))
return self.xy_to_ham_addr((x << 8) | y)
def get_pe_type(self, ham_addr):
xy_addr = self.ham_to_xy_addr(ham_addr)
x = xy_addr >> 8
y = xy_addr & 0xFF
if x < self.manager_position_x or y < self.manager_position_y:
return self.SLAVE
if x == self.global_position_x and y == self.global_position_y:
return self.GLOBAL_MASTER
if ((x - self.manager_position_x) % self.cluster_x == 0
and (y - self.manager_position_y) % self.cluster_y == 0):
return self.CLUSTER_MASTER
return self.SLAVE
# ==========================================
# PLATAFORMA
# ==========================================
def get_pe_number(self):
return self.mpsoc_x * self.mpsoc_y
def get_testcase_path(self):
"""Pasta do cenário: a que contém o diretório de debug (e o log/)."""
debug_dir = os.path.normpath(self.debug_file_path)
if os.path.basename(debug_dir) != "debug":
return None
return os.path.dirname(debug_dir)
def get_frequency_in_hz(self):
return 1_000_000_000 // self.clock_period_in_ns
def get_frequency_in_khz(self):
return self.get_frequency_in_hz() // 1000
def get_frequency_in_mhz(self):
return self.get_frequency_in_hz() // 1_000_000
def get_link_bandwidth_in_mbps(self):
return self.get_frequency_in_hz() * self.flit_size // 1_000_000
# Métodos de acesso necessários para compatibilidade com sua interface gráfica
def get_task_name_hash(self):
return self.task_name_hash
def get_services_hash(self):
return self.services_hash