ADD file via upload

master
pl7xmnuv6 3 years ago
parent 50fb8c3e67
commit e89d766fbf

@ -0,0 +1,733 @@
# -*- 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__()
Loading…
Cancel
Save