You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

746 lines
27 KiB

"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 21/11/2022 下午 8:12
# @Author :
# @File : tomasulo.py
# @Description :
"""
import numpy as np
from typing import List
class Normalizer:
def __init__(self):
self.__instructions = None
self.__out = None
def __replace(self):
self.__out = [i.split(r'//')[0] for i in self.__instructions]
self.__out = [i.replace(':', ': ', -1) for i in self.__out]
self.__out = [i.replace(',', ', ', -1) for i in self.__out]
self.__out = [i.replace('/t', ' ', -1) for i in self.__out]
self.__out = [i.replace('#', '', -1) for i in self.__out]
self.__out = [i.replace('(', ',', -1) for i in self.__out]
self.__out = [i.replace(')', ',', -1) for i in self.__out]
self.__out = [i.replace('F', 'R', -1) for i in self.__out]
for i in range(len(self.__out)):
while True:
if ' ' in self.__out[i]:
self.__out[i] = self.__out[i].replace(
' ', ' ', -1)
else:
break
self.__out = [i.replace(' ,', ',', -1) for i in self.__out]
self.__out = [i.replace(', ', ',', -1) for i in self.__out]
def __delete_empty(self):
self.__out = [i[1:] if i[0] == ' ' else i for i in self.__out]
temp = self.__out
self.__out = []
for i in temp:
if not i == '':
self.__out.append(i)
def instructions_input(self, _instructions: List[str]):
self.__instructions = _instructions
def get_out(self):
return self.__out
def run(self):
self.__replace( )
self.__delete_empty( )
class Spliter:
def __init__(self):
self.__instructions = None
self.__out = None
def __get_pointer(self):
for i in range(len(self.__instructions)):
if ':' in self.__instructions[i]:
self.__out[i]['pointer'] = \
self.__instructions[i].split(':')[0]
self.__instructions[i] = \
self.__instructions[i].split(':')[1][1:]
else:
self.__out[i]['pointer'] = ''
def __get_mnemonic(self):
for i in range(len(self.__instructions)):
self.__out[i]['mnemonic'] = \
self.__instructions[
i][: self.__instructions[i].find(' ')]
self.__instructions[i] = \
self.__instructions[
i][self.__instructions[i].find(' ') + 1:]
def __get_parameters(self):
for i in range(len(self.__instructions)):
self.__out[i]['parameters'] = [
self.__instructions[
i][: self.__instructions[i].find(',')]]
self.__instructions[i] = \
self.__instructions[
i][self.__instructions[i].find(',') + 1:]
self.__out[i]['parameters'].append(
self.__instructions[
i][: self.__instructions[i].find(',')])
self.__out[i]['parameters'].append(
self.__instructions[
i][self.__instructions[i].find(',') + 1:])
if self.__out[i]['parameters'][-1][-1] == ',':
self.__out[i]['parameters'][-1] = \
self.__out[i]['parameters'][-1][: -1]
for i in range(len(self.__instructions)):
for j in range(len(self.__out[i]['parameters'])):
self.__out[i]['parameters'][j] = \
self.__out[i]['parameters'][j].split(r' ')[0]
def instructions_input(self, _instructions: List[str]):
self.__instructions = _instructions
def get_out(self):
return self.__out
def run(self):
self.__out = [{} for _ in range(len(self.__instructions))]
self.__get_pointer( )
self.__get_mnemonic( )
self.__get_parameters( )
class Table:
def __init__(self, _name: str = "table"):
self.name = _name
def set_name(self, _name: str):
self.name = _name
def get_name(self):
return self.name
class InstructionStatus(Table):
def __init__(self):
super( ).__init__( )
self.__index = []
self.__keys = ["Ins", "FI", "IS", "EX", "WR", "Unit"]
def push(self, _instruction: dict):
self.__index = np.append(self.__index,
{i: False for i in self.__keys})
self.__index[-1]["Ins"] = _instruction.copy( )
def get_table(self):
return self.__index
def clear(self):
self.__index = []
class ReservationStation(Table):
def __init__(self):
super( ).__init__( )
self.__index = {}
self.__keys = ["Busy", "Op", "Vj", "Vk", "Qj", "Qk", "A"]
self.__unit_name = []
self.__unit_name.extend(
["LOAD" + str(i + 1) for i in range(2)])
self.__unit_name.extend(
["ADD" + str(i + 1) for i in range(3)])
self.__unit_name.extend(
["MULT" + str(i + 1) for i in range(2)])
self.__unit_name.extend(
["STORE" + str(i + 1) for i in range(2)])
self.__index = {i: {
j: False for j in self.__keys} for i in self.__unit_name}
def get_table(self):
return self.__index
class RegisterResultStatus(Table):
def __init__(self):
super( ).__init__( )
self.__index = None
self.__keys = []
for i in range(32):
self.__keys.append(str(i))
self.__index = {i: "" for i in self.__keys}
def get_table(self):
return self.__index
class Analyzer:
def __init__(self):
self.__instructions = None
self.__out = []
self.__dict_steps = {
'L.D': 2,
'MUL.D': 10,
'S.D': 2,
}
self.__dict_FU = {
'L.D': 'LOAD',
'MUL.D': 'MUL',
'S.D': 'STORE',
}
def __get_RR(self):
for i in range(len(self.__out)):
if self.__out[i]['Ins']['mnemonic'] != 'S.D':
self.__out[i]["W"] = \
self.__instructions[i]['parameters'][0][1:]
for j in range(2):
if 'R' in self.__out[i]['Ins']['parameters'][1 + j]:
self.__out[i]["R"].append(
self.__instructions[i][
'parameters'][1 + j][1:])
else:
self.__out[i]["R"].append('')
def instructions_input(self, _instructions: List[str]):
self.__instructions = _instructions
for instruction in self.__instructions:
if instruction["mnemonic"] == "BNE" or \
instruction["mnemonic"] == "DADDUI":
continue
else:
self.__out.append({
"Ins": instruction.copy( ),
"FU": self.__dict_FU[instruction["mnemonic"]],
"W": '',
"R": [],
"steps": self.__dict_steps[
instruction["mnemonic"]]})
def get_out(self) -> dict:
return self.__out
def run(self):
self.__get_RR( )
class Tomasulo:
def __init__(self):
self.__change = []
self.__tables = {
"instruction_status": InstructionStatus( ),
"reservation_station": ReservationStation( ),
"register_result_status": RegisterResultStatus( )
}
self.__func_dict = {
'IS': self.__issue,
'EX': self.__execute,
'WR': self.__write
}
self.__loop = []
self.__record = []
self.__loop_time = 2
self.__times = 0
self.__time = 0
self.__run = []
self.__index = []
self.__record_dict = {
"instruction_status": [],
"reservation_station": [],
"register_result_status": []
}
def __issue(self):
if not len(self.__tables["instruction_status"].get_table( )):
for _ in range(self.__loop_time):
self.__times += 1
for i in range(len(self.__loop)):
self.__tables["instruction_status"].push(
_instruction = self.__index[
_ * len(self.__loop) + i])
self.__tables["instruction_status"].get_table( )[
-1]['FI'] = self.__times
for instruction in self.__tables[
"instruction_status"].get_table( ):
if instruction['Ins']['W'] != instruction[
'Ins']['Ins'][
'parameters'][0][
1:]:
instruction['Ins']['W'] = \
instruction['Ins']['Ins']['parameters'][0][1:]
iteration = [False for _ in range(self.__loop_time)]
for i in range(len(
self.__tables["instruction_status"].get_table( ))):
if not self.__tables[
"instruction_status"].get_table( )[i]['IS']:
if iteration[(self.__tables[
"instruction_status"
].get_table( )[i]['FI'] - 1) %
self.__loop_time]:
continue
instruction = \
self.__tables[
"instruction_status"].get_table( )[i]['Ins']
op_FU = instruction['FU']
reg_R = [instruction['R'][0], instruction['R'][1]]
reg_W = instruction['W']
mnemonic = instruction['Ins']['mnemonic']
if reg_W and self.__tables[
"register_result_status"].get_table( )[reg_W]:
position = -1
used = [False for _ in range(32)]
for j in range(0, (i // len(self.__loop) + 1)
* len(self.__loop)):
for k in range(3):
if 'R' in self.__tables[
"instruction_status"].get_table( )[j][
'Ins']['Ins']['parameters'][k]:
used[int(self.__tables[
"instruction_status"
].get_table( )[j]['Ins'][
'Ins']['parameters'][
k][1:])] = True
for j in range(32):
if not self.__tables[
"register_result_status"].get_table( )[
str(j)] and not used[j]:
position = j
break
if position == -1:
iteration[self.__tables[
"instruction_status"
].get_table( )[i]['FI'] - 1] = True
continue
for j in range(i, (i // len(self.__loop) + 1) *
len(self.__loop)):
if self.__tables[
"instruction_status"].get_table( )[j][
'Ins']['W'] == reg_W:
self.__tables[
"instruction_status"].get_table( )[j][
'Ins']['W'] = str(position)
self.__tables[
"instruction_status"].get_table( )[j][
'Ins']['Ins']['parameters'][0] = \
'R' + str(position)
for k in range(2):
if self.__tables[
"instruction_status"].get_table( )[j][
'Ins']['R'][k] == reg_W:
self.__tables[
"instruction_status"].get_table(
)[j]['Ins']['R'][k] = str(position)
self.__tables[
"instruction_status"].get_table(
)[j]['Ins']['Ins']['parameters'][
1 + k] = 'R' + str(position)
instruction = self.__tables[
"instruction_status"].get_table( )[i]['Ins']
reg_R = [instruction['R'][0], instruction['R'][1]]
reg_W = instruction['W']
self.__run[i] = False
self.__tables[
"instruction_status"].get_table( )[i]['IS'] = \
self.__time
for function_unit in self.__tables[
"reservation_station"].get_table( ):
if op_FU in function_unit:
if self.__tables[
"reservation_station"].get_table( )[
function_unit]['Busy']:
continue
else:
self.__tables[
"instruction_status"].get_table( )[i][
'Unit'] = function_unit
unit = self.__tables[
"reservation_station"].get_table( )[
function_unit]
unit['Busy'] = True
unit['Op'] = mnemonic
for i in range(2):
if not reg_R[i]:
continue
if self.__tables[
"register_result_status"
].get_table( )[reg_R[i]]:
unit['Q' + chr(ord('j') + i)] = \
self.__tables[
"register_result_status"
].get_table( )[reg_R[i]]
else:
unit['V' + chr(ord('j') + i)] = \
'R' + reg_R[i]
self.__tables[
"register_result_status"
].get_table( )[reg_W] = function_unit
break
break
def __execute(self):
for i in range(len(
self.__tables["instruction_status"].get_table( ))):
if not self.__run[i]:
continue
if self.__tables[
"instruction_status"].get_table( )[i]['IS']:
unit = self.__tables[
"reservation_station"].get_table( )[
self.__tables["instruction_status"].get_table( )[
i]['Unit']]
if not unit['Qj'] and not unit['Qk'] and \
self.__tables["instruction_status"].get_table(
)[i]['Ins']['steps']:
self.__tables["instruction_status"].get_table(
)[i]['Ins']['steps'] -= 1
if not self.__tables[
"instruction_status"].get_table( )[i][
'Ins']['steps']:
self.__tables["instruction_status"].get_table(
)[i]['EX'] = self.__time
self.__run[i] = False
def __write(self):
for i in range(len(
self.__tables["instruction_status"].get_table( ))):
if not self.__run[i]:
continue
if self.__tables[
"instruction_status"].get_table( )[i]['EX'] and not \
self.__tables[
"instruction_status"].get_table( )[i]['WR']:
self.__tables["register_result_status"].get_table( )[
self.__tables["instruction_status"].get_table( )[
i]['Ins']['W']] = ''
self.__tables["instruction_status"].get_table( )[i][
'WR'] = self.__time
unit = self.__tables[
"reservation_station"].get_table( )[
self.__tables["instruction_status"].get_table( )[
i]['Unit']]
unit['Busy'] = False
unit['Op'] = ''
unit['Vj'] = ''
unit['Vk'] = ''
unit['Qj'] = ''
unit['Qk'] = ''
unit['A'] = ''
def set_change(self, _change: List[dict]):
self.__change = _change
def set_loop(self, _loop: List[dict]):
self.__loop = _loop
def set_index(self, _loop: List[dict]):
for i in _loop:
self.__index.append(i.copy( ))
def run(self, _time: int):
self.__run = [True for _ in range(self.__loop_time *
len(self.__loop))]
self.__time = _time
self.__issue( )
self.__execute( )
self.__write( )
for key in self.__tables['reservation_station'].get_table( ):
unit = self.__tables[
'reservation_station'].get_table( )[key]
for i in range(2):
if unit['Q' + chr(ord('j') + i)]:
unit_name = unit['Q' + chr(ord('j') + i)]
if unit_name not in self.__tables[
'register_result_status'].get_table(
).values( ):
unit['Q' + chr(ord('j') + i)] = ''
unit['V' + chr(ord('j') + i)] = unit_name
if 'LOAD' in key:
if not unit['A']:
for i in range(2):
if unit['V' + chr(ord('j') + i)]:
unit['A'] = unit['V' + chr(ord('j') + i)]
unit['V' + chr(ord('j') + i)] = ''
break
time = 0
for i in range(
len(self.__loop) * self.__loop_time):
if key == self.__tables[
'instruction_status'].get_table( )[i][
'Unit']:
time = (self.__tables[
'instruction_status'
].get_table( )[i]['FI'] - 1) % \
self.__loop_time
break
for change in self.__change:
if unit['A'] and time and \
change['REG'] == unit['A'][1:]:
unit['A'] += ' ' + str(change['C'] * time)
break
if 'STORE' in key:
for i in range(
len(self.__loop) * self.__loop_time):
if key == self.__tables[
'instruction_status'].get_table( )[i][
'Unit']:
time = (self.__tables[
'instruction_status'].get_table(
)[i]['FI'] - 1) % self.__loop_time
break
for change in self.__change:
for j in range(2):
if unit['V' + chr(ord('j') + j)] and \
time and change['REG'] == \
unit['V' + chr(ord('j') + j)][1:]:
unit['V' + chr(ord('j') + j)] += \
' ' + str(change['C'] * time)
break
flag = False
for instruction in self.__tables[
'instruction_status'].get_table( ):
if not (instruction['IS'] and instruction['EX'] and
instruction['WR']):
flag = True
self.__record_dict["instruction_status"].append(
[{'Ins': i['Ins']['Ins'], 'FI': i['FI'], 'IS': i['IS'],
'EX': i['EX'], 'WR': i['WR']}
for i in self.__tables[
'instruction_status'].get_table( )])
reservation_station = [
np.append([i], [self.__tables[
'reservation_station'].get_table( )[
i][j] for j in self.__tables[
'reservation_station'].get_table( )[
i]])
for i in self.__tables[
'reservation_station'].get_table( )]
self.__record_dict[
"reservation_station"].append(reservation_station)
register_result_status = [
self.__tables['register_result_status'].get_table( )[i]
for i in self.__tables[
'register_result_status'].get_table( )]
self.__record_dict[
"register_result_status"].append(register_result_status)
if not flag:
self.__tables['instruction_status'].clear( )
def get_out(self):
return self.__record_dict
def run(_instructions: List[str]) -> dict:
normalizer = Normalizer( )
spliter = Spliter( )
analyzer = Analyzer( )
tomasulo = Tomasulo( )
normalizer.instructions_input(_instructions)
normalizer.run( )
spliter.instructions_input(normalizer.get_out( ))
spliter.run( )
loop = []
change = [{'REG': '', 'C': 0}]
for instruction in spliter.get_out( ):
if instruction['mnemonic'] == 'BNE':
pointer = instruction['parameters'][-1]
for _instruction in spliter.get_out( ):
if pointer == _instruction['pointer']:
for _instruction in spliter.get_out( ):
if _instruction['mnemonic'] == 'DADDUI':
break
loop.append(_instruction)
break
if instruction['mnemonic'] == 'DADDUI':
change[0]['REG'] = instruction['parameters'][0][1:]
change[0]['C'] = int(instruction['parameters'][-1])
analyzer.instructions_input(loop)
analyzer.run( )
tomasulo.set_change(change)
tomasulo.set_loop(analyzer.get_out( ))
normalizer = Normalizer( )
spliter = Spliter( )
analyzer = Analyzer( )
_instructions = _instructions[: -2]
_instructions.extend(_instructions)
normalizer.instructions_input(_instructions)
normalizer.run( )
spliter.instructions_input(normalizer.get_out( ))
spliter.run( )
analyzer.instructions_input(spliter.get_out( ))
analyzer.run( )
tomasulo.set_index(analyzer.get_out( ))
for time in range(1, 43):
tomasulo.run(time)
return tomasulo.get_out( )
def show(_table: dict):
IS = _table['instruction_status']
FUS = _table['reservation_station']
RRS = _table['register_result_status']
cycles = len(IS)
for cycle in range(cycles):
print('*' * 100)
print('*', ' ' * 8, end = '')
cycle_str = 'Cycle ' + str(cycle + 1)
print(cycle_str, end = '')
print(' ' * (88 - len(cycle_str)), '*')
print('*' * 100)
print('*', ' ' * 3, end = '')
print('instruction status', ' ' * 74, '*')
print('*' + '-' * 98 + '*')
print('*' + ' ' * 8, end = '')
print(' instruction ', end = '')
print(' ' * 5 + 'From Iteration', end = '')
print(' ' * 5 + 'Read Oper', end = '')
print(' ' * 6 + 'Exec Comp', end = '')
print(' ' * 5 + 'Write Result *')
for ins in IS[cycle]:
print('*' + ' ' * 8, end = '')
index = ins['Ins']['mnemonic'] + ' ' * (
8 - len(ins['Ins']['mnemonic']))
for i in ins['Ins']['parameters']:
index += ' ' + i + ' ' * (4 - len(i))
index += ' ' * 10
index += str(ins['FI']) + ' ' * (15 - len(str(ins['FI'])))
index += str(ins['IS']) + ' ' * (15 - len(str(ins['IS'])))
index += str(ins['EX']) + ' ' * (15 - len(str(ins['EX'])))
index += str(ins['WR']) + ' ' * (
12 - len(str(ins['WR']))) + '*'
index = index.replace('False', ' ' * 5, -1)
print(index)
print('*' * 100)
print('*', ' ' * 3, end = '')
print('reservation station', ' ' * 73, '*')
print('*' + '-' * 98 + '*')
print('*' + ' ' * 8, end = '')
label = ['Name', 'Busy', 'Op', 'Fi', 'Fj', 'Fk', 'Qj', 'A']
index = ""
for i in label:
index += i + ' ' * (11 - len(i))
print(index, end = ' *\r\n')
for fus in FUS[cycle]:
print('*' + ' ' * 8, end = '')
index = ""
for i in range(len(fus)):
if fus[i] == '1' or not fus[i] or fus[i] == 'False':
fus[i] = ''
elif fus[i] is True or fus[i] == 'True':
fus[i] = 'Yes'
for i in range(3):
if fus[3 + i]:
fus[3 + i] = 'R' + fus[3 + i]
for label in fus:
index += label + ' ' * (11 - len(label))
print(index, end = ' *\r\n')
print('*' * 100)
print('*', ' ' * 3, end = '')
print('register result status', ' ' * 70, '*')
print('*' + '-' * 98 + '*')
count = 0
index = ""
value = ""
for i in RRS[cycle]:
if count % 8 == 0:
print(index, end = '')
if count:
print(' *')
print(value, end = '')
if count:
print(' *')
index = '*' + ' ' * 8
value = '*' + ' ' * 8
index += 'R' + str(count) + ' ' * (10 - len(str(count)))
value += i + ' ' * (11 - len(i))
count += 1
print('*' * 100)
print('\r\n\r\n')
if __name__ == '__main__':
instructions = [
"LOOP: L.D F0, 0 (R1)",
" MUL.D F4, F0, F2 ",
" S.D 0 (R1) F4 ",
" DADDUI R1, R1, #-8 ",
" BNE R1, R2, LOOP",
]
tables = run(instructions)
show(_table = tables)