python模拟硬件实现btb和tomasulo算法

本程序在上一个tomasulo算法的基础上添加了btb分支预测

代码实现如下

# RISC-V
# 小端模式

# 硬件
Hardware = {
    # tag:还剩多久执行完毕;  busy:0空闲,1不空闲;  op:'lw' 'sw' 'mul' 'addi' 'bne'五条指令
    # 'addi'指令:'imm'用来存立即数
    # s1_vj和s2_vk:直接存数;   rs_qj和rs_qk:存 'load1' 'mult2' 'add3'等
    # rs_qj和rs_qk:如果有数据,不需要指针,则这两个指针置为数字0
    # 寄存器中,如果有结果直接存数,如果是指针,则同rs_qj和rs_qk存 'load1' 'mult2' 'add3'等
    # isinstance()函数可以判断数据类型是不是指定类型,例如isinstance(Hardware['load1']['busy'],int)==True/False
    'load1': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        'op' : 0
    },
    'load2': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        'op' : 0
    },
    'load3': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        'op' : 0
    },
    'store1': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        's1_vj': 0,
        'rs_qj': 0,
        'op' : 0
    },
    'store2': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        's1_vj': 0,
        'rs_qj': 0,
        'op' : 0
    },
    'store3': {
        'tag': 0,
        'busy': 0,
        'address': 0,
        'data': 0,
        's1_vj': 0,
        'rs_qj': 0,
        'op' : 0
    },
    'add1': {
        'tag': 0,
        'busy': 0,
        'op': 0,
        's1_vj': 0,
        's2_vk': 0,
        'rs_qj': 0,
        'rs_qk': 0,
        'imm': 0,
        'data': 0
    },
    'add2': {
        'tag': 0,
        'busy': 0,
        'op': 0,
        's1_vj': 0,
        's2_vk': 0,
        'rs_qj': 0,
        'rs_qk': 0,
        'imm': 0,
        'data': 0
    },
    'add3': {
        'tag': 0,
        'busy': 0,
        'op': 0,
        's1_vj': 0,
        's2_vk': 0,
        'rs_qj': 0,
        'rs_qk': 0,
        'imm': 0,
        'data': 0
    },
    'mult1': {
        'tag': 0,
        'busy': 0,
        'op': 0,
        's1_vj': 0,
        's2_vk': 0,
        'rs_qj': 0,
        'rs_qk': 0,
        'data': 0
    },
    'mult2': {
        'tag': 0,
        'busy': 0,
        'op': 0,
        's1_vj': 0,
        's2_vk': 0,
        'rs_qj': 0,
        'rs_qk': 0,
        'data': 0
    }
}
# 调用方式
# Hardware['load1']['busy']='6'
# print(Hardware['load1']['busy'])
# print(isinstance(Hardware['load1']['busy'],int))

'''for key in Hardware:
    print(Hardware[key]['tag'])
    pass'''

# 寄存器类
X_ = 0x00000033
Register = {
    0b00000: 0x00000000,
    0b00001: 0x00000000,
    0b00010: 0x00000008,
    0b00011: 0x00000000,
    0b00100: 0x00000000,
    0b00101: 0x00000000,
    0b00110: 0x00000000,
    0b00111: 0x00000000,
    0b01000: 0x00000000,
    0b01001: 0x00000000,
    0b01010: 0x00000000,
    0b01011: 0x00000000,
    0b01100: 0x00000000,
    0b01101: 0x00000000,
    0b01110: 0x00000000,
    0b01111: 0x00000000,
    0b10000: 0x00000000,
    0b10001: 0x00000000,
    0b10010: 0x00000000,
    0b10011: 0x00000000,
    0b10100: 0x00000000,
    0b10101: 0x00000000,
    0b10110: 0x00000000,
    0b10111: 0x00000000,
    0b11000: 0x00000000,
    0b11001: 0x00000000,
    0b11010: 0x00000000,
    0b11011: 0x00000000,
    0b11100: 0x00000000,
    0b11101: 0x00000000,
    0b11110: 0x00000000,
    0b11111: 0x00000000

}
pc = 0x00000000
'''Register[0]=0
if(isinstance(Register[0],str)):
    print(type(Register[0]),'class')
    print('ss')
elif(isinstance(Register[0],int)):
    print(type(Register[0]), 'int')
    print('ii')'''

# 储存器类
Memory = {
    0x00000000: 0x00
}

# 控制BTB的执行
BTB={
    0x00000000:[0x00000000,0,0], #PC:[PC_predict,tag1,tag2];tag1为第一次判断结果(yes:1/no:0),tag2为第二次判断结果
}

PC_Control = [0,0,0,0]#[PC,PC_IF,PC_ID,PC_EX],分阶段存下该阶段所执行指令对应的PC值

# 初始化内存,大小为16KB
def init_Mem():
    for i in range(2 ** 14):
        Memory[0x00000000 + i] = 0x00


