python模拟基于risc-v指令集的加法运算

本文档展示了一段实现RISC-V指令集的Python代码,包括加载、存储、移位、算术和逻辑运算、比较、分支、跳转等指令。代码中定义了寄存器和内存类,并提供了相应的指令执行函数。此外,还包含了一个简单的ISA类用于解码指令。
摘要由CSDN通过智能技术生成

本段代码实现了部分risc-v指令,没有全部实现,具体risc-v指令集看我的下载

#RISC-V
#小端模式

# 寄存器类
Register = {
    0b00000: 0x00000000,
    0b00001: 0xf2345678,
    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

}

# 储存器类
Memory = {
    0x00000000: 0b01000001,
    0x00000001: 0b10000000,
    0x00000002: 0b00001000,
    0x00000003: 0b11000000,
    0x00000004: 0b00000000,
    0x00000005: 0b00000000,
    0x00000006: 0b00000000,
    0x00000007: 0b00000000,
    0x00000008: 0b00000000,
    0x00000009: 0b00000000,
    0x0000000A: 0b00000000,
    0x0000000B: 0b00000000,
    0x0000000C: 0b00000000,
    0x0000000D: 0b00000000,
    0x0000000E: 0b00000000,
    0x0000000F: 0b00000000,
    0x00000010: 0b00000000,
    0x00000011: 0b00000000,
    0x00000012: 0b00000000,
    0x00000013: 0b00000000,
    0x00000014: 0b00000000,
    0x00000015: 0b00000000,
    0x00000016: 0b00000000,
    0x00000017: 0b00000000,
    0x00000018: 0b00000000,
    0x00000019: 0b00000000,
    0x0000001A: 0b00000000,
    0x0000001B: 0b00000000,
    0x0000001C: 0b00000000,
    0x0000001D: 0b00000000,
    0x0000001E: 0b00000000,
    0x0000001F: 0b00000000,
    0x00000020: 0b00000000,
    0x00000021: 0b00000000,
    0x00000022: 0b00000000,
    0x00000023: 0b00000000,
    0x00000024: 0b00000000,
    0x00000025: 0b00000000,
    0x00000026: 0b00000000,
    0x00000027: 0b00000000,
    0x00000028: 0b00000000,
    0x00000029: 0b00000000,
    0x0000002A: 0b00000000,
    0x0000002B: 0b00000000,
    0x0000002C: 0b00000000,
    0x0000002D: 0b00000000,
    0x0000002E: 0b00000000,
    0x0000002F: 0b00000000,
    0x00000030: 0b00000000,
    0x00000031: 0b00000000,
    0x00000032: 0b00000000,
    0x00000033: 0b00000000,
    0x00000034: 0b00000000,
    0x00000035: 0b00000000,
    0x00000036: 0b00000000,
    0x00000037: 0b00000000,
    0x00000038: 0b00000000,
    0x00000039: 0b00000000,
    0x0000003A: 0b00000000,
    0x0000003B: 0b00000000,
    0x0000003C: 0b00000000,
    0x0000003D: 0b00000000,
    0x0000003E: 0b00000000,
    0x0000003F: 0b00000000

}


# 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):
    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):
    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):
    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):
    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):
    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

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

    def defInstr(self,addr):  # 传入参数为指令在内存的地址
        instru = 0x00000000
        for i in range(4):
            # print(hex(addr + i))
            # print(hex(Memory[addr + i]))
            instru += Memory[addr + 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
    }

    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
        }
        Format = switch.get(opcode, 'Invalid')
        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):
        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)
        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)
        return False

    def decodeSFormat(self, instruction):
        imm = (instruction >> 7) & 0b11111 + (instruction >> 25) * 0b100000
        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)
        return False

    def decodeSBFormat(self, instruction):
        imm = (instruction >> 7) & 0b11111 + (instruction >> 25) * 0b100000
        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
        if opcode == 0b0110111:
            return lui(rd, imm)
        elif opcode == 0b0010111:
            return auipc(rd, imm)
        return False

    def decodeUJFormat(self, instruction):
        return False


