Chip_Case_Generator/4ch-Z_Generator/make_inst.py

319 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
class make_inst(object):
def parse_instruction(self, instruction, labels, pc):
# 去掉所有逗号
instruction = instruction.replace(',', ' ')
parts = instruction.split()
opcode = parts[0].upper().strip()
if opcode.endswith(':'):
# 处理标签
label_name = opcode[:-1]
labels[label_name] = pc
return None
operands = [op.strip() for op in parts[1:]]
def parse_immediate(imm_str):
try:
if imm_str.startswith('0x') or imm_str.startswith('0X'):
return int(imm_str, 16)
elif imm_str.startswith('0b') or imm_str.startswith('0B'):
return int(imm_str, 2)
elif imm_str.startswith('-0x') or imm_str.startswith('-0X'):
return -int(imm_str[1:], 16)
elif imm_str.startswith('-0b') or imm_str.startswith('-0B'):
return -int(imm_str[1:], 2)
elif imm_str.startswith('-'):
return -int(imm_str[1:], 10)
else:
return int(imm_str, 10)
except ValueError:
raise ValueError(f"Invalid immediate value: {imm_str}")
if opcode == 'LUI':
rd, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
return format((self.opcode_map[opcode]) | (imm & 0xFFFFF) << 12 | (rd << 7), '032b')
elif opcode == 'AUIPC':
rd, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
return format((self.opcode_map[opcode]) | (imm & 0xFFFFF) << 12 | (rd << 7), '032b')
elif opcode == 'JAL':
rd, label_or_imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
if label_or_imm.lstrip('-').isdigit() or label_or_imm.startswith(('0x', '0X', '0b', '0B', '-0x', '-0X', '-0b', '-0B')):
imm = parse_immediate(label_or_imm)
else:
imm = labels.get(label_or_imm.upper().strip(), 0) - pc
imm_bits = (((imm >> 20) & 0x1) << 19) | (((imm >> 1) & 0x3FF) << 9) | (((imm >> 11) & 0x1) << 8) | ((imm >> 12) & 0xFF)
return format((self.opcode_map[opcode]) | (imm_bits) << 12 | (rd << 7), '032b')
elif opcode == 'JALR':
rd = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (imm & 0xFFF) << 20 | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['BEQ', 'BNE', 'BLT', 'BGE', 'BLTU', 'BGEU']:
rs1, rs2, label_or_imm = operands
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
if label_or_imm.lstrip('-').isdigit() or label_or_imm.startswith(('0x', '0X', '0b', '0B', '-0x', '-0X', '-0b', '-0B')):
imm = parse_immediate(label_or_imm)
else:
imm = labels.get(label_or_imm.upper().strip(), 0) - pc
imm_high_bits = (((imm >> 12) & 0x1) << 6) | (((imm >> 5 ) & 0x3F))
imm_low_bits = (((imm >> 1 ) & 0xF) << 1) | (((imm >> 11) & 0x1 ))
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (imm_high_bits << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (imm_low_bits << 7), '032b')
elif opcode in ['LB', 'LH', 'LW', 'LBU', 'LHU']:
rd = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['SB', 'SH', 'SW']:
rs2 = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (((imm >> 5) & 0x7F) << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | ((imm & 0x1F) << 7), '032b')
elif opcode in ['ADDI', 'SLTI', 'SLTIU', 'XORI', 'ORI', 'ANDI']:
rd, rs1, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['SLLI', 'SRLI', 'SRAI']:
rd, rs1, shamt = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
shamt = parse_immediate(shamt)
funct3 = self.opcode_funct3_map[opcode]
funct7 = self.opcode_funct7_map[opcode]
return format((self.opcode_map[opcode]) | (funct7 << 25) | ((shamt & 0x1F) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['ADD', 'SUB', 'SLL', 'SLT', 'SLTU', 'XOR', 'SRL', 'SRA', 'OR', 'AND']:
rd, rs1, rs2 = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
funct3 = self.opcode_funct3_map[opcode]
funct7 = self.opcode_funct7_map[opcode]
return format((self.opcode_map[opcode]) | (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['WAIT', 'SEND', 'SENDC']:
rd, rs1, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['EXIT']:
return format((self.opcode_map[opcode]), '032b')
elif opcode in ['EXIT_IR']:
return '00000000000000000001000000101011'
else:
raise ValueError(f"Unsupported opcode: {opcode}")
def write(self, instructions, file_name, exaddr = 1, chip_id = 0, channel_id = 0, pc_start = 0, ard_flag = 0, show = False):
if instructions == "":
pass
else:
labels = {}
binary_instructions = []
# 将整段汇编代码拆成多条指令组成的字符串数组
inst_list = instructions.split('\n')
instructions = []
for this_inst in inst_list:
this_inst = this_inst.split('#')
if this_inst[0].strip() != '':
instructions.append(this_inst[0].strip())
# 第一遍扫描:记录标签位置
pc = pc_start
for instr in instructions:
binary = self.parse_instruction(instr, labels, pc)
if binary is not None:
binary_instructions.append(binary)
pc += 4
else:
# 如果是标签不增加pc
pass
# 第二遍扫描:生成最终的二进制代码
pc = pc_start
final_binary_instructions = []
for instr in instructions:
binary = self.parse_instruction(instr, labels, pc)
if binary is not None:
final_binary_instructions.append(binary)
if show:
print(f"{instr}: {binary}")
pc += 4
else:
# 如果是标签不增加pc
pass
with open(file_name, "a") as f:
base_addr = 0x010_0000 + pc_start + channel_id * 0x060_0000
length = np.size(final_binary_instructions)
f.write(f"{((ard_flag << 30) | (chip_id << 25) | (base_addr)):08x}\n")
f.write(f"{((exaddr << 20) | (length<<2)):08x}\n")
for binary_instr in final_binary_instructions:
f.write(f"{int(binary_instr,2):08x}\n")
f.write("\n")
return final_binary_instructions
opcode_map = {
'LUI': 0x37,
'AUIPC': 0x17,
'JAL': 0x6F,
'JALR': 0x67,
'BEQ': 0x63,
'BNE': 0x63,
'BLT': 0x63,
'BGE': 0x63,
'BLTU': 0x63,
'BGEU': 0x63,
'LB': 0x03,
'LH': 0x03,
'LW': 0x03,
'LBU': 0x03,
'LHU': 0x03,
'SB': 0x23,
'SH': 0x23,
'SW': 0x23,
'ADDI': 0x13,
'SLTI': 0x13,
'SLTIU': 0x13,
'XORI': 0x13,
'ORI': 0x13,
'ANDI': 0x13,
'SLLI': 0x13,
'SRLI': 0x13,
'SRAI': 0x13,
'ADD': 0x33,
'SUB': 0x33,
'SLL': 0x33,
'SLT': 0x33,
'SLTU': 0x33,
'XOR': 0x33,
'SRL': 0x33,
'SRA': 0x33,
'OR': 0x33,
'AND': 0x33,
'WAIT': 0x0B,
'SEND': 0x0B,
'SENDC': 0x0B,
'EXIT': 0x2B,
}
opcode_funct3_map = {
'JALR': 0x0,
'BEQ': 0x0,
'BNE': 0x1,
'BLT': 0x4,
'BGE': 0x5,
'BLTU': 0x6,
'BGEU': 0x7,
'LB': 0x0,
'LH': 0x1,
'LW': 0x2,
'LBU': 0x4,
'LHU': 0x5,
'SB': 0x0,
'SH': 0x1,
'SW': 0x2,
'ADDI': 0x0,
'SLTI': 0x2,
'SLTIU': 0x3,
'XORI': 0x4,
'ORI': 0x6,
'ANDI': 0x7,
'SLLI': 0x1,
'SRLI': 0x5,
'SRAI': 0x5,
'ADD': 0x0,
'SUB': 0x0,
'SLL': 0x1,
'SLT': 0x2,
'SLTU': 0x3,
'XOR': 0x4,
'SRL': 0x5,
'SRA': 0x5,
'OR': 0x6,
'AND': 0x7,
'WAIT': 0x0,
'SEND': 0x2,
'SENDC': 0x3,
'EXIT': 0x0,
}
opcode_funct7_map = {
'JALR': 0x00,
'BEQ': 0x00,
'BNE': 0x00,
'BLT': 0x00,
'BGE': 0x00,
'BLTU': 0x00,
'BGEU': 0x00,
'LB': 0x00,
'LH': 0x00,
'LW': 0x00,
'LBU': 0x00,
'LHU': 0x00,
'SB': 0x00,
'SH': 0x00,
'SW': 0x00,
'ADDI': 0x00,
'SLTI': 0x00,
'SLTIU': 0x00,
'XORI': 0x00,
'ORI': 0x00,
'ANDI': 0x00,
'SLLI': 0x00,
'SRLI': 0x00,
'SRAI': 0x20,
'ADD': 0x00,
'SUB': 0x20,
'SLL': 0x00,
'SLT': 0x00,
'SLTU': 0x00,
'XOR': 0x00,
'SRL': 0x00,
'SRA': 0x20,
'OR': 0x00,
'AND': 0x00,
'WAIT': 0x00,
'SEND': 0x00,
'SENDC': 0x00,
'EXIT': 0x00,
}