# *****************Tomasulo**************
def Refresh(a):  # 如果得到了某个数据,则利用这个函数,刷新需要这个数据的所有buffer和寄存器
    a1 = list(a)
    a1.pop()
    a1 = ''.join(a1)
    if a1 == 'store':
        Memory[Hardware[a]['address']] = Hardware[a]['data']
        return

    for key in Register:  # 刷新寄存器
        if Register[key] == a:
            Register[key] = Hardware[a]['data']
            pass
        pass

    for key in Hardware:  # 刷新buffer
        key1 = list(key)
        key1.pop()
        key1 = ''.join(key1)
        if key1 == 'load':
            continue
        if key1 == 'store':
            if Hardware[key]['rs_qj'] == a:
                Hardware[key]['s1_vj'] = Hardware[a]['data']
                Hardware[key]['rs_qj'] = 0
                Hardware[key]['tag'] = 2
            continue
        if Hardware[key]['rs_qj'] == a or Hardware[key]['rs_qk'] == a:
            if Hardware[key]['rs_qj'] == a:
                Hardware[key]['s1_vj'] = Hardware[a]['data']
                Hardware[key]['rs_qj'] = 0
            if Hardware[key]['rs_qk'] == a:
                Hardware[key]['s2_vk'] = Hardware[a]['data']
                Hardware[key]['rs_qk'] = 0
            if Hardware[key]['rs_qj'] == 0 and Hardware[key]['rs_qk'] == 0:  # 所需数据准备完毕,则进入执行阶段
                if Hardware[key]['op'] == 'addi' or Hardware[key]['op'] == 'bne':
                    Hardware[key]['tag'] = 2
                elif Hardware[key]['op'] == 'mul':
                    Hardware[key]['tag'] = 10
            pass
        pass
    pass

IF_Found = False
ID_Branch = False

def IF():
    global IF_Found
    # IF阶段
    # 第一次判断,PC_Control是否在BTB中
    global pc
    if pc== 64:
        print(pc)
    PC_Control[0] = pc
    # PC_Control[0] = PC_Control[0] + 1  # PC_Control[0]表示PC_Control值
    PC_Control[1] = PC_Control[0] + 1  # PC_Control_IF,IF阶段的PC_Control
    if PC_Control[0] in BTB:
        #BTB[PC_Control[1]][1] = 1
        IF_Found = True
    else:
        #BTB[PC_Control[0]] = [0, 0, 0]  # 如果没有命中BTB,插入一条item方便后续操作
        IF_Found = False
    pass

def ID():
    global IF_Found
    global ID_Branch
    global BTB
    # ID阶段
    PC_Control[2] = PC_Control[1]  # PC_Control_ID,ID阶段指令对应的PC_Control

    #opcode = Memory[PC_Control[0]] & 0b1111111
    instru = 0x00000000
    for i in range(4):
        instru += Memory[PC_Control[0] + i] * (256 ** i)
    opcode = instru & 0b1111111

    if (IF_Found == False):
        if opcode == 0b1100011:  # 如果是分支指令
            #这里需要知道当前正在执行的指令的下一条语句,稍后处理这一段
            ID_Branch = True
            # BTB[PC_Control[0]] = [48,1,0]
        else:
            ID_Branch = False
            return
    else:
        pass
        """
        if BTB[PC_Control[2]][1] == 1 and BTB[PC_Control[2]][2] == 1:  # 是分支指令,并且命中BTB时,将预测地址赋值给PC_Control,因为PC_Control会自增,这里提前-1
            PC_Control[0] = BTB[PC_Control[2]][0]
        """

    """
    if opcode == 0b1100011:  # 如果是分支指令
        BTB[PC_Control[2]][2] = 1
    else:
        BTB[PC_Control[2]][2] = 0
        
    if BTB[PC_Control[2]][1] == 1 and BTB[PC_Control[2]][2] == 1:  # 是分支指令,并且命中BTB时,将预测地址赋值给PC_Control,因为PC_Control会自增,这里提前-1
        PC_Control[0] = BTB[ PC_Control[2]][0]
    """
    pass

def Issue():  # 指令流出
    # 1 首先检查是否可进行指令流出
    # 2 若可以进行指令流出则设置对应硬件的状态
    # 3 若流出则安排pc加四的位置
    global IF_Found
    global ID_Branch
    IF_Found = False
    ID_Branch = False
    IF()
    ID()
    ISA()
    # 只修改了这次用到的几个函数,将函数的实现改完,硬件状态的改变以及是否流出

    pass


def BTB_Exec():
    global IF_Found
    global ID_Branch
    global pc
    if IF_Found == False and ID_Branch == False:
        return
    elif IF_Found == False and ID_Branch == True:
        BTB[PC_Control[0]] = [pc, 1, 0]
    elif IF_Found == True:
        if BTB[PC_Control[0]][0] == pc:
            pass
        else:
            BTB.pop(PC_Control[0])
    """
    # EX阶段
    PC_Control[3] = PC_Control[2]  # PC_Control_EX,EX阶段指令对应的PC_Control
    if BTB[PC_Control[3]][2] == 0:  # 若不是分支指令,则删除该PC_Control在BTB中的item
        BTB.pop(PC_Control[3])
    elif BTB[PC_Control[3]][1] == 0:  # 是分支指令,但没有在BTB中时,将该PC_Control放入到BTB中
        # branch为该指令跳转的地址,需要针对指令设置;
        branch = 0  # 该指令跳转的地址,需要针对指令设置;
        BTB[PC_Control[3]][0] == branch

    print(PC_Control)
    print(BTB)
    """
    pass

