|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
import sys
|
|
|
|
|
|
LD = "L.D" # exe steps: 2
|
|
|
SD = "S.D" # 1
|
|
|
ADDD = "ADD.D" # 2
|
|
|
SUBD = "SUB.D" # 2
|
|
|
MULD = "MUL.D" # 10
|
|
|
DIVD = "DIV.D" # 40
|
|
|
|
|
|
|
|
|
class Tomasulo:
|
|
|
|
|
|
def __init__(self, insts, adder_num, multiplier_num, load_buffer_num,
|
|
|
store_buffer_num, float_reg_num, int_reg_num, mem_size):
|
|
|
i = 0
|
|
|
for inst in insts:
|
|
|
inst_ = ""
|
|
|
for term in inst.split(" "):
|
|
|
inst_ = inst_ + term.split(",")[0] + " "
|
|
|
insts[i] = inst_.split("\n")[0]
|
|
|
i += 1
|
|
|
self.instruction_status = [
|
|
|
instruction_status(insts[i], i) for i in range(len(insts))
|
|
|
]
|
|
|
|
|
|
self.reservation_station = reservation_station(adder_num,
|
|
|
multiplier_num)
|
|
|
self.load_buffers = [load_buffer(i) for i in range(load_buffer_num)]
|
|
|
self.store_buffers = [store_buffer(i) for i in range(store_buffer_num)]
|
|
|
|
|
|
self.register_result_status = register_result_status(
|
|
|
float_reg_num, int_reg_num)
|
|
|
self.mem = [mem(i) for i in range(mem_size)]
|
|
|
self.clock = 1
|
|
|
|
|
|
def lbIsFull(self):
|
|
|
for lb in self.load_buffers:
|
|
|
if lb.busy == False: return lb.index # return free buffer's index
|
|
|
return "True" # indicate Full by returning "True"
|
|
|
|
|
|
def sbIsFull(self):
|
|
|
for sb in self.store_buffers:
|
|
|
if sb.busy == False: return sb.index # return free buffer's index
|
|
|
return "True" # indicate Full by returning "True"
|
|
|
|
|
|
def print(self):
|
|
|
print("Cycle " + str(self.clock) + ":")
|
|
|
print("\nInstruction Status: ")
|
|
|
print("\t\t\t\t\t\t%s\t%s %s" %
|
|
|
("Issue", "Complete", "Write_Result"))
|
|
|
for IS in self.instruction_status:
|
|
|
IS.print()
|
|
|
self.reservation_station.print()
|
|
|
print("-\n")
|
|
|
# print("Load/Store Buffer:")
|
|
|
# print("\t\t\tBusy\tAddress\t\tFu")
|
|
|
# for lb in self.load_buffers:
|
|
|
# lb.print()
|
|
|
# for sb in self.store_buffers:
|
|
|
# sb.print()
|
|
|
# print("-\n")
|
|
|
self.register_result_status.print()
|
|
|
|
|
|
# print("Memory: \n")
|
|
|
# mem_name = "\t\t "
|
|
|
# mem_value = "\t\tValue: "
|
|
|
# for mem in self.mem:
|
|
|
# if int(mem.name.split("_")[-1]) % 8 == 0:
|
|
|
# mem_name += ("\tMem_" +
|
|
|
# str(int(int(mem.name.split("_")[-1]) / 8) + 1))
|
|
|
# mem_value += ("\t" + str(mem.value))
|
|
|
# print(mem_name + "\n")
|
|
|
# print(mem_value)
|
|
|
# print("-\n")
|
|
|
|
|
|
def isFinished(self): # check whether the insts are finished
|
|
|
for IS in self.instruction_status:
|
|
|
if IS.write == -1: return False
|
|
|
return True
|
|
|
|
|
|
def writeResult(self):
|
|
|
for RS in self.reservation_station.adders:
|
|
|
self.broadcast(RS)
|
|
|
|
|
|
for RS in self.reservation_station.multipliers:
|
|
|
self.broadcast(RS)
|
|
|
|
|
|
for RS in self.load_buffers:
|
|
|
self.broadcast(RS)
|
|
|
|
|
|
for RS in self.store_buffers:
|
|
|
if RS.busy == True and RS.time == 0:
|
|
|
if RS.qk != "null":
|
|
|
if RS.qk.split("_")[0] == "Add":
|
|
|
fus = self.reservation_station.adders
|
|
|
elif RS.qk.split("_")[0] == "Mult":
|
|
|
fus = self.reservation_station.multipliers
|
|
|
for fu in fus: # store buffer所等待的function unit(reservation station)
|
|
|
if RS.qk == fu.name and self.clock == self.instruction_status[
|
|
|
fu.inst_index].write + 1:
|
|
|
self.mem[RS.address].value = fu.result
|
|
|
RS.last_time_write = self.clock # 记录instruction最近一次的write_result时间
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].write = self.clock
|
|
|
fu.result = -1 # reset the result
|
|
|
RS.reset()
|
|
|
|
|
|
# 对沒有dependence的修改vk
|
|
|
elif RS.qk == "null": # source register(rt) 未占用
|
|
|
self.mem[RS.address].value = RS.vk
|
|
|
self.vk_broadcasted_cycle = self.clock
|
|
|
RS.last_time_write = self.clock # 记录instruction的write_result时间
|
|
|
self.instruction_status[RS.inst_index].write = self.clock
|
|
|
RS.reset()
|
|
|
|
|
|
def broadcast(self, RS):
|
|
|
if RS.busy == True and RS.time == 0:
|
|
|
RS.last_time_write = self.clock
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].write = self.clock # write result
|
|
|
|
|
|
# broadcast to all awaiting reservation stations
|
|
|
for reg in self.register_result_status.float_regs:
|
|
|
if reg.qi != "null" and reg.qi == RS.name:
|
|
|
reg.value = RS.result
|
|
|
reg.qi = "null"
|
|
|
|
|
|
for RSs in self.reservation_station.adders: # search for matched Qj or Qk
|
|
|
if RSs.busy == True and RSs.qj == RS.name:
|
|
|
RSs.vj = RS.result
|
|
|
RSs.vj_broadcasted_cycle = self.clock
|
|
|
RSs.qj = "null"
|
|
|
if RSs.busy == True and RSs.qk == RS.name:
|
|
|
RSs.vk = RS.result
|
|
|
RSs.vk_broadcasted_cycle = self.clock
|
|
|
RSs.qk = "null"
|
|
|
|
|
|
for RSs in self.reservation_station.multipliers: # search for matched Qj or Qk
|
|
|
if RSs.busy == True and RSs.qj == RS.name:
|
|
|
RSs.vj = RS.result
|
|
|
RSs.vj_broadcasted_cycle = self.clock
|
|
|
RSs.qj = "null"
|
|
|
if RSs.busy == True and RSs.qk == RS.name:
|
|
|
RSs.vk = RS.result
|
|
|
RSs.vk_broadcasted_cycle = self.clock
|
|
|
RSs.qk = "null"
|
|
|
|
|
|
for RSs in self.load_buffers: # search for matched Qj
|
|
|
if RSs.busy == True and RSs.qj == RS.name:
|
|
|
RSs.vj = RS.result
|
|
|
RSs.vj_broadcasted_cycle = self.clock
|
|
|
RSs.qj = "null"
|
|
|
RS.reset()
|
|
|
|
|
|
def execute(self):
|
|
|
for RS in self.reservation_station.adders:
|
|
|
if RS.busy == True and RS.vj != "null" and RS.vk != "null" and RS.qj == "null" and RS.qk == "null":
|
|
|
if RS.vj_broadcasted_cycle == self.clock or RS.vk_broadcasted_cycle == self.clock:
|
|
|
continue
|
|
|
else:
|
|
|
RS.time = RS.time - 1
|
|
|
if RS.time == 0:
|
|
|
if RS.op == ADDD: RS.result = RS.vj + RS.vk
|
|
|
elif RS.op == SUBD: RS.result = RS.vj - RS.vk
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].complete = self.clock
|
|
|
|
|
|
for RS in self.reservation_station.multipliers:
|
|
|
if RS.busy == True and RS.vj != "null" and RS.vk != "null" and RS.qj == "null" and RS.qk == "null":
|
|
|
if RS.vj_broadcasted_cycle == self.clock or RS.vk_broadcasted_cycle == self.clock:
|
|
|
continue
|
|
|
else:
|
|
|
RS.time = RS.time - 1
|
|
|
if RS.time == 0:
|
|
|
if RS.op == MULD: RS.result = RS.vj * RS.vk
|
|
|
elif RS.op == DIVD: RS.result = RS.vj / RS.vk
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].complete = self.clock
|
|
|
|
|
|
for RS in self.load_buffers:
|
|
|
if RS.busy == True and RS.vj != "null" and RS.qj == "null":
|
|
|
if RS.vj_broadcasted_cycle == self.clock:
|
|
|
continue
|
|
|
else:
|
|
|
RS.time = RS.time - 1
|
|
|
if RS.time == 1:
|
|
|
RS.address = RS.address + RS.vj
|
|
|
elif RS.time == 0:
|
|
|
RS.result = self.mem[RS.address].value
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].complete = self.clock
|
|
|
|
|
|
for RS in self.store_buffers:
|
|
|
#if RS.busy == True and RS.vk != "null" and RS.qk == "null":
|
|
|
#if RS.busy == True and RS.vk != "null":
|
|
|
if RS.busy == True:
|
|
|
#if RS.vk_broadcasted_cycle == self.clock: continue
|
|
|
#else:
|
|
|
if RS.time != 0:
|
|
|
RS.time = RS.time - 1
|
|
|
if RS.time == 0:
|
|
|
RS.address = RS.address + RS.vj
|
|
|
self.instruction_status[
|
|
|
RS.inst_index].complete = self.clock
|
|
|
|
|
|
def issue(self):
|
|
|
for inst in self.instruction_status:
|
|
|
if inst.issue == -1: # only issue the unissued instructions
|
|
|
if inst.name == LD:
|
|
|
index = self.lbIsFull() # index 为 free load_buffer's index
|
|
|
if index != "True" and self.load_buffers[
|
|
|
index].last_time_write != self.clock:
|
|
|
self.load_buffers[index].time = 2
|
|
|
inst.issue = self.clock
|
|
|
self.load_buffers[index].inst_index = inst.index
|
|
|
# load or store
|
|
|
if self.register_result_status.int_regs[
|
|
|
inst.rsIndex].qi != "null":
|
|
|
self.load_buffers[
|
|
|
index].qj = self.register_result_status.int_regs[
|
|
|
inst.rsIndex].qi
|
|
|
else:
|
|
|
self.load_buffers[
|
|
|
index].vj = self.register_result_status.int_regs[
|
|
|
inst.rsIndex].value # base address
|
|
|
self.load_buffers[index].qj = "null"
|
|
|
self.load_buffers[
|
|
|
index].address = inst.offset # save offset(immd. value) to address
|
|
|
self.load_buffers[index].busy = True
|
|
|
|
|
|
# load only
|
|
|
self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi = self.load_buffers[index].name
|
|
|
|
|
|
elif inst.name == SD:
|
|
|
index = self.sbIsFull()
|
|
|
if index != "True" and self.store_buffers[
|
|
|
index].last_time_write != self.clock:
|
|
|
inst.issue = self.clock
|
|
|
self.store_buffers[index].time = 1
|
|
|
self.store_buffers[index].inst_index = inst.index
|
|
|
# load or store
|
|
|
if self.register_result_status.int_regs[
|
|
|
inst.rsIndex].qi != "null":
|
|
|
self.store_buffers[
|
|
|
index].qj = self.register_result_status.int_regs[
|
|
|
inst.rsIndex].qi
|
|
|
else:
|
|
|
self.store_buffers[
|
|
|
index].vj = self.register_result_status.int_regs[
|
|
|
inst.rsIndex].value # base address
|
|
|
self.store_buffers[index].qj = "null"
|
|
|
self.store_buffers[
|
|
|
index].address = inst.offset # save offset(immd. value) to address
|
|
|
self.store_buffers[index].busy = True
|
|
|
|
|
|
# store only
|
|
|
if self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi != "null":
|
|
|
self.store_buffers[
|
|
|
index].qk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi
|
|
|
else:
|
|
|
self.store_buffers[
|
|
|
index].vk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].value # source register (rt)
|
|
|
self.store_buffers[index].qk = "null"
|
|
|
|
|
|
elif inst.name == ADDD or inst.name == SUBD or inst.name == MULD or inst.name == DIVD:
|
|
|
if inst.name == ADDD or inst.name == SUBD:
|
|
|
index = self.reservation_station.isFull(
|
|
|
self.reservation_station.adders)
|
|
|
if index != "True" and self.reservation_station.adders[
|
|
|
index].last_time_write != self.clock:
|
|
|
inst.issue = self.clock
|
|
|
self.reservation_station.adders[
|
|
|
index].inst_index = inst.index
|
|
|
if inst.name == ADDD:
|
|
|
self.reservation_station.adders[
|
|
|
index].op = ADDD
|
|
|
elif inst.name == SUBD:
|
|
|
self.reservation_station.adders[
|
|
|
index].op = SUBD
|
|
|
self.reservation_station.adders[index].time = 2
|
|
|
if self.register_result_status.float_regs[
|
|
|
inst.rsIndex].qi != "null":
|
|
|
self.reservation_station.adders[
|
|
|
index].qj = self.register_result_status.float_regs[
|
|
|
inst.rsIndex].qi
|
|
|
else:
|
|
|
self.reservation_station.adders[
|
|
|
index].vj = self.register_result_status.float_regs[
|
|
|
inst.rsIndex].value
|
|
|
self.reservation_station.adders[
|
|
|
index].qj = "null"
|
|
|
|
|
|
if self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi != "null":
|
|
|
self.reservation_station.adders[
|
|
|
index].qk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi
|
|
|
else:
|
|
|
self.reservation_station.adders[
|
|
|
index].vk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].value # base address
|
|
|
self.reservation_station.adders[
|
|
|
index].qk = "null"
|
|
|
self.reservation_station.adders[index].busy = True
|
|
|
self.register_result_status.float_regs[
|
|
|
inst.
|
|
|
rdIndex].qi = self.reservation_station.adders[
|
|
|
index].name
|
|
|
|
|
|
elif inst.name == MULD or inst.name == DIVD:
|
|
|
index = self.reservation_station.isFull(
|
|
|
self.reservation_station.multipliers)
|
|
|
if index != "True" and self.reservation_station.multipliers[
|
|
|
index].last_time_write != self.clock:
|
|
|
inst.issue = self.clock
|
|
|
self.reservation_station.multipliers[
|
|
|
index].inst_index = inst.index
|
|
|
if inst.name == MULD:
|
|
|
self.reservation_station.multipliers[
|
|
|
index].time = 10
|
|
|
self.reservation_station.multipliers[
|
|
|
index].op = MULD
|
|
|
elif inst.name == DIVD:
|
|
|
self.reservation_station.multipliers[
|
|
|
index].time = 40
|
|
|
self.reservation_station.multipliers[
|
|
|
index].op = DIVD
|
|
|
|
|
|
if self.register_result_status.float_regs[
|
|
|
inst.rsIndex].qi != "null":
|
|
|
self.reservation_station.multipliers[
|
|
|
index].qj = self.register_result_status.float_regs[
|
|
|
inst.rsIndex].qi
|
|
|
else:
|
|
|
self.reservation_station.multipliers[
|
|
|
index].vj = self.register_result_status.float_regs[
|
|
|
inst.rsIndex].value
|
|
|
self.reservation_station.multipliers[
|
|
|
index].qj = "null"
|
|
|
|
|
|
if self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi != "null":
|
|
|
self.reservation_station.multipliers[
|
|
|
index].qk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].qi
|
|
|
else:
|
|
|
self.reservation_station.multipliers[
|
|
|
index].vk = self.register_result_status.float_regs[
|
|
|
inst.rtIndex].value
|
|
|
self.reservation_station.multipliers[
|
|
|
index].qk = "null"
|
|
|
self.reservation_station.multipliers[
|
|
|
index].busy = True
|
|
|
self.register_result_status.float_regs[
|
|
|
inst.
|
|
|
rdIndex].qi = self.reservation_station.multipliers[
|
|
|
index].name
|
|
|
|
|
|
break # issue one instruction per cycle, so break from for loop anyway
|
|
|
|
|
|
|
|
|
class instruction_status:
|
|
|
|
|
|
def __init__(self, inst, i):
|
|
|
inst = inst.split()
|
|
|
self.name = inst[0]
|
|
|
self.issue = self.complete = self.write = self.rs = self.rt = self.rd = self.offset = -1
|
|
|
self.index = i # instruction index for reservation_station mapping
|
|
|
|
|
|
if self.name == LD or self.name == SD: # target address: rt = base(rs) + offset
|
|
|
self.offset = int(inst[-1].split("(")[0])
|
|
|
|
|
|
self.rs = inst[-1].split("(")[-1].split(")")[0] # base address
|
|
|
self.rsIndex = int(self.rs.split(
|
|
|
'R')[-1]) # rs index for register_result_status mapping
|
|
|
|
|
|
self.rt = inst[1] # destination register
|
|
|
self.rtIndex = int(int(self.rt.split('F')[-1]) / 2)
|
|
|
else:
|
|
|
self.rd = inst[1] # destination register
|
|
|
self.rdIndex = int(int(self.rd.split('F')[-1]) / 2)
|
|
|
|
|
|
self.rs = inst[2] # source register 1
|
|
|
self.rsIndex = int(int(self.rs.split('F')[-1]) / 2)
|
|
|
|
|
|
self.rt = inst[3] # source register 2
|
|
|
self.rtIndex = int(int(self.rt.split('F')[-1]) / 2)
|
|
|
|
|
|
def print(self):
|
|
|
if self.issue == -1: issue = ""
|
|
|
else: issue = self.issue
|
|
|
if self.complete == -1: complete = ""
|
|
|
else: complete = self.complete
|
|
|
if self.write == -1: write = ""
|
|
|
else: write = self.write
|
|
|
|
|
|
if self.name == LD or self.name == SD:
|
|
|
print("\t\t%s\t%s\t%s\t%s\t %s\t %s\t\t %s" %
|
|
|
(self.name, self.rt, self.offset, self.rs, issue, complete,
|
|
|
write))
|
|
|
else:
|
|
|
print(
|
|
|
"\t\t%s\t%s\t%s\t%s\t %s\t %s\t\t %s" %
|
|
|
(self.name, self.rd, self.rs, self.rt, issue, complete, write))
|
|
|
|
|
|
|
|
|
class reservation_station:
|
|
|
|
|
|
def __init__(self, adder_num, multiplier_num):
|
|
|
self.adders = [adder(i) for i in range(adder_num)]
|
|
|
self.multipliers = [multiplier(i) for i in range(multiplier_num)]
|
|
|
|
|
|
def isFull(self, RS):
|
|
|
for rs in RS:
|
|
|
if rs.busy == False: return rs.index
|
|
|
return "True"
|
|
|
|
|
|
def print(self):
|
|
|
print("-\n\nResevation Station:")
|
|
|
print("\t\tTime\tName\tBusy\tOp\tVj\tVk\tQj\tQk")
|
|
|
for adder in self.adders:
|
|
|
self.print_RS(adder)
|
|
|
for multiplier in self.multipliers:
|
|
|
self.print_RS(multiplier)
|
|
|
|
|
|
def print_RS(self, RS):
|
|
|
if RS.time == -1: time = ""
|
|
|
else: time = RS.time
|
|
|
if RS.busy == False: busy = "No"
|
|
|
else: busy = "Yes"
|
|
|
if RS.op == "null": op = ""
|
|
|
else: op = RS.op
|
|
|
if RS.vj == "null": vj = ""
|
|
|
else: vj = RS.vj
|
|
|
if RS.vk == "null": vk = ""
|
|
|
else: vk = RS.vk
|
|
|
if RS.qj == "null": qj = ""
|
|
|
else:
|
|
|
qj = qj = RS.qj.split("_")[0] + "_" + str(
|
|
|
int(RS.qj.split("_")[-1]) + 1)
|
|
|
if RS.qk == "null": qk = ""
|
|
|
else:
|
|
|
qk = RS.qk.split("_")[0] + "_" + str(int(RS.qk.split("_")[-1]) + 1)
|
|
|
name = RS.name.split("_")[0] + "_" + str(
|
|
|
int(RS.name.split("_")[-1]) + 1)
|
|
|
print("\t\t%4s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" %
|
|
|
(time, name, busy, op, vj, vk, qj, qk))
|
|
|
|
|
|
def adderIsFull(self, RS):
|
|
|
for adder in self.adders:
|
|
|
if adder.busy == False: return False
|
|
|
return True
|
|
|
|
|
|
def multiplierIsFull(self, RS):
|
|
|
for multiplier in self.multipliers:
|
|
|
if multiplier.busy == False: return False
|
|
|
return True
|
|
|
|
|
|
|
|
|
class adder:
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.index = i
|
|
|
self.name = "Add_" + str(i)
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.op = "null"
|
|
|
self.vj = "null"
|
|
|
self.vk = "null"
|
|
|
self.qj = "null"
|
|
|
self.qk = "null"
|
|
|
self.result = 0
|
|
|
self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
self.vk_broadcasted_cycle = -1
|
|
|
self.last_time_write = -1
|
|
|
|
|
|
def reset(self):
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.op = "null"
|
|
|
self.vj = "null"
|
|
|
self.vk = "null"
|
|
|
self.qj = "null"
|
|
|
self.qk = "null"
|
|
|
#self.result = 0
|
|
|
#self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
self.vk_broadcasted_cycle = -1
|
|
|
|
|
|
|
|
|
class multiplier:
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.index = i
|
|
|
self.name = "Mult_" + str(i)
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.op = "null"
|
|
|
self.vj = "null"
|
|
|
self.vk = "null"
|
|
|
self.qj = "null"
|
|
|
self.qk = "null"
|
|
|
self.result = 0
|
|
|
self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
self.vk_broadcasted_cycle = -1
|
|
|
self.last_time_write = -1
|
|
|
|
|
|
def reset(self):
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.op = "null"
|
|
|
self.vj = "null"
|
|
|
self.vk = "null"
|
|
|
self.qj = "null"
|
|
|
self.qk = "null"
|
|
|
#self.result = 0
|
|
|
#self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
self.vk_broadcasted_cycle = -1
|
|
|
|
|
|
|
|
|
class load_buffer:
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.index = i # index for register_result_status mapping
|
|
|
self.name = "Load_" + str(i)
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.vj = "null" # base address
|
|
|
self.qj = "null" # the function unit which is processing base address
|
|
|
self.address = 0
|
|
|
self.result = 0
|
|
|
self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
self.last_time_write = -1
|
|
|
|
|
|
def reset(self):
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.vj = "null"
|
|
|
self.qj = "null"
|
|
|
self.address = 0
|
|
|
#self.result = 0
|
|
|
#self.inst_index = -1
|
|
|
self.vj_broadcasted_cycle = -1
|
|
|
|
|
|
def print(self):
|
|
|
if self.busy == False: busy = "No"
|
|
|
else: busy = "Yes"
|
|
|
if self.qj == "null": qj = ""
|
|
|
else:
|
|
|
qj = self.qj.split("_")[0] + "_" + str(
|
|
|
int(self.qj.split("_")[-1]) + 1)
|
|
|
name = self.name.split("_")[0] + "_" + str(
|
|
|
int(self.name.split("_")[-1]) + 1)
|
|
|
print("\t\t%s\t%s\t%s\t\t%s" % (name, busy, self.address, qj))
|
|
|
|
|
|
|
|
|
class store_buffer:
|
|
|
# mem[rs + immd.(offset)] = rt
|
|
|
def __init__(self, i):
|
|
|
self.index = i # index for register_result_status mapping
|
|
|
self.name = "Store_" + str(i)
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.vj = "null" # base address register(rs)
|
|
|
self.vk = "null" # source register (rt)
|
|
|
self.qj = "null"
|
|
|
self.qk = "null" # the function unit which is processing base address
|
|
|
self.address = 0
|
|
|
self.result = 0
|
|
|
self.inst_index = -1 # reservation_station 处理的是哪一个 instruction
|
|
|
self.vk_broadcasted_cycle = -1 # 为了不让RS在broadcast的cycle就开始执行,因此必须在RS记录得到broadcast的时间(cycle)
|
|
|
self.last_time_write = -1 # 为了禁止在write result之后的下个cycle释放station后,马上被新的指令issue并放入station中,
|
|
|
# 因此记录该 station 上个指令的 write result 时间,让下个指令必须2个cycle才能issue。
|
|
|
|
|
|
def reset(self):
|
|
|
self.time = -1
|
|
|
self.busy = False
|
|
|
self.vj = "null"
|
|
|
self.vk = "null"
|
|
|
self.qj = "null"
|
|
|
self.qk = "null"
|
|
|
self.address = 0
|
|
|
#self.result = 0
|
|
|
#self.inst_index = -1
|
|
|
self.vk_broadcasted_cycle = -1
|
|
|
|
|
|
def print(self):
|
|
|
if self.busy == False: busy = "No"
|
|
|
else: busy = "Yes"
|
|
|
if self.qk == "null": qk = ""
|
|
|
else:
|
|
|
qk = self.qk.split("_")[0] + "_" + str(
|
|
|
int(self.qk.split("_")[-1]) + 1)
|
|
|
name = self.name.split("_")[0] + "_" + str(
|
|
|
int(self.name.split("_")[-1]) + 1)
|
|
|
print("\t\t%s\t%s\t%s\t\t%s" % (name, busy, self.address, qk))
|
|
|
|
|
|
|
|
|
class mem: # 内存8个Double(64-bit)的(64-Bytes),初始值1
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.name = "Mem_" + str(i)
|
|
|
if i % 8 == 0: self.value = 1
|
|
|
else: self.value = 0
|
|
|
|
|
|
|
|
|
class register_result_status:
|
|
|
|
|
|
def __init__(self, float_reg_num, int_reg_num):
|
|
|
self.float_regs = [float_reg(i) for i in range(float_reg_num)
|
|
|
] # 浮点寄存器F0、F2、F4、…、F30,初始值1;
|
|
|
self.int_regs = [int_reg(i)
|
|
|
for i in range(int_reg_num)] # 整数寄存器R0、R1、…、R31
|
|
|
self.int_regs[1].value = 16
|
|
|
|
|
|
def print(self):
|
|
|
print("Register result status:")
|
|
|
a = ""
|
|
|
for fr in self.float_regs:
|
|
|
a += fr.name + "\t"
|
|
|
print("\t\t\t" + a)
|
|
|
|
|
|
a = ""
|
|
|
for fr in self.float_regs:
|
|
|
if fr.qi == "null": qi = ""
|
|
|
else:
|
|
|
qi = fr.qi.split("_")[0] + "_" + str(
|
|
|
int(fr.qi.split("_")[-1]) + 1)
|
|
|
a += str(qi) + "\t"
|
|
|
print("\t\tQi:\t" + a)
|
|
|
|
|
|
a = ""
|
|
|
for fr in self.float_regs:
|
|
|
a += str(fr.value) + "\t"
|
|
|
print("\t\tvalue:\t" + a)
|
|
|
# print("\n")
|
|
|
|
|
|
# a = ""
|
|
|
# for ir in self.int_regs:
|
|
|
# a += ir.name + "\t"
|
|
|
# print("\t\t\t" + a)
|
|
|
|
|
|
# a = ""
|
|
|
# for ir in self.int_regs:
|
|
|
# if ir.qi == "null": qi = ""
|
|
|
# else:
|
|
|
# qi = ir.qi.split("_")[0] + "_" + str(
|
|
|
# int(ir.qi.split("_")[-1]) + 1)
|
|
|
# a += str(qi) + "\t"
|
|
|
# print("\t\tQi:\t" + a)
|
|
|
|
|
|
# a = ""
|
|
|
# for ir in self.int_regs:
|
|
|
# a += str(ir.value) + "\t"
|
|
|
# print("\t\tvalue:\t" + a)
|
|
|
print("-\n")
|
|
|
|
|
|
|
|
|
class float_reg:
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.name = "F" + str(i * 2)
|
|
|
self.value = 1
|
|
|
self.qi = "null" # 正在等待的 function unit
|
|
|
|
|
|
def print(self):
|
|
|
print("reg %s, value: %d" % (self.name, self.value))
|
|
|
|
|
|
|
|
|
class int_reg:
|
|
|
|
|
|
def __init__(self, i):
|
|
|
self.name = "R" + str(i)
|
|
|
self.value = 0
|
|
|
self.qi = "null" # 正在等待的 function unit
|
|
|
|
|
|
def print(self):
|
|
|
print("reg %s, value: %d" % (self.name, self.value))
|
|
|
|
|
|
|
|
|
def __main__():
|
|
|
# read argument from command lind
|
|
|
# input_argv = "Computer Architecture\TomasuloAlgorithm-master\sample1.txt"
|
|
|
# f = open(input_argv, 'r')
|
|
|
# insts = f.readlines() # read instructions from text file
|
|
|
insts = [
|
|
|
'L.D F6, 8(R2)',
|
|
|
'L.D F2, 40(R3)',
|
|
|
'MUL.D F0, F2, F4',
|
|
|
'SUB.D F8, F6, F2',
|
|
|
'DIV.D F10, F0, F6',
|
|
|
'ADD.D F6, F8, F2',
|
|
|
]
|
|
|
|
|
|
# f.close()
|
|
|
|
|
|
adder_num = 3
|
|
|
multiplier_num = load_buffer_num = store_buffer_num = 2
|
|
|
float_reg_num = 16 # 浮点寄存器, from F0, F2, F4, …, to F30, 初始值为1;
|
|
|
int_reg_num = 32 # 整数寄存器, from R0, R1, …, to R31
|
|
|
mem_size = 64 # 64-byte memory(8 double-precision space)
|
|
|
tomasulo = Tomasulo(insts, adder_num, multiplier_num, load_buffer_num,
|
|
|
store_buffer_num, float_reg_num, int_reg_num, mem_size)
|
|
|
|
|
|
# original_stdout = sys.stdout
|
|
|
# sys.stdout = open(
|
|
|
# r"Computer Architecture\TomasuloAlgorithm\output.txt", "w")
|
|
|
while (True):
|
|
|
#ipdb.set_trace()
|
|
|
tomasulo.writeResult() # 执行已完成Execution的指令
|
|
|
tomasulo.execute() # 执行已完成Issue的指令,维护指令
|
|
|
tomasulo.issue() # issue指令
|
|
|
|
|
|
tomasulo.print()
|
|
|
tomasulo.clock += 1 # steps one clock cycle
|
|
|
|
|
|
if tomasulo.isFinished(): break
|
|
|
#if tomasulo.clock > 71: break
|
|
|
# sys.stdout = original_stdout
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
__main__()
|