python模拟硬件实现加法运算

该博客详细介绍了如何使用RISC-V指令集在Python中模拟硬件实现简单的1+2=3运算。程序遵循小端模式,寄存器0保持为0,不可修改。通过load指令加载数据,add指令执行加法,store指令将结果存储回内存。文章还展示了指令解析、内存布局和寄存器操作的过程。
摘要由CSDN通过智能技术生成

下面的程序用python模拟硬件实现了1+2=3这个简单的运算,本程序基于risc-v指令集,采用小端模式,寄存器0中恒存0,不能被修改

用到的risc-v指令集见下载文档

#基于risc-v指令集
#小端模式
Register = {
    #risc指令集中第零号寄存器恒存0
    0b00001 : 0x00000010,       #第一条指令基址寻址的基址寄存器
    0b00010 : 0x00000000,       #第一条指令load的目的寄存器,初始内容为0
    0b00011 : 0x00000014,       #第二条load指令基址寻址的基址寄存器
    0b00100 : 0x00000000,       #第二条load指令的目的寄存器,厨师内容为0
    0b00101 : 0x00000000,       #用来存储add指令的计算结果
    0b00110 : 0x00000018        #store指令中基址寄存器

}

Memory = {
    #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
    0x00000000 : 0x03,
    0x00000001 : 0xA1,
    0x00000002 : 0x00,
    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
    0x00000004 : 0x03,
    0x00000005 : 0xA2,
    0x00000006 : 0x01,
    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
    0x00000008 : 0xB3,
    0x00000009 : 0x02,
    0x0000000A : 0x41,
    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
    0x0000000C : 0x23,
    0x0000000D : 0x20,
    0x0000000E : 0x53,
    0x0000000F : 0x00,

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

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

    #这个内存地址用来存放store指令的数据
    #初始为0
    0x00000018 : 0x00,
    0x00000019 : 0x00,
    0x0000001A : 0x00,
    0x0000001B : 0x00
}

#指令类型
Instruction = {
    0b0000011 : 'load',
    0b0110011 : 'add',
    0b0100011 : 'store'
}

#读取指令,根据pc中的内容,读取memory中的内容,大小为四个存储单元
#读取到的内容进行解析
#大端,小端,以及左右顺序问题
#对操作码的解析:0-6,表示操作码,如何模拟查询操作?
#需要定义指令集
def defInstr(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

def judgeType(instru):
    return Instruction[instru & 0b1111111]

#load指令
def load(instru):
    #offset     base        width       dst     load
    #imm[11:0]  rs1         func3       rd      opcode
    #1 找到base中的内容
    #2 base中的内容和offset相加,得到内存地址
    #3 将内存单元的内容复制到dst
    offset = instru >> 20
    rs1 = (instru >> 15) & 0b11111
    rd = (instru >> 7) & 0b11111
    Register[rd] = defInstr(Register[rs1] + offset)


#add指令
def add(instru):
    #funct7     rs2     rs1     funct3      rd      opcode
    #1 取出rs2和rs1,rd
    #2 做加法运算
    #3 判断溢出(通过抑或)
    rs2 = (instru >> 20) & 0b11111
    rs1 = (instru >> 15) & 0b11111
    rd = (instru >> 7) & 0b11111
    #print(Register[rs1],Register[rs2],Register[rd])
    a1=Register[rs1]
    a2=Register[rs2]
    R1=[0]*33
    R2=[0]*33
    R3=[0]*33
    for i in range(0,32):
        R1[32-i]=a1%2
        R2[32-i]=a2%2
        a1=a1>>1
        a2=a2>>1
    R1[0]=R1[1]
    R2[0]=R2[1]
    carry=0
    for i in range(0,33):
        R3[32-i]=(carry+R1[32-i]+R2[32-i])%2
        carry=(carry+R1[32-i]+R2[32-i])>>1
    if R3[0]!=R3[1]:
        return 0
    for i in range(1,33):
        Register[rd]=Register[rd]*2+R3[i]

#store指令
def store(instru):
    #imm[11:5]      rs2     rs1     func3       imm[4:0]    opcode
    #1 读取寄存器和offset的内容
    #2 拼接出offset的大小
    #3 rs2存储数据,rs1表示基址寄存器,里面的内容和offset相加得到内存地址
    #4 将rs2中的内容存放到内存中
    rs2 = (instru >> 20) & 0b11111
    rs1 = (instru >> 15) & 0b11111
    im1 = (instru >> 25)
    im2 = (instru >> 7) & 0b11111
    im = im1 << 5 + im2
    memAddr = rs1 + im
    for i in range(4):
        Memory[memAddr + i] = Register[rs2] & 0xff
        Register[rs2] = Register[rs2] >> 8
        print(hex(Memory[memAddr + i]))

def main():
    #首先进行,pc加一这种操作
    #pc指向指令在内存中的地址,32位
    #寄存器,32个,需要5位寻找一个寄存器
    #内存:32位地址,说明pc的内容占32位
    #pc的初值:设为0地址
    #pc+1怎么实现:取决于risc-v是定长指令系统还是不定长指令,32位定长指令集
    pc = 0x00000000
    while (1):
        #首先读取指令,然后根据指令判断进行pc+1还是进行跳转
        #读取指令:读取pc指向内存地址的内容
        instru = defInstr(pc)
        print(hex(pc))
        print(hex(instru))
        print (judgeType(instru))
        if judgeType(instru) == 'load':
            load(instru)
        elif judgeType(instru) == 'add':
            add(instru)
            print(Register[0b00101])
        elif judgeType(instru) == 'store':
            store(instru)
        pc += 4#这里小端模式的处理方式有待商榷
        print(pc)

main()#程序入口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值