def Exec():  # 指令执行

    for key in Hardware:
        if Hardware[key]['busy'] == 1 and Hardware[key]['tag'] > 0:
            Hardware[key]['tag'] -= 1

            if Hardware[key]['tag'] == 0:  # 执行结束,得到结果存到data
                if Hardware[key]['op'] == 'lw':  # 'sw' 'mul' 'addi' 'bne'
                    Hardware[key]['data'] = Memory[Hardware[key]['address']] + (Memory[Hardware[key]['address'] + 1] << 8) + (
                            Memory[Hardware[key]['address'] + 2] << 16) + (Memory[Hardware[key]['address'] + 3] << 24)
                    pass
                if Hardware[key]['op'] == 'sw':  # 'sw' 'mul' 'addi' 'bne'
                    #Memory[Hardware[key]['address']] = Hardware[key]['s1_vj']
                    #Memory[Hardware[key]['address']] = Hardware[key]['s1_vj']
                    Hardware[key]['data'] = Hardware[key]['s1_vj']
                    pass
                if Hardware[key]['op'] == 'mul':  # 'sw' 'mul' 'addi' 'bne'
                    if Hardware[key]['s1_vj'] < 2 ** 31:
                        tag1 = Hardware[key]['s1_vj']
                    else:
                        tag1 = Hardware[key]['s1_vj'] - 2 ** 32
                    if Hardware[key]['s2_vk'] < 2 ** 31:
                        tag2 = Hardware[key]['s2_vk']
                    else:
                        tag2 = Hardware[key]['s2_vk'] - 2 ** 32
                    tag3 = tag1 * tag2
                    if tag3 < 2 ** 31:
                        Hardware[key]['data'] = tag3
                    elif tag3 < 2 ** 32:
                        Hardware[key]['data'] = tag3 - 2 ** 32
                    else:
                        return False
                    pass
                if Hardware[key]['op'] == 'addi':  # 'sw' 'mul' 'addi' 'bne'
                    imm = Hardware[key]['imm']
                    if Hardware[key]['imm'] & 0b100000000000 == 0b100000000000:
                        imm = Hardware[key]['imm'] + 0b11111111111111111111000000000000
                    Hardware[key]['data'] = (Hardware[key]['s2_vk'] + imm) & 0xffffffff
                    pass
                if Hardware[key]['op'] == 'bne':  # 'sw' 'mul' 'addi' 'bne'
                    if Hardware[key]['s1_vj'] != Hardware[key]['s2_vk']:
                        global pc
                        pc += (Hardware[key]['imm'] * 4) - 4

                    BTB_Exec()
                    pass

                pass
        pass
    pass


def Write():  # 数据写回
    for key in Hardware:
        if Hardware[key]['busy'] == 1 and Hardware[key]['tag'] == 0:  # 如果该数据可以写回
            Refresh(key)  # 刷新需要这个数据的所有buffer和寄存器
            Hardware[key]['busy'] = 0
            pass
        pass
    pass


# ISA指令

