# rv32c **Repository Path**: lwhengbit/rv32c ## Basic Information - **Project Name**: rv32c - **Description**: RISC-V C扩展指令集功能模拟 - **Primary Language**: Python - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-10-25 - **Last Updated**: 2023-04-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RV32C [TOC] ## 1 实验主要内容 - 使用Python 3 模拟RISC-V指令集C扩展(RV32C)中的指令功能 ## 2 RV32C指令集 ### 2.1 RV32C指令集介绍 - RV32C指令集在RISC-V指令集中的位置 ![riscv_ref_card1](image/riscv_ref_card1.jpg) ![riscv_ref_card2](image/riscv_ref_card2.jpg) - 从上图可以看到,RV32C为RISC-V指令集的可选压缩扩展,其主要作用是压缩32位整数指令集中的某些指令,使得编译后的程序更小,所以其本质和目的是实现代码压缩。其原理是基于RISC-V开发者长期的工程实践经验限制某些字段的编码长度,大概的几点思想如下: - 1.对十个常用寄存器(a0-a5, s0-s1, sp 以及 ra)访问的频率远超过其他寄存器; - 2.许多指令的写入目标是它的源操作数之一; - 3.立即数往往很小,而且有些指令比较喜欢某些特定的立即数。 - 从上述思想中提炼出的压缩代码的方法如下: - 某些RV32C 指令只能访问那些常用寄存器; - 一些指令隐式写入源操作数的位置; - 几乎所有的立即数都被缩短了, load 和 store 操作只使用操作数整数倍尺寸的无符号数偏移量 ### 2.2 RV32C指令集详述 #### 2.2.1 RV32C指令集指令格式 - RV32C指令集指令结构如下所示,共有9种压缩指令结构,用于实现代码压缩,其中Format中的C为Compress,意为压缩,指明这种指令用于实现代码压缩 ![image](image/361409-20190729141613741-730429314.png) - 在RV32C指令结构中的rs1',rs2'和rd'并不能使用所有的32个通用寄存器,存在一定的限制,但有些指令可以使用所有的32个通用寄存器,如下所示: ![image](image/361409-20190729141630511-1752197138.png) - PS:ABI(Application Binary Interface),RISC中的通用寄存器存在两个名称,一为xX为ABI name,它们存在对应关系。 #### 2.2.2 RV32C指令 ![image-20211025201037864](image/image-20211025201037864.png) ![image-20211025201451776](image/image-20211025201451776.png) ##### 2.2.2.1 CR格式指令 ![image-20211026110030147](README.assets/image-20211026110030147.png) ![image-20211026112245837](README.assets/image-20211026112245837.png) ![image-20211026112349672](README.assets/image-20211026112349672.png) ###### 2.2.2.1.1 c.add ###### 2.2.2.1.2 c.mv ![image-20211026103225570](README.assets/image-20211026103225570.png) ![image-20211026112213379](README.assets/image-20211026112213379.png) ![image-20211026112324694](README.assets/image-20211026112324694.png) ###### 2.2.2.1.3 c.jr ###### 2.2.2.1.4 c.jalr ##### 2.2.2.2 CI格式指令 ![image-20211026102748321](README.assets/image-20211026102748321.png) ![image-20211026112143801](README.assets/image-20211026112143801.png) ###### 2.2.2.2.1 c.lwsp ###### 2.2.2.2.2 c.ldsp(RV64/128扩展,此处不实现) ###### 2.2.2.2.3 c.lqsp(RV128扩展,此处不实现) ###### 2.2.2.2.4 c.flwsp ###### 2.2.2.2.5 c.fldsp ![image-20211026103443374](README.assets/image-20211026103443374.png) ![image-20211026111559396](README.assets/image-20211026111559396.png) ![image-20211026111438216](README.assets/image-20211026111438216.png) ###### 2.2.2.2.6 c.addi ###### 2.2.2.2.7 c.addiw(RV64/128扩展,此处不实现) ###### 2.2.2.2.8 c.addi16sp ![image-20211026103416208](README.assets/image-20211026103416208.png) ![image-20211026111628214](README.assets/image-20211026111628214.png) ![image-20211026111650285](README.assets/image-20211026111650285.png) ###### 2.2.2.2.9 c.li ###### 2.2.2.2.10 c.lui ![image-20211026103620602](README.assets/image-20211026103620602.png) ![image-20211026112038038](README.assets/image-20211026112038038.png) ###### 2.2.2.2.11 c.slli ![image-20211026110307921](README.assets/image-20211026110307921.png) ![image-20211026111402283](README.assets/image-20211026111402283.png) ###### 2.2.2.2.12 c.nop ![image-20211026110319664](README.assets/image-20211026110319664.png) ![image-20211026112301687](README.assets/image-20211026112301687.png) ###### 2.2.2.2.13 c.ebreak ##### 2.2.2.3 CSS格式指令 ![image-20211026102915683](README.assets/image-20211026102915683.png) ![image-20211026112416275](README.assets/image-20211026112416275.png) ###### 2.2.2.3.1 c.swsp ###### 2.2.2.3.2 c.sdsp(RV64/128扩展,此处不实现) ###### 2.2.2.3.3 c.sqsp(RV128扩展,此处不实现) ###### 2.2.2.3.4 c.fswsp ###### 2.2.2.3.5 c.fsdsp ##### 2.2.2.4 CIW格式指令 ![image-20211026103515846](README.assets/image-20211026103515846.png) ![image-20211026111141415](README.assets/image-20211026111141415.png) ###### 2.2.2.4.1 c.addi4spn ##### 2.2.2.5 CL格式指令 ![image-20211026103008343](README.assets/image-20211026103008343.png) ![image-20211026111235003](README.assets/image-20211026111235003.png) ###### 2.2.2.5.1 c.lw ###### 2.2.2.5.2 c.ld(RV64/128扩展,此处不实现) ###### 2.2.2.5.3 c.lq(RV64/128扩展,此处不实现) ###### 2.2.2.5.4 c.flw ###### 2.2.2.5.5 c.fld ##### 2.2.2.6 CS格式指令 ![image-20211026103029375](README.assets/image-20211026103029375.png) ![image-20211026111323887](README.assets/image-20211026111323887.png) ###### 2.2.2.6.1 c.sw ###### 2.2.2.6.2 c.sd(RV64/128扩展,此处不实现) ###### 2.2.2.6.3 c.sq(RV128扩展,此处不实现) ###### 2.2.2.6.4 c.fsw ###### 2.2.2.6.5 c.fsd ##### 2.2.2.7 CA格式指令 ![image-20211026110101079](README.assets/image-20211026110101079.png) ![image-20211026111909470](README.assets/image-20211026111909470.png) ###### 2.2.2.7.1 c.and ###### 2.2.2.7.2 c.or ###### 2.2.2.7.3 c.xor ###### 2.2.2.7.4 c.sub ###### 2.2.2.7.5 c.addw(RV64/128扩展,此处不实现) ###### 2.2.2.7.6 c.subw(RV64/128扩展,此处不实现) ##### 2.2.2.8 CB格式指令 ![image-20211026103300760](README.assets/image-20211026103300760.png) ![image-20211026111957810](README.assets/image-20211026111957810.png) ###### 2.2.2.8.1 c.beqz ###### 2.2.2.8.2 c.bnez ![image-20211026105820325](README.assets/image-20211026105820325.png) ![image-20211026111748725](README.assets/image-20211026111748725.png) ###### 2.2.2.8.3 c.srli ###### 2.2.2.8.4 c.srai ![image-20211026105911242](README.assets/image-20211026105911242.png) ![image-20211026111841698](README.assets/image-20211026111841698.png) ###### 2.2.2.8.5 c.andi ##### 2.2.2.9 CJ格式指令 ![image-20211026103147306](README.assets/image-20211026103147306.png) ![image-20211026111933173](README.assets/image-20211026111933173.png) ![image-20211026111503951](README.assets/image-20211026111503951.png) ###### 2.2.2.9.1 c.j ###### 2.2.2.9.2 c.jal ## 3 实现 ### 3.1 思路 - 实现RC32V指令编译为机器码(16位) - 创建Constants模块用于寄存器到编号的映射及指令的识别 - 在main函数中实现试验集代码的执行 ### 3.2 源代码说明 #### 3.2.1 实现RV32C指令集的编译 ##### 3.2.1.1 Constants模块 - 存储RV32C指令集opcode 和funct字段 ```json # 存储指令对应的二进制代码 CR_instruction = {'c.add': ['10', '1001'], 'c.mv': ['10', '1000'], 'c.jr': ['10', '1000'], 'c.jalr': ['10', '1001'] } CI_instruction = {'c.lwsp': ['10', '010'], 'c.flwsp': ['10', '011'], 'c.fldsp': ['10', '001'], 'c.addi': ['01', '000'], 'c.addi16sp': ['01', '011'], 'c.li': ['01', '010'], 'c.lui': ['01', '011'], 'c.slli': ['10', '000'], 'c.nop': ['01', '000'], 'c.ebreak': ['10', '100'] } CSS_instruction = {'c.swsp': ['10', '110'], 'c.fswsp': ['10', '111'], 'c.fsdsp': ['10', '101'] } CIW_instruction = {'c.addi4spn': ['00', '000']} CL_instruction = {'c.lw': ['00', '010'], 'c.flw': ['00', '011'], 'c.fld': ['00', '001'] } CS_instruction = {'c.sw': ['00', '110'], 'c.fsw': ['00', '111'], 'c.fsd': ['00', '101'] } CA_instruction = {'c.and': ['01', '11', '100011'], 'c.or': ['01', '10', '100011'], 'c.xor': ['01', '01', '100011'], 'c.sub': ['01', '00', '100011'] } CB_instruction = {'c.beqz': ['01', '110'], 'c.bnez': ['01', '111'], 'c.srli': ['01', '00', '100'], 'c.srai': ['01', '01', '100'], 'c.andi': ['01', '10', '100'] } CJ_instruction = {'c.j': ['01', '101'], 'c.jal': ['01', '001'] } ``` - 存储opcode、funct3字段到指令的映射关系 - ![image-20211026101530594](image/image-20211026101530594.png) ```python instructionFormatChoice = {'CR_instruction': CR_instruction, 'CI_instruction': CI_instruction, 'CSS_instruction': CSS_instruction, 'CIW_instruction': CIW_instruction, 'CL_instruction': CL_instruction, 'CS_instruction': CS_instruction, 'CA_instruction': CA_instruction, 'CB_instruction': CB_instruction, 'CJ_instruction': CJ_instruction} instructionMapping = {'00': {}, '01': {}, '10': {}, '11': {}} def mappingInstruction(): for k, v in instructionFormatChoice.items(): for k_instruction, v_instruction in v.items(): if v_instruction[0] in instructionMapping.keys(): if len(v_instruction[-1]) != 3: if v_instruction[-1][:3] in instructionMapping[v_instruction[0]].keys(): instructionMapping[v_instruction[0]][v_instruction[-1][:3]].append(k_instruction) else: instructionMapping[v_instruction[0]][v_instruction[-1][:3]] = [] instructionMapping[v_instruction[0]][v_instruction[-1][:3]].append(k_instruction) else: if v_instruction[-1] in instructionMapping[v_instruction[0]].keys(): instructionMapping[v_instruction[0]][v_instruction[-1]].append(k_instruction) else: instructionMapping[v_instruction[0]][v_instruction[-1]] = [] instructionMapping[v_instruction[0]][v_instruction[-1]].append(k_instruction) return instructionMapping instructionMapping = mappingInstruction() ``` - 实现寄存器名到寄存器编号、寄存器编号到寄存器名的映射 ```python """ 字典key, value值互换函数 """ def reverse_dict(d): reverse_d = {} for k, v in d.items(): if isinstance(v, list): for temp in v: reverse_d[temp] = k else: reverse_d[v] = k return reverse_d """ 存储寄存器号到寄存器ABI名的映射 """ index2RegABIName = { 0: "zero", # 0 1: "ra", 2: "sp", 3: "gp", 4: "tp", 5: "t0", 6: "t1", 7: "t2", 8: ["s0", "fp"], 9: "s1", 10: "a0", 11: "a1", 12: "a2", 13: "a3", 14: "a4", 15: "a5", 16: "a6", 17: "a7", 18: "s2", 19: "s3", 20: "s4", 21: "s5", 22: "s6", 23: "s7", 24: "s8", 25: "s9", 26: "s10", 27: "s11", 28: "t3", 29: "t4", 30: "t5", 31: "t6", 32: "t7", } """ 存储寄存器号到寄存器名的映射 """ index2RegName = { 0: "x0", 1: "x1", 2: "x2", 3: "x3", 4: "x4", 5: "x5", 6: "x6", 7: "x7", 8: "x8", 9: "x9", 10: "x10", 11: "x11", 12: "x12", 13: "x13", 14: "x14", 15: "x15", 16: "x16", 17: "x17", 18: "x18", 19: "x19", 20: "x20", 21: "x21", 22: "x22", 23: "x23", 24: "x24", 25: "x25", 26: "x26", 27: "x27", 28: "x28", 29: "x29", 30: "x30", 31: "x31", 32: "x32", } """ 存储名到寄存器号的映射 """ regABIName2Index = reverse_dict(index2RegABIName) regName2Index = reverse_dict(index2RegName) ``` - 实现指令到二进制机器码的映射 - CR格式 ```python def CR_type_Format(data_list): """ CR格式指令转换位二进制代码,data_list中为转换好的字段值 :param data_list: :return: """ return "{:04b}{:05b}{:05b}{:02b}".format(data_list[3], data_list[2], data_list[1], data_list[0]) def CR_convertInstruction2Binary(instruction): """ 用于实现CR格式指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CR_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) if k == 'c.jr' or k == 'c.jalr': rs1 = findRegId(instruction[1]) rs2 = 0 op = int(instruction[0], 2) func4 = int(instruction[2], 2) instruction = [op, rs2, rs1, func4] pass else: # print(instruction) rd = findRegId(instruction[1]) rs2 = findRegId(instruction[2]) op = int(instruction[0], 2) func4 = int(instruction[3], 2) instruction = [op, rs2, rd, func4] return CR_type_Format(instruction) ``` - CI格式 ```python def CI_type_Format(data_list): return "{:03b}{:01b}{:05b}{:05b}{:02b}".format(data_list[4], data_list[3], data_list[2], data_list[1], data_list[0]) def CI_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CI_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) if k == 'c.addi16sp': rd = 2 imm = "{:06b}".format(int(instruction[1])) imm_high = int(imm[0], 2) imm_low = int(imm[1:], 2) op = int(instruction[0], 2) func3 = int(instruction[2],2) instruction = [op, imm_low, rd, imm_high, func3] elif k == 'c.nop': rd = 0 imm = "{:06b}".format(int(instruction[1])) imm_high = int(imm[0], 2) imm_low = int(imm[1:], 2) op = int(instruction[0], 2) func3 = int(instruction[2], 2) instruction = [op, imm_low, rd, imm_high, func3] print(instruction) elif k == 'c.ebreak': rd = 0 imm_low = 0 imm_high = 0 op = int(instruction[0], 2) func3 = int(instruction[1], 2) instruction = [op, imm_low, rd, imm_high, func3] print(instruction) else: instruction[1] = findRegId(instruction[1]) op = int(instruction[0], 2) imm = "{:06b}".format(int(instruction[2])) imm_high = int(imm[0], 2) imm_low = int(imm[1:], 2) rd = instruction[1] func3 = int(instruction[3], 2) instruction = [op, imm_low, rd, imm_high, func3] print(instruction) return CI_type_Format(instruction) ``` - CSS格式 ```python def CSS_type_Format(data_list): return "{:03b}{:06b}{:05b}{:02b}".format(data_list[3], data_list[2], data_list[1], data_list[0]) def CSS_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CSS_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) rs2 = findRegId(instruction[1]) op = int(instruction[0], 2) imm = "{:06b}".format(int(instruction[2])) imm = int(imm, 2) func3 = int(instruction[3], 2) print(instruction) instruction = [op, rs2, imm, func3] return CSS_type_Format(instruction) ``` - CIW格式 ```python def CIW_type_Format(data_list): return "{:03b}{:08b}{:03b}{:02b}".format(data_list[3], data_list[2], data_list[1], data_list[0]) def CIW_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: 分割好的指令,如:['c.addi4spn', '1', '32'] :return: instruction:转换为二进制代码的指令,如:['00', '1', '32', '000'] """ for k, v in CIW_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) op = int(instruction[0], 2) func3 = int(instruction[3], 2) rd_1 = int(instruction[1]) imm = "{:08b}".format(int(instruction[2])) imm = int(imm, 2) instruction = [op, rd_1, imm, func3] print(instruction) return CIW_type_Format(instruction) ``` - CL格式 ```python def CL_type_Format(data_list): return "{:03b}{:03b}{:03b}{:02b}{:03b}{:02b}".format(data_list[5], data_list[4], data_list[3], data_list[2], data_list[1], data_list[0]) def CL_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction:['c.fld', '2', '32', '3'] :return: instruction:00010100011000001 """ for k, v in CL_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) # instruction_change = list(map(int, instruction[1:-1])) op = int(instruction[0], 2) rd_1 = int(instruction[1]) rs_1 = int(instruction[2]) func = int(instruction[4], 2) imm = "{:05b}".format(int(instruction[3])) imm_high = int(imm[:2], 2) imm_low = int(imm[2:], 2) instruction = [op, rd_1, imm_high, rs_1, imm_low, func] print(instruction) return CL_type_Format(instruction) ``` - CS格式 ```python def CS_type_Format(data_list): return "{:03b}{:03b}{:03b}{:02b}{:03b}{:02b}".format(data_list[5], data_list[4], data_list[3], data_list[2], data_list[1], data_list[0]) def CS_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CS_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) rs_2 = int(instruction[1]) rs_1 = int(instruction[2]) op = int(instruction[0], 2) func3 = int(instruction[4], 2) imm = "{:05b}".format(int(instruction[3])) imm_high = int(imm[:2], 2) imm_low = int(imm[2:], 2) instruction = [op, rs_2, imm_high, rs_1, imm_low, func3] print(instruction) return CS_type_Format(instruction) ``` - CA格式 ```python def CA_type_Format(data_list): return "{:06b}{:03b}{:02b}{:03b}{:02b}".format(data_list[4], data_list[3], data_list[2], data_list[1], data_list[0]) def CA_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CA_instruction.items(): if k == instruction[0]: # instruction[0] = v[0] # instruction.append(v[1]) op = int(v[0], 2) func2 = int(v[1], 2) func6 = int(v[2], 2) rd_1 = int(instruction[1]) rs2_1 = int(instruction[2]) instruction = [op, rs2_1, func2, rd_1, func6] print(instruction) return CA_type_Format(instruction) ``` - CB格式 ```python def CB_type_Format(data_list): return "{:03b}{:03b}{:03b}{:05b}{:02b}".format(data_list[4], data_list[3], data_list[2], data_list[1], data_list[0]) def CB_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CB_instruction.items(): if k == instruction[0]: # instruction[0] = v[0] # instruction.append(v[1]) if k == 'c.srli' or k == 'c.srai' or k == 'c.andi': op = int(v[0], 2) func2 = v[1] func3 = int(v[2], 2) rd_1 = int(instruction[1]) imm = "{:05b}".format(int(instruction[2])) imm_high = imm[0] imm_low = int(imm[1:], 2) instruction = [op, imm_low, rd_1, int(imm_high + func2, 2), func3] print(instruction) else: op = int(v[0], 2) func3 = int(v[1], 2) rs1_1 = int(instruction[1]) imm = "{:08b}".format(int(instruction[2])) imm_high = int(imm[:5], 2) imm_low = int(imm[5:], 2) instruction = [op, imm_high, rs1_1, imm_low, func3] print(instruction) return CB_type_Format(instruction) ``` - CJ格式 ```python def CJ_type_Format(data_list): return "{:03b}{:011b}{:02b}".format(data_list[2], data_list[1], data_list[0]) def CJ_convertInstruction2Binary(instruction): """ 用于实现指令到二进制代码的转换 :param instruction: :return: instruction: """ for k, v in CJ_instruction.items(): if k == instruction[0]: instruction[0] = v[0] instruction.append(v[1]) print(instruction) op = int(instruction[0], 2) imm = int(instruction[1]) func3 = int(instruction[2], 2) instruction = [op, imm, func3] print(instruction) return CJ_type_Format(instruction) ``` ##### 3.2.1.2 Assembler模块 - 实现从Problem.txt文件中读取指令,编译成32位代码后存储到ProblemBinary.txt文件中 ```python import Constants def assembler(instruction): """ 对初步分割的指令进行编译 :param instruction: 分割好的指令,如:['c.addi4spn', '1', '32'] :return: instructionConverted:转换为二进制代码的指令,如:0000100100000000 """ judgeInstructionFormat = Constants.confirmInstructionFormat(instruction[0]) instructionConverted = [] func = Constants.switch.get(judgeInstructionFormat) if func is not None: instructionConverted = func(instruction) return instructionConverted f = open("./ProgramBinary.txt", "w") for instruction in open('./Program.txt', "r"): instructionSplit = instruction.strip().replace(",", " ").replace("(", " ").replace(")", " ").strip().split(" ") print(instructionSplit) instructionAssembler = assembler(instructionSplit) print(instructionAssembler) f.write(instructionAssembler + "\n") pass f.close() ``` #### 3.2.2 试验代码集 - Problem.txt文件 ```python c.srli 3,16 c.bnez 4,128 c.and 5,6 c.sw 2,3,16 c.swsp x7,16 c.jalr x10 c.jr x5 c.mv x3,x4 c.add x3,x4 c.nop 31 c.ebreak c.addi16sp 32 c.lwsp x6,32 c.addi x1,32 c.li x2,32 c.lui x3,32 c.addi4spn 1,32 c.lw 2,4,31 c.jal 32 ``` - ProblemBinary.txt文件 ```python 1001000110000001 1110001001000001 1000111011111001 1100000111001000 1100100000011110 1001010100000010 1000001010000010 1000000110010010 1001000110010010 0000000001111101 1000000000000010 0111000100000001 0101001100000010 0001000010000001 0101000100000001 0111000110000001 0000010000000100 0101111001101000 0010000010000001 ``` #### 3.2.3 主体函数(main) - 为程序框架,实现从ProblemBinary.txt文件中读取指令二进制代码,然后识别执行 ```python import Assembler import Constants import instructionRun RegisterSize = 33 MemorySize = 256 registers = [] # 为32个寄存器组,定义为全局变量 pc = 0 memory_cache = {} # 输出语句染色方法,放置此处方便使用 class Bcolors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m' def printSystemStatus(register_list): """ 打印当前系统状态 :param register_list: :return: """ print(f"{Bcolors.WARNING}$pc:{pc}{Bcolors.ENDC}") k = enumerate(register_list) for index, registerValue in enumerate(register_list): if isinstance(Constants.index2RegABIName[index], list): print(f"{Bcolors.WARNING}{Constants.index2RegName[index] + '/' + '/'.join(Constants.index2RegABIName[index]):8}:{registerValue}{Bcolors.ENDC}", end="\t") else: print(f"{Bcolors.WARNING}{Constants.index2RegName[index] + '/' + Constants.index2RegABIName[index]:8}:{registerValue}{Bcolors.ENDC}", end="\t") if (index + 1) % 8 == 0: print() print() for index in range(0, 8): print('{:032b}'.format(memory_cache[str(index)]), end='\t') if (index + 1) % 64 == 0: print() print() pass def initialization(): """ 初始化程序运行(系统运行)的初始状态,一般为PC、段寄存器等赋初值,此处简化操作,令PC=0,S=0,寄存器均为32位 :return: """ for i in range(0, RegisterSize): registers.append(0b00000000000000000000000000000000) for i in range(0, MemorySize): memory_cache[f"{i}"] = 1 pass def clear(): """ 清空寄存器和存储 :return: """ for i in range(0, RegisterSize): registers[i] = 0 for i in range(0, MemorySize): memory_cache[f"{i}"] = 1 pass if __name__ == '__main__': initialization() # 初始化寄存器组 command = '' for instruction in open("ProgramBinary.txt", "r"): instruction = instruction.strip() clear() func = instructionRun.switch[instruction[-2:]][instruction[:3]] instruction, registers, memory_cache, pc, command = func(instruction, registers, memory_cache, pc, command) print(command) printSystemStatus(registers) ``` #### 3.2.4 指令功能实现模块(instructionRun) - 实现RV32C指令的功能 ```python # switch_test = {'00': # {'000': ['c.addi4spn'], # '010': ['c.lw'], # '011': ['c.flw'], # '001': ['c.fld'], # '110': ['c.sw'], # '111': ['c.fsw'], # '101': ['c.fsd'] # }, # '01': # {'000': ['c.addi', 'c.nop'], # '011': ['c.addi16sp', 'c.lui'], # '010': ['c.li'], # '100': ['c.and', 'c.or', 'c.xor', 'c.sub', 'c.srli', 'c.srai', 'c.andi'], # '110': ['c.beqz'], # '111': ['c.bnez'], # '101': ['c.j'], # '001': ['c.jal'] # }, # '10': # {'100': ['c.add', 'c.mv', 'c.jr', 'c.jalr', 'c.ebreak'], # '010': ['c.lwsp'], # '011': ['c.flwsp'], # '001': ['c.fldsp'], # '000': ['c.slli'], # '110': ['c.swsp'], # '111': ['c.fswsp'], # '101': ['c.fsdsp'] # }, # '11': # {} # } def c_addi4spn(instruction, registers, memory, pc, command): # "{:03b}{:08b}{:03b}{:02b}".format(data_list[3], data_list[2], data_list[1], data_list[0]) func3 = instruction[0:3] imm = int(instruction[3:11], 2) rd_1 = int(instruction[11:14], 2) op = instruction[14:] rd = rd_1 + 8 command = 'c.addi4spn' registers[rd] = imm*4 + registers[2] return instruction, registers, memory, pc, command def c_lw(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_low = instruction[3:6] rs1_1 = instruction[6:9] imm_high = instruction[9:11] rd_1 = instruction[11:14] op = instruction[14:] rs1 = int(rs1_1, 2) + 8 rd = int(rd_1, 2) + 8 imm = imm_high + imm_low imm = int(imm, 2) command = 'c.lw' registers[rd] = memory[str(registers[rs1] + imm)] return instruction, registers, memory, pc, command def c_flw(instruction, registers, memory, pc, command): pass def c_fld(instruction, registers, memory, pc, command): pass def c_sw(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_low = instruction[3:6] rs1_1 = int(instruction[6:9], 2) imm_high = instruction[9:11] rs2_1 = int(instruction[11:14], 2) op = instruction[14:] imm = imm_high + imm_low imm = int(imm, 2) rs1 = rs1_1 + 8 rs2 = rs2_1 + 8 command = 'c.sw' memory[str(registers[rs1] + imm)] = registers[rs2] return instruction, registers, memory, pc, command def c_fsw(instruction, registers, memory, pc, command): pass def c_fsd(instruction, registers, memory, pc, command): pass def c_addi_nop(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_high = instruction[3] rd = instruction[4:9] imm_low = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low rd = int(rd, 2) imm = int(imm, 2) if rd == 0: # c.nop command = 'c.nop' else: # c.addi command = 'c.addi' registers[rd] = registers[rd] + imm return instruction, registers, memory, pc, command def c_addi16sp_lui(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_high = instruction[3] rd = instruction[4:9] imm_low = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low rd = int(rd, 2) imm = int(imm, 2) if rd == 2: # c.addi16sp command = 'c.addi16sp' registers[2] = registers[2] + imm * 16 else: # c.lui command = 'c.lui' registers[rd] = imm << 12 return instruction, registers, memory, pc, command def c_li(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_high = instruction[3] rd = instruction[4:9] imm_low = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low rd = int(rd, 2) imm = int(imm, 2) command = 'c.li' registers[rd] = imm return instruction, registers, memory, pc, command def c_and_or_xor_sub_srli_srai_andi(instruction, registers, memory, pc, command): func6 = instruction[0:6] if func6 == '100011': # c.sub, c.xor, c.or, c.and rd_1 = int(instruction[6:9], 2) func2_alu = instruction[9:11] rs2_1 = int(instruction[11:14], 2) op = instruction[14:] rd_alu = rd_1 + 8 rs_alu = rs2_1 + 8 if func2_alu == '00': # c.sub command = 'c.sub' registers[rd_alu] = registers[rd_alu] - registers[rs_alu] elif func2_alu == '01': # c.xor command = 'c.xor' registers[rd_alu] = registers[rd_alu] ^ registers[rs_alu] elif func2_alu == '10': # c.or command = 'c.or' registers[rd_alu] = registers[rd_alu] | registers[rs_alu] elif func2_alu == '11': # c.and command = 'c.and' registers[rd_alu] = registers[rd_alu] & registers[rs_alu] else: # c.srli, c.srai, c.andi func3 = instruction[0:3] imm_high = instruction[3] func2 = instruction[4:6] rd_1 = int(instruction[6:9], 2) rd = rd_1 + 8 imm_low = instruction[9:14] imm = imm_high + imm_low imm = int(imm, 2) op = instruction[14:] if func2 == '00': # c.srli command = 'c.srli' registers[rd] = registers[rd] >> imm elif func2 == '01': # c.srai command = 'c.srai' registers[rd] = registers[rd] << imm elif func2 == '10': # c.andi command = 'c.andi' registers[rd] = registers[rd] & imm return instruction, registers, memory, pc, command def c_beqz(instruction, registers, memory, pc, command): func3 = instruction[0:3] imm_low = instruction[3:6] rs_1 = int(instruction[6:9], 2) imm_high = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low imm = int(imm, 2) rs = rs_1 + 8 command = 'c.beqz' if registers[rs] == 0: pc = pc + imm return instruction, registers, memory, pc, command def c_bnez(instruction, registers, memory, pc, command): func3 = instruction[0:3] imm_low = instruction[3:6] rs_1 = int(instruction[6:9], 2) imm_high = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low imm = int(imm, 2) rs = rs_1 + 8 command = 'c.bnez' if registers[rs] != 0: pc = pc + imm return instruction, registers, memory, pc, command def c_j(instruction, registers, memory, pc, command): pass def c_jal(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm = instruction[3:14] op = instruction[14:] imm = int(imm, 2) registers[1] = pc + 2 pc = imm command = 'c.jal' return instruction, registers, memory, pc, command def c_add_mv_jr_jalr_ebreak(instruction, registers, memory, pc, command): funct4 = instruction[0:4] rd = instruction[4:9] rs2 = instruction[9:14] op = instruction[14:] rd = int(rd, 2) rs2 = int(rs2, 2) if rs2 == 0 & rd == 0: command = 'c.ebreak' return instruction, registers, memory, pc, command if rs2 == 0: # c.jr or c.jalr if funct4 == '1000': # c.jr command = 'c.jr' pc = registers[rd] elif funct4 == '1001': # c.jalr command = 'c.jalr' registers[1] = pc + 2 pc = registers[rd] else: # c.mc or c.add if funct4 == '1000': # c.mv command = 'c.mv' registers[rd] = registers[rs2] elif funct4 == '1001': # c.add command = 'c.add' registers[rd] = registers[rs2] + registers[rd] return instruction, registers, memory, pc, command def c_lwsp(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm_high = instruction[3] rd = instruction[4:9] imm_low = instruction[9:14] op = instruction[14:] imm = imm_high + imm_low rd = int(rd, 2) imm = int(imm, 2) command = 'c.lwsp' registers[rd] = memory[str(registers[2] + imm)] return instruction, registers, memory, pc, command def c_flwsp(instruction, registers, memory, pc, command): pass def c_fldsp(instruction, registers, memory, pc, command): pass def c_slli(instruction, registers, memory, pc, command): pass def c_swsp(instruction, registers, memory, pc, command): funct3 = instruction[0:3] imm = instruction[3:9] rs2 = instruction[9:14] op = instruction[14:] rs2 = int(rs2, 2) imm = int(imm, 2) command = 'c.swsp' memory[str(registers[2] + imm)] = registers[rs2] return instruction, registers, memory, pc, command def c_fswsp(instruction, registers, memory, pc, command): pass def c_fsdsp(instruction, registers, memory, pc, command): pass switch = {'00': {'000': c_addi4spn, '010': c_lw, '011': c_flw, '001': c_fld, '110': c_sw, '111': c_fsw, '101': c_fsd}, '01': {'000': c_addi_nop, '011': c_addi16sp_lui, '010': c_li, '100': c_and_or_xor_sub_srli_srai_andi, '110': c_beqz, '111': c_bnez, '101': c_j, '001': c_jal}, '10': {'100': c_add_mv_jr_jalr_ebreak, '010': c_lwsp, '011': c_flwsp, '001': c_fldsp, '000': c_slli, '110': c_swsp, '111': c_fswsp, '101': c_fsdsp}, '11': {} } ```