319 lines
12 KiB
Python
319 lines
12 KiB
Python
|
|
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,
|
|||
|
|
}
|