# ***************************Loads***************************
# 字节加载指令
def lb(rd, rs1, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    a = Memory[Register[rs1] + imm]
    if a & 0b10000000 == 0b10000000:
        a = a + 0b11111111111111111111111100000000
    Register[rd] = a
    pass


# 半字加载指令
def lh(rd, rs1, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8)
    if a & 0b1000000000000000 == 0b1000000000000000:
        a = a + 0b11111111111111110000000000000000
    Register[rd] = a
    pass


# 字加载指令
def lw(rd, rs1, imm):
    # 将原来的实现修改为硬件状态的检查和修改以及是否流出
    # 1 检查是否有空闲的硬件,若没有则停止流出
    # 2 若有则修改硬件状态
    List = ['load1', 'load2', 'load3']
    for i in List:
        if Hardware[i]['busy'] == 0:
            # 若存在硬件是空闲的,则修改硬件状态,然后返回
            Hardware[i]['tag'] = 2
            Hardware[i]['busy'] = 1
            Hardware[i]['op'] = 'lw'
            Hardware[i]['address'] = Register[rs1] + imm
            Register[rd] = i
            return

    # 若不存在空闲硬件,则停止流出
    global pc
    pc -= 4

    """if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (
            Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)
    Register[rd] = a
    """
    pass

# 无符号字节加载指令
def lbu(rd, rs1, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    a = Memory[Register[rs1] + imm]
    Register[rd] = a
    pass


# 无符号半字加载指令
def lhu(rd, rs1, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8)
    Register[rd] = a
    pass


# ***************************Stores***************************
# 存字节指令
def sb(rs1, rs2, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111
    pass


# 存半字指令
def sh(rs1, rs2, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111
    Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111
    pass


# 存字指令
# 存字指令
def sw(rs1, rs2, imm):
    # rs1表示内存地址,rs2表示存入寄存器

    List = ['store1', 'store2', 'store3']
    for i in List:
        if Hardware[i]['busy'] == 0:
            # 若存在硬件是空闲的,则修改硬件状态,然后返回
            Hardware[i]['tag'] = 2
            Hardware[i]['busy'] = 1
            Hardware[i]['op'] = 'sw'
            Hardware[i]['address'] = Register[rs1] + imm
            if isinstance(Register[rs2], int):
                Hardware[i]['s1_vj'] = Register[rs2]
            else:
                Hardware[i]['rs_qj'] = Register[rs2]
            Register[rs2] = Hardware[i]
            return

    # 若不存在空闲硬件,则停止流出
    global pc
    pc -= 4


    """
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111
    Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111
    Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111
    Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24
    """
    pass


# ***************************Shifts***************************
# 逻辑左移指令
def sll(rd, rs1, rs2):
    Register[rd] = (Register[rs1] << (Register[rs2] & 0b11111)) & 0xffffffff
    pass


# 立即数逻辑左移
def slli(rd, rs1, shamt):
    if shamt < 0b100000:
        Register[rd] = (Register[rs1] << shamt) & 0xffffffff
    pass


# 逻辑右移指令
def srl(rd, rs1, rs2):
    Register[rd] = Register[rs1] >> (Register[rs2] & 0b11111)
    pass


# 立即数逻辑右移
def srli(rd, rs1, shamt):
    if shamt < 0b100000:
        Register[rd] = Register[rs1] >> shamt
    pass


# 算数右移指令
def sra(rd, rs1, rs2):
    Register[rd] = Register[rs1] >> (Register[rs2] & 0b11111)
    if (Register[rs1] >> 31) == 1:
        for i in range(0, Register[rs2] & 0b11111):
            Register[rd] = Register[rd] + 2 ** (31 - i)
    pass


# 立即数算数右移指令
def srai(rd, rs1, shamt):
    Register[rd] = Register[rs1] >> (shamt & 0b11111)
    if (Register[rs1] >> 31) == 1:
        for i in range(0, shamt & 0b11111):
            Register[rd] = Register[rd] + 2 ** (31 - i)
    pass


# ***************************Arithmetic***************************
# 加指令
def add(rd, rs1, rs2):
    Register[rd] = Register[rs1] + Register[rs2]
    pass


# 加立即数指令
def addi(rd, rs1, imm):
    List = ['add1', 'add2', 'add3']
    for i in List:
        if Hardware[i]['busy'] == 0:
            # 若存在硬件是空闲的,则修改硬件状态,然后返回
            Hardware[i]['tag'] = 2
            Hardware[i]['busy'] = 1
            Hardware[i]['op'] = 'addi'
            if isinstance(Register[rs1], int):
                Hardware[i]['s1_vj'] = Register[rs1]
            else:
                Hardware[i]['rs_qj'] = Register[rs1]
            Hardware[i]['imm'] = imm
            Register[rd] = Hardware[i]
            return

    # 若不存在空闲硬件,则停止流出
    global pc
    pc -= 4


    """
    # print(Register[rd],Register[rs1],imm)
    print('指令addi')
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    Register[rd] = (Register[rs1] + imm) & 0xffffffff
    print('x1:')
    print(Register[rd])
    """
    pass


# 减指令
def sub(rd, rs1, rs2):
    pass


# 高位立即数加载指令
def lui(rd, imm):
    pass


# PC加立即数指令
def auipc(rd, imm):
    pass


# ***************************Logical***************************
# 异或指令
def xor(rd, rs1, rs2):
    pass


# 立即数异或指令
def xori(rd, rs1, imm):
    pass


# 取或指令
def or_(rd, rs1, rs2):
    pass


# 立即数取或指令
def ori(rd, rs1, imm):
    pass


# 与指令
def and_(rd, rs1, rs2):
    pass


# 与立即数指令
def andi(rd, rs1, imm):
    Register[rd] = Register[rs1] + imm
    pass


def mul(rd, rs1, rs2):
    List = ['mult1', 'mult2']
    for i in List:
        if Hardware[i]['busy'] == 0:
            # 若存在硬件是空闲的,则修改硬件状态,然后返回
            Hardware[i]['tag'] = 10
            Hardware[i]['busy'] = 1
            Hardware[i]['op'] = 'mul'
            if isinstance(Register[rs1], int):
                Hardware[i]['s1_vj'] = Register[rs1]
            else:
                Hardware[i]['rs_qj'] = Register[rs1]
            if isinstance(Register[rs2], int):
                Hardware[i]['s2_vk'] = Register[rs2]
            else:
                Hardware[i]['rs_qk'] = Register[rs2]
            Register[rd] = Hardware[i]
            return

    # 若不存在空闲硬件,则停止流出
    global pc
    pc -= 4


    """
    if Register[rs1] < 2 ** 31:
        tag1 = Register[rs1]
    else:
        tag1 = Register[rs1] - 2 ** 32
    if Register[rs2] < 2 ** 31:
        tag2 = Register[rs2]
    else:
        tag2 = Register[rs2] - 2 ** 32
    tag3 = tag1 * tag2
    if tag3 < 2 ** 31:
        Register[rd] = tag3
    elif tag3 < 2 ** 32:
        Register[rd] = tag3 - 2 ** 32
    else:
        return False
    """
    pass


# ***************************Compare***************************
# 小于则置位指令
def slt(rd, rs1, rs2):
    pass


# 小于立即数则置位指令
def slti(rd, rs1, imm):
    pass


# 无符号小于则置位指令
def sltu(rd, rs1, rs2):
    pass


# 无符号小于立即数则置位指令
def sltiu(rd, rs1, imm):
    pass


# ***************************Branches***************************
# 相等时分支指令
def beq(rs1, rs2, imm):
    pass


# 不等式分支指令
def bne(rs1, rs2, imm):
    List = ['add1', 'add2', 'add3']
    for i in List:
        if Hardware[i]['busy'] == 0:
            # 若存在硬件是空闲的,则修改硬件状态,然后返回
            Hardware[i]['tag'] = 1
            Hardware[i]['busy'] = 1
            Hardware[i]['op'] = 'bne'
            Hardware[i]['s1_vj'] = Register[rs1]

            Hardware[i]['s2_vk'] = Register[rs2]

            Hardware[i]['imm'] = imm
            return

    # 若不存在空闲硬件,则停止流出
    global pc
    pc -= 4


    """
    print('指令bne')
    global pc
    if (Register[rs1] != Register[rs2]):
        pc += (imm * 4) - 4
    """
    pass


# 小于时分支指令
def blt(rs1, rs2, imm):
    pass


# 大于等于时分支指令
def bge(rs1, rs2, imm):
    pass


# 无符号小于时分支指令
def bltu(rs1, rs2, imm):
    pass


# 无符号大于等于时分支指令
def bgeu(rs1, rs2, imm):
    pass


def jalr(rd, rs1, imm):
    pass


def ecall(rd, rs1, imm):
    pass


def ebreak(rd, rs1, imm):
    pass


# ***************************Supplement***************************
# 浮点加载双字
def fld(rd, rs1, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    # print(Register[rs1], imm)
    # mout(Register[rs1] + imm)

    a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (
            Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)
    Register[rd] = a

    imm = imm + 4
    a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (
            Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)
    Register[rd + 1] = a
    print('指令fld')
    print('内存:')
    print(((Register[rs1] + imm - 4) - 56) / 8)
    print('取数:')
    rout(rd)
    pass


# 双精度浮点加
def fadd_d(rd, rs1, rs2):
    tag1 = Register[rs1 + 1] >> 31
    index1 = ((Register[rs1 + 1] >> 20) & 0b11111111111) - 1023
    mantissa1 = 1 + ((Register[rs1 + 1] & 0xfffff) * (2 ** 32) + Register[rs1]) * (2 ** (-52))
    tag2 = Register[rs2 + 1] >> 31
    index2 = ((Register[rs2 + 1] >> 20) & 0b11111111111) - 1023
    mantissa2 = 1 + ((Register[rs2 + 1] & 0xfffff) * (2 ** 32) + Register[rs2]) * (2 ** (-52))
    a = ((-1) ** tag1) * mantissa1 * (2 ** index1) + ((-1) ** tag2) * mantissa2 * (2 ** index2)
    # print(a)
    if a >= 0:
        tag3 = 0
    else:
        tag3 = 1
        a = a * (-1)
        # print(a)
    index3 = 1023
    while a >= 2:
        a = a / 2
        index3 = index3 + 1

    mantissa3 = (int)((a - 1) * (2 ** 52))
    # print(bin(tag3),bin(index3),bin(mantissa3))
    Register[rd] = mantissa3 & 0xffffffff
    # print(bin(Register[rd]))
    Register[rd + 1] = tag3 * (2 ** 31) + index3 * (2 ** 20) + (mantissa3 >> 32)
    # print(bin(Register[rd]+1))
    print('指令fadd_d')
    rout(rs1)
    rout(rs2)
    rout(rd)
    pass


'''Register[0]=0 
Register[1]=0b01000000000010110110000000000000 
Register[2]=0 
Register[3]=0b11000000001001011000000000000000 
Register[4]=0 
Register[5]=0 
fadd_d(4,0,2) 
print(bin(Register[4]),bin(Register[5])) 
print((0b11011011-0b1010110000)/(2**6),(0b111010101)/64)'''


# 双精度浮点存储
def fsd(rs1, rs2, imm):
    if imm & 0b100000000000 == 0b100000000000:
        imm = imm + 0b11111111111111111111000000000000
    Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111
    Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111
    Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111
    Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24
    rs2 = rs2 + 1
    imm = imm + 4
    Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111
    Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111
    Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111
    Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24
    print('指令fsd')
    # rout(rs2-1)
    print('存入内存:')
    print(((Register[rs1] + imm - 4) - 56) / 8)
    print('存入数:')
    mout(Register[rs1] + imm - 4)
    pass


def mout(addr):
    a = Memory[addr] + (Memory[addr + 1] << 8) + (
            Memory[addr + 2] << 16) + (Memory[addr + 3] << 24)
    addr = addr + 4
    b = Memory[addr] + (Memory[addr + 1] << 8) + (
            Memory[addr + 2] << 16) + (Memory[addr + 3] << 24)
    tag = b >> 31
    index = ((b >> 20) & 0b11111111111) - 1023
    mantissa = 1 + ((b & 0xfffff) * (2 ** 32) + a) * (2 ** (-52))
    flo = mantissa * (2 ** index) * ((-1) ** tag)
    print(flo)


def rout(addr):
    a = Register[addr]
    addr = addr + 1
    b = Register[addr]
    tag = b >> 31
    index = ((b >> 20) & 0b11111111111) - 1023
    mantissa = 1 + ((b & 0xfffff) * (2 ** 32) + a) * (2 ** (-52))
    flo = mantissa * (2 ** index) * ((-1) ** tag)
    print(flo)


# 指令集
class ISA:
    def __init__(self):
        instruction = self.defInstr()
        self.tellFormat(instruction)

    def defInstr(self):  # 传入参数为指令在内存的地址
        instru = 0x00000000
        if (pc == 68):
            print("breakpoint")
        for i in range(4):
            # print(hex(addr + i))
            # print(hex(Memory[addr + i]))
            instru += Memory[pc + i] * (256 ** i)
            # print(hex(instru))
        return instru

    instruFormat = {
        0b0110011: 'RFormat',  # 运算
        0b0010011: 'IFormat',  # 运算
        0b0000011: 'IFormat',  # load
        0b0100011: 'SFormat',  # store
        0b1100011: 'SBFormat',  # branch
        0b1101111: 'UJFormat',  # jump(大立即数跳转)
        0b1100111: 'IFormat',  # jump
        0b0110111: 'UFormat',  # rd = imm << 12
        0b0010111: 'UFormat',  # rd = pc + (imm << 12)
        0b1110011: 'IFormat',  # transfer control
        0b0100111: 'SFormat',  # fsd
        0b0000111: 'IFormat',  # fld
        0b1010011: 'RFormat',  # fadd_d
    }

    def getopfromins(self, instruction):
        return instruction & 0b1111111

    def tellFormat(self, instruction):
        opcode = self.getopfromins(instruction)
        switch = {
            0b0110011: 'RFormat',  # 运算
            0b0010011: 'IFormat',  # 运算
            0b0000011: 'IFormat',  # load
            0b0100011: 'SFormat',  # store
            0b1100011: 'SBFormat',  # branch
            0b1101111: 'UJFormat',  # jump(大立即数跳转)
            0b1100111: 'IFormat',  # jump
            0b0110111: 'UFormat',  # rd = imm << 12
            0b0010111: 'UFormat',  # rd = pc + (imm << 12)
            0b1110011: 'IFormat',  # transfer control
            0b0100111: 'SFormat',  # fsd
            0b0000111: 'IFormat',  # fld
            0b1010011: 'RFormat',  # fadd_d
        }
        Format = switch.get(opcode, 'Invalid')
        # 这里pc加四,如果后面检测到不可以流出,再进行减四
        global pc
        pc += 4
        if (Format == 'Invalid'):
            return False
        elif (Format == 'RFormat'):
            return self.decodeRFormat(instruction)
        elif (Format == 'IFormat'):
            return self.decodeIFormat(instruction)
        elif (Format == 'SFormat'):
            return self.decodeSFormat(instruction)
        elif (Format == 'SBFormat'):
            return self.decodeSBFormat(instruction)
        elif (Format == 'UFormat'):
            return self.decodeUFormat(instruction)
        elif (Format == 'UJFormat'):
            return self.decodeUJFormat(instruction)
        return False

    def decodeRFormat(self, instruction):
        opcode = instruction & 0b1111111
        funct7 = instruction >> 25
        rs2 = instruction >> 20 & 0b11111
        rs1 = instruction >> 15 & 0b11111
        funct3 = instruction >> 12 & 0b111
        rd = instruction >> 7 & 0b11111
        if (funct7 == 0x00):
            if (funct3 == 0x0):
                return add(rd, rs1, rs2)
            elif (funct3 == 0x4):
                return xor(rd, rs1, rs2)
            elif (funct3 == 0x6):
                return or_(rd, rs1, rs2)
            elif (funct3 == 0x7):
                return and_(rd, rs1, rs2)
            elif (funct3 == 0x1):
                return sll(rd, rs1, rs2)
            elif (funct3 == 0x5):
                return srl(rd, rs1, rs2)
            elif (funct3 == 0x2):
                return slt(rd, rs1, rs2)
            elif (funct3 == 0x3):
                return sltu(rd, rs1, rs2)
        elif (funct7 == 0x20):
            if (funct3 == 0x0):
                return sub(rd, rs1, rs2)
            elif (funct3 == 0x5):
                return sra(rd, rs1, rs2)
        elif (funct7 == 0x01):
            if (opcode == 0b1010011):
                return fadd_d(rd, rs1, rs2)
            elif (funct3 == 0x0 and opcode == 0b0110011):
                return mul(rd, rs1, rs2)
        return False

    def decodeIFormat(self, instruction):
        imm = instruction >> 20
        rs1 = instruction >> 15 & 0b11111
        funct3 = instruction >> 12 & 0b111
        rd = instruction >> 7 & 0b11111
        opcode = instruction & 0b1111111
        if (opcode == 0b0010011):
            if (funct3 == 0x0):
                return addi(rd, rs1, imm)
            elif (funct3 == 0x4):
                return xori(rd, rs1, imm)
            elif (funct3 == 0x6):
                return ori(rd, rs1, imm)
            elif (funct3 == 0x7):
                return andi(rd, rs1, imm)
            elif (funct3 == 0x1):
                return slti(rd, rs1, imm)
            elif (funct3 == 0x5):
                if (instruction >> 25 == 0b0000000):
                    return srli(rd, rs1, imm)
                elif (instruction >> 25 == 0b0100000):
                    return srai(rd, rs1, imm)
            elif (funct3 == 0x2):
                return slti(rd, rs1, imm)
            elif (funct3 == 0x3):
                return sltiu(rd, rs1, imm)
        elif (opcode == 0b0000011):
            if (funct3 == 0x0):
                return lb(rd, rs1, imm)
            elif (funct3 == 0x1):
                return lh(rd, rs1, imm)
            elif (funct3 == 0x2):
                return lw(rd, rs1, imm)
            elif (funct3 == 0x4):
                return lbu(rd, rs1, imm)
            elif (funct3 == 0x5):
                return lhu(rd, rs1, imm)
        elif (opcode == 0b1100111):
            if (funct3 == 0x0):
                return jalr(rd, rs1, imm)
        elif (opcode == 0b1110011):
            if (funct3 == 0x0 and imm == 0x0):
                return ecall(rd, rs1, imm)
            elif (funct3 == 0x0 and imm == 0x1):
                return ebreak(rd, rs1, imm)
        elif (opcode == 0b0000111):
            if (funct3 == 0b011):
                return fld(rd, rs1, imm)
        return False

    def decodeSFormat(self, instruction):
        imm = (instruction >> 7) & 0b11111 + (instruction >> 25) * 0b100000

        immTemp = 0b000000000000
        # 这里的imm是十二位的二进制补码,需要将其转换为机器数
        if (imm >> 11 == 1):
            for i in range(11):
                immTemp += (1 - (imm >> i & 1)) * (2 ** i)
            immTemp += 1
            imm = 0 - immTemp

        funct3 = (instruction >> 12) & 0b111
        rs1 = (instruction >> 15) & 0b11111
        rs2 = (instruction >> 20) & 0b11111
        if funct3 == 0x0:
            return sb(rs1, rs2, imm)
        elif funct3 == 0x1:
            return sh(rs1, rs2, imm)
        elif funct3 == 0x2:
            return sw(rs1, rs2, imm)
        elif funct3 == 0x3:
            return fsd(rs1, rs2, imm)
        return False

    def decodeSBFormat(self, instruction):
        a = (instruction >> 7) & 0b11111
        c = ((instruction >> 25) & 0b1111111) << 5
        imm = a + c
        immTemp = 0b000000000000
        # 这里的imm是十二位的二进制补码,需要将其转换为机器数
        if (imm >> 11 == 1):
            for i in range(11):
                immTemp += (1 - (imm >> i & 1)) * (2 ** i)
            immTemp += 1
            imm = 0 - immTemp

        funct3 = (instruction >> 12) & 0b111
        rs1 = (instruction >> 15) & 0b11111
        rs2 = (instruction >> 20) & 0b11111
        if funct3 == 0x0:
            return beq(rs1, rs2, imm)
        elif funct3 == 0x1:
            return bne(rs1, rs2, imm)
        elif funct3 == 0x4:
            return blt(rs1, rs2, imm)
        elif funct3 == 0x5:
            return bge(rs1, rs2, imm)
        elif funct3 == 0x6:
            return bltu(rs1, rs2, imm)
        elif funct3 == 0x7:
            return bgeu(rs1, rs2, imm)
        return False

    def decodeUFormat(self, instruction):
        opcode = instruction & 0b1111111
        rd = (instruction >> 7) & 0b11111

        imm = instruction >> 12
        immTemp = 0b000000000000
        # 这里的imm是十二位的二进制补码,需要将其转换为机器数
        if (imm >> 11 == 1):
            for i in range(11):
                immTemp += (1 - (imm >> i & 1)) * (2 ** i)
            immTemp += 1
            imm = 0 - immTemp

        if opcode == 0b0110111:
            return lui(rd, imm)
        elif opcode == 0b0010111:
            return auipc(rd, imm)
        return False

    def decodeUJFormat(self, instruction):
        return False


def main():
    global Register
    global Memory
    # 初始化寄存器
    Register[0b00001] = 0x00000000  # 1,2寄存器用来存储常量s
    Register[0b00010] = 0x40180000  # s=6
    # Register[0b00011] = 0x00000300  # 用来存储x1,即99,这里令其为96*8=768=0x300
    Register[0b00100] = 0x00000318  # 用来存储x2,即99 * 8 =
    # 需要变址寄存器用来找到load和store指令中的内存地址,每四条指令使用同一个变址寄存器,通过改变立即数的大小来决定内存地址的变换
    Register[0b00101] = 0x00000000  # 用来存储x1=0,用来表示load或者store指令的变址寄存器
    # 其余的寄存器用来存储加载的数字以及计算结果,其初始值都是零

    # l1 fld
    # 内存中的指令数据
    # 1 fld  f6  0x38()
    # load two word指令,立即数为0x38,转化为二进制为0011 1000
    # imm[11:0]      rs1     011     rd       0000111
    # 0000 0011 1000   0010 1   011     0011 0    000 0111
    # EA = A + (rs1)
    # 0x 03 82 B3 07
    Memory[0x00000030] = 0x07
    Memory[0x00000031] = 0xB3
    Memory[0x00000032] = 0x82
    Memory[0x00000033] = 0x03

    # l2 fadd
    # 这里rd(14\15)的地址为:0b01110,rs1(6、7数组中的元素)的地址为:0b00110,r2(1/2,常量s)的地址为:0b00001
    # funct7     rs2     rs1     funct3      rd      opcode
    # 0000001    00001   00110   001         01110   1010011
    # 其中funct7和funct3的组合表示浮点加法运算
    # 16进制表示为0x 02 13 17 53
    Memory[0x00000034] = 0x53
    Memory[0x00000035] = 0x17
    Memory[0x00000036] = 0x13
    Memory[0x00000037] = 0x02

    # l3 fsd
    # 和第一条load指令相对应
    # 内存中的指令数据
    # 1 fld
    # load two word指令,立即数为0x38,转化为二进制为0011 1000
    # imm[11:0]      rs1     110     rd       0000011
    # 000000111000   00101   110     00110    0000011

    #                rs2需要存储的数据
    #                        rs1基址寄存器
    # imm[11:5]      rs2     rs1     func3       imm[4:0]        opcode
    # 0000001        01110   00101   011         11000           0100011
    # 这里的立即数和load指令中的立即数具有相同的作用,即数组在内存中的开始地址
    # 其十六进制表示为0x02 E2 BC 23
    Memory[0x00000038] = 0x23
    Memory[0x00000039] = 0xBC
    Memory[0x0000003A] = 0xE2
    Memory[0x0000003B] = 0x02

    # l4 addi
    # x1是存储在第一条load指令的基址寄存器和imm产生的内存地址,初始值为96*4,最后的值为0
    # imm为8
    # imm[11:0]      rs1     111     rd      0010011
    # 0000 0000 1000   0010 1   000     0010 1   001 0011
    # 十六进制表示为0x 00 82 82 93
    Memory[0x0000003C] = 0x93
    Memory[0x0000003D] = 0x82
    Memory[0x0000003E] = 0x82
    Memory[0x0000003F] = 0x00

    """
    # l5 bne
    # 若x1和x2里面的内容不相等则进行分支转移
    # 分支转移中的立即数,令其为-6
    # imm[12|10:5]       rs2     rs1     func3       imm[4:1|11]     opcode
    #                    x1      x2
    # 1111111            00101   00100   001         11010            1100011
    # 16进制表示为0x FE 52 1D 63
    Memory[0x00000040] = 0x63
    Memory[0x00000041] = 0x1D
    Memory[0x00000042] = 0x52
    Memory[0x00000043] = 0xFE
    """

    # l5 bne
    # 若x1和x2里面的内容不相等则进行分支转移
    # 分支转移中的立即数,令其为-4
    # imm[12|10:5]       rs2     rs1     func3       imm[4:1|11]     opcode
    #                    x1      x2
    # 1111111            00101   00100   001         11100            1100011
    # 16进制表示为0x FE 52 1E 63
    Memory[0x00000040] = 0x63
    Memory[0x00000041] = 0x1E
    Memory[0x00000042] = 0x52
    Memory[0x00000043] = 0xFE


    # 指令后面的位置用来存储数组数据,从十进制56开始即0x38
    for i in range(100):
        Memory[0x00000044 + i * 8] = 0x00
        Memory[0x00000044 + i * 8 + 1] = 0x00
        Memory[0x00000044 + i * 8 + 2] = 0x00
        Memory[0x00000044 + i * 8 + 3] = 0x00
        m = (i + 1023) * 16
        Memory[0x00000044 + i * 8 + 4] = 0x00
        Memory[0x00000044 + i * 8 + 5] = 0x00
        Memory[0x00000044 + i * 8 + 6] = m & 0xff
        Memory[0x00000044 + i * 8 + 7] = (m >> 8) & 0xff

    """
    for i in range(100):
        print('运行前内存%d:' % i)
        mout(0x00000044 + i * 8)
    """

    global pc
    pc = 0x00000030
    clock = 0

    for clock in range(10000):
        print(pc)
        Issue()
        Exec()
        Write()
        clock += 1
        if pc == 0x00000044:
            pass

    """
    for i in range(100):
        print('运行后内存%d:' % i)
        mout(0x00000038 + i * 8)
    """

main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值