def main():


    #取指
        #io,采取直接写死的方式
    # load r1, #0
    # 采用基址寻址和寄存器间接寻址,通过寄存器中的内容加offset得到内存中的地址,然后去内存中取源操作数
    # load 指令为0 00 00 11
    # imm[11:0]     rs1     func3    rd      opcode
    # offset        base    width    dst     load
    # 000000000000  00001   010      00010   0000011
    # imm =+0       rs1=1   lw       rd=2    load
    # 0x000 0A 1 03采用小端方式存储,内容为0x03 A1 00 00
    Memory[0x00000000]= 0x03
    Memory[0x00000001]= 0xA1
    Memory[0x00000002]= 0x00
    Memory[0x00000003]= 0x00

    # load r2, #1
    # imm[11:0]     rs1     func3    rd      opcode
    # offset        base    width    dst     load
    # 000000000000  00011   010      00100   0000011
    # imm =+0       rs1=3   lw       rd=4    load
    # 0x000 1A 2 03采用小端方式存储,内容为0x03 A2 01 00
    Memory[0x00000004]= 0x03
    Memory[0x00000005]= 0xA2
    Memory[0x00000006]= 0x01
    Memory[0x00000007]= 0x00

    # add r3, r1, r2
    # 这里r3的地址为:0b00101,r1的地址为:0b00010,r2的地址为:0b00100
    # funct7     rs2     rs1     funct3      rd      opcode
    # 0000000    00100   00010   000         00101   0110011
    # 其中funct7和funct3的组合表示加法运算
    # 16进制表示为0x 00 41 02 B3小端模式表示为0xB3 02 41 00
    Memory[0x00000008]= 0xB3
    Memory[0x00000009]= 0x02
    Memory[0x0000000A]= 0x41
    Memory[0x0000000B]= 0x00

    # store r3, #3
    # r3为0b00101,#3采用基址寻址+间接寻址,内存起始地址为0x00000019,基址寄存器为0b00110,offset为0
    #               rs2需要存储的数据
    #                       rs1基址寄存器
    # imm[11:5]      rs2     rs1     func3       imm[4:0]        opcode
    # 0000000        00101   00110   010         00000           0100011
    # 其十六进制表示为0x00 53 20 23
    Memory[0x0000000C]= 0x23
    Memory[0x0000000D]= 0x20
    Memory[0x0000000E]= 0x53
    Memory[0x0000000F]= 0x00

    # 这个内存地址用来存放第一条load指令的数据
    # 令第一个加数为1:0x00000001,小端存储为0x01000000
    Memory[0x00000010]= 0x01
    Memory[0x00000011]= 0x00
    Memory[0x00000012]= 0x00
    Memory[0x00000013]= 0x00

    # 这个内存地址用来存放第二条load指令的数据
    # 令第二个加数为2:0x00000002,小端存储为0x02000000
    Memory[0x00000014]= 0x02
    Memory[0x00000015]= 0x00
    Memory[0x00000016]= 0x00
    Memory[0x00000017]= 0x00

    #寄存器
    Register[0b00001]= 0x00000010  # 第一条指令基址寻址的基址寄存器
    Register[0b00010]= 0x00000000  # 第一条指令load的目的寄存器,初始内容为0
    Register[0b00011]= 0x00000014  # 第二条load指令基址寻址的基址寄存器
    Register[0b00100]= 0x00000000  # 第二条load指令的目的寄存器,厨师内容为0
    Register[0b00101]= 0x00000000  # 用来存储add指令的计算结果
    Register[0b00110]= 0x00000018  # store指令中基址寄存器

    #译码
        #这里通过while循环取指令,然后执行指令
    #执行

    pc = 0x00000000

    for i in range(12):
        # 首先读取指令,然后根据指令判断进行pc+1还是进行跳转
        # 读取指令:读取pc指向内存地址的内容
        ISA(pc)
        #print(pc)
        print(hex(Memory[0x00000018]))
        print(hex(Memory[0x00000019]))
        print(hex(Memory[0x0000001A]))
        print(hex(Memory[0x0000001B]))
        pc += 4  # 这里小端模式的处理方式有待商榷

    pass

main()

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值