# # ecdsa_microcode_parser.py # # Author: Pavel Shatov # # Copyright 2018 NORDUnet A/S # Copyright 2021 The Commons Conservancy Cryptech Project # SPDX-License-Identifier: BSD-3-Clause # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Imports import re import sys from enum import Enum # Source File C_FILES = [ "ecdsa_fpga_curve_microcode.cpp", "ecdsa_fpga_microcode.cpp"] class MICROCODE_PARSER: # enumerate microcode pieces class MICROCODE_PIECE_ENUM(Enum): NONE = -1 PREPARE = 0 CYCLE_DOUBLE_R0 = 1 CYCLE_DOUBLE_R1 = 2 CYCLE_ADD = 3 CYCLE_ADD_R0_AT_INFINITY = 4 CYCLE_ADD_R1_AT_INFINITY = 5 CYCLE_ADD_REGULAR = 6 CYCLE_K0 = 7 CYCLE_K1 = 8 CONVERT = 9 INVERT_P256 = 10 INVERT_P384 = 11 # magic pair of begin/end markers MARKER_BEGIN_MICROCODE = "BEGIN_MICROCODE:" MARKER_END_MICROCODE = "END_MICROCODE" # names of banks MICROCODE_C_NAME_BANK_LO = "BANK_LO" MICROCODE_C_NAME_BANK_HI = "BANK_HI" # micro-operation names MICROCODE_C_NAME_UOP_CMPZ = "uop_cmpz" MICROCODE_C_NAME_UOP_MOVE = "uop_move" MICROCODE_C_NAME_UOP_CALC = "uop_calc" MICROCODE_C_NAME_UOP_CYCLE = "uop_cycle" MICROCODE_C_NAME_UOP_REPEAT = "uop_repeat" MICROCODE_C_NAME_UOP_CALC_EVEN = "uop_calc_if_even" MICROCODE_C_NAME_UOP_CALC_ODD = "uop_calc_if_odd" # calculate micro-operations MICROCODE_C_NAME_UOP_MATH_MUL = "MUL" MICROCODE_C_NAME_UOP_MATH_ADD = "ADD" MICROCODE_C_NAME_UOP_MATH_SUB = "SUB" # names of banks in C source MICROCODE_C_NAMES_BANKS = [MICROCODE_C_NAME_BANK_LO, MICROCODE_C_NAME_BANK_HI] # names of operands in C source MICROCODE_C_NAMES_OPERANDS = [ "CONST_ZERO", "CONST_ONE", "CONST_DELTA", "CONST_GX", "CONST_GY", "INVERT_R1", "INVERT_R2", "INVERT_X2", "INVERT_X3", "INVERT_X6", "INVERT_X12", "INVERT_X15", "INVERT_X30", "INVERT_X32", "INVERT_X60", "INVERT_X120", "INVERT_A2", "INVERT_A3", "CYCLE_R0X", "CYCLE_R0Y", "CYCLE_R0Z", "CYCLE_R1X", "CYCLE_R1Y", "CYCLE_R1Z", "CYCLE_SX", "CYCLE_SY", "CYCLE_SZ", "CYCLE_TX", "CYCLE_TY", "CYCLE_TZ", "CYCLE_T1", "CYCLE_T2", "CYCLE_T3", "CYCLE_T4", "CYCLE_T5", "CYCLE_T6", "CYCLE_T7", "CYCLE_T8"] # names of banks in Verilog source MICROCODE_V_NAME_BANKS_DUMMY = "UOP_BANKS_DUMMY" MICROCODE_V_NAMES_BANKS = ["UOP_BANKS_LO2HI", "UOP_BANKS_HI2LO"] # names of operands in Verilog source MICROCODE_V_NAMES_OPERANDS = ["UOP_OPERAND_" + op for op in MICROCODE_C_NAMES_OPERANDS] # names of opcodes in Verilog source MICROCODE_V_NAME_OPCODE_CMPZ = "UOP_OPCODE_CMPZ" MICROCODE_V_NAME_OPCODE_MOVE = "UOP_OPCODE_COPY" MICROCODE_V_NAME_OPCODE_MUL = "UOP_OPCODE_MUL" MICROCODE_V_NAME_OPCODE_ADD = "UOP_OPCODE_ADD" MICROCODE_V_NAME_OPCODE_SUB = "UOP_OPCODE_SUB" MICROCODE_V_NAME_OPCODE_STOP = "UOP_OPCODE_STOP" MICROCODE_V_NAME_OPERAND_DONTCARE = "UOP_OPERAND_DONTCARE" # match group to catch operand names MATCH_GROUP_09AZ = "([0-9A-Z_]+)" # match group to catch bank names MATCH_GROUP_BANK = "(" + MICROCODE_C_NAME_BANK_LO + "|" + MICROCODE_C_NAME_BANK_HI + ")" # match group to catch number of loop iterations MATCH_GROUP_NUMBER = "(\d+)" # match group to catch math instruction MATCH_GROUP_MATH = "(" + MICROCODE_C_NAME_UOP_MATH_MUL + "|" + MICROCODE_C_NAME_UOP_MATH_ADD + "|" + MICROCODE_C_NAME_UOP_MATH_SUB + ")" # match group to catch calculation micro-operation MATCH_GROUP_CALC = "(" + MICROCODE_C_NAME_UOP_CALC + "|" + MICROCODE_C_NAME_UOP_CALC_EVEN + "|" + MICROCODE_C_NAME_UOP_CALC_ODD + ")" # map string microcode piece names to enum values MICROCODE_PIECE_DICT = { "PREPARE": MICROCODE_PIECE_ENUM.PREPARE, "CYCLE_DOUBLE_R0": MICROCODE_PIECE_ENUM.CYCLE_DOUBLE_R0, "CYCLE_DOUBLE_R1": MICROCODE_PIECE_ENUM.CYCLE_DOUBLE_R1, "CYCLE_ADD": MICROCODE_PIECE_ENUM.CYCLE_ADD, "CYCLE_ADD_R0_AT_INFINITY": MICROCODE_PIECE_ENUM.CYCLE_ADD_R0_AT_INFINITY, "CYCLE_ADD_R1_AT_INFINITY": MICROCODE_PIECE_ENUM.CYCLE_ADD_R1_AT_INFINITY, "CYCLE_ADD_REGULAR": MICROCODE_PIECE_ENUM.CYCLE_ADD_REGULAR, "CYCLE_K0": MICROCODE_PIECE_ENUM.CYCLE_K0, "CYCLE_K1": MICROCODE_PIECE_ENUM.CYCLE_K1, "INVERT_P256": MICROCODE_PIECE_ENUM.INVERT_P256, "INVERT_P384": MICROCODE_PIECE_ENUM.INVERT_P384, "CONVERT": MICROCODE_PIECE_ENUM.CONVERT} # map C bank names to Verilog bank names MICROCODE_BANK_DICT = dict(zip(MICROCODE_C_NAMES_BANKS, MICROCODE_V_NAMES_BANKS)) # map C operand names to Verilog operand names MICROCODE_OPERAND_DICT = dict(zip(MICROCODE_C_NAMES_OPERANDS, MICROCODE_V_NAMES_OPERANDS)) # map C calculation names to Verilog opcode names MICROCODE_MATH_DICT = { MICROCODE_C_NAME_UOP_MATH_MUL: MICROCODE_V_NAME_OPCODE_MUL, MICROCODE_C_NAME_UOP_MATH_ADD: MICROCODE_V_NAME_OPCODE_ADD, MICROCODE_C_NAME_UOP_MATH_SUB: MICROCODE_V_NAME_OPCODE_SUB} # microcode format MICROCODE_FORMAT_ADDR = "9'd%03d" MICROCODE_FORMAT_LINE = MICROCODE_FORMAT_ADDR + ": data <= %s;" MICROCODE_FORMAT_OFFSET = "localparam [UOP_ADDR_WIDTH-1:0] %s = " + MICROCODE_FORMAT_ADDR + ";" # pieces of microcode MICROCODE_LINES_PREPARE = [] MICROCODE_LINES_CYCLE_DOUBLE_R0 = [] MICROCODE_LINES_CYCLE_DOUBLE_R1 = [] MICROCODE_LINES_CYCLE_ADD = [] MICROCODE_LINES_CYCLE_ADD_R0_AT_INFINITY = [] MICROCODE_LINES_CYCLE_ADD_R1_AT_INFINITY = [] MICROCODE_LINES_CYCLE_ADD_REGULAR = [] MICROCODE_LINES_CYCLE_K0 = [] MICROCODE_LINES_CYCLE_K1 = [] MICROCODE_LINES_INVERT_P256 = [] MICROCODE_LINES_INVERT_P384 = [] MICROCODE_LINES_CONVERT = [] MICROCODE_LINE_STOP = "{%s, %s, %s, %s, %s}" % ( MICROCODE_V_NAME_OPCODE_STOP, MICROCODE_V_NAME_BANKS_DUMMY, MICROCODE_V_NAME_OPERAND_DONTCARE, MICROCODE_V_NAME_OPERAND_DONTCARE, MICROCODE_V_NAME_OPERAND_DONTCARE) def __init__(self, filenames): self.__filenames = filenames def parse(self): for next_filename in self.__filenames: print("Parsing '%s'..." % (next_filename)) parsing_now = False line_num = 0 with open(next_filename, "r") as c_file: c_lines = c_file.readlines() for next_c_line in c_lines: line_num += 1 self.__line_num = line_num self.__next_c_line = next_c_line.strip() if len(self.__next_c_line) == 0: continue if self.__next_c_line.startswith("//"): continue if not parsing_now: self.__current_piece = self.__try_start_parsing() if self.__current_piece != self.MICROCODE_PIECE_ENUM.NONE: print(" Found piece of microcode: %s" % (str(self.__current_piece))) parsing_now = True else: parsing_now = self.__continue_parsing() def format(self): mode = 0 if len(sys.argv) == 2: if sys.argv[1] == "P256": mode = 1 if sys.argv[1] == "P384": mode = 2 if mode == 0: sys.exit("sys.exit(): Usage: ecdsa_microcode_parser.py !") if len(self.MICROCODE_LINES_PREPARE) == 0: sys.exit("sys.exit(): Empty PREPARE piece!") if len(self.MICROCODE_LINES_CYCLE_DOUBLE_R0) == 0: sys.exit("sys.exit(): Empty CYCLE_DOUBLE_R0 piece!") if len(self.MICROCODE_LINES_CYCLE_DOUBLE_R1) == 0: sys.exit("sys.exit(): Empty CYCLE_DOUBLE_R1 piece!") if len(self.MICROCODE_LINES_CYCLE_ADD) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD piece!") if len(self.MICROCODE_LINES_CYCLE_ADD_R0_AT_INFINITY) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_R0_AT_INFINITY piece!") if len(self.MICROCODE_LINES_CYCLE_ADD_R1_AT_INFINITY) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_R1_AT_INFINITY piece!") if len(self.MICROCODE_LINES_CYCLE_ADD_REGULAR) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_REGULAR piece!") if len(self.MICROCODE_LINES_CYCLE_K0) == 0: sys.exit("sys.exit(): Empty CYCLE_K0 piece!") if len(self.MICROCODE_LINES_CYCLE_K1) == 0: sys.exit("sys.exit(): Empty CYCLE_K1 piece!") if len(self.MICROCODE_LINES_INVERT_P256) == 0: sys.exit("sys.exit(): Empty INVERT_P256 piece!") if len(self.MICROCODE_LINES_INVERT_P384) == 0: sys.exit("sys.exit(): Empty INVERT_P384 piece!") if len(self.MICROCODE_LINES_CONVERT) == 0: sys.exit("sys.exit(): Empty CONVERT piece!") length = 0 length += len(self.MICROCODE_LINES_PREPARE) length += len(self.MICROCODE_LINES_CYCLE_DOUBLE_R0) length += len(self.MICROCODE_LINES_CYCLE_DOUBLE_R1) length += len(self.MICROCODE_LINES_CYCLE_ADD) length += len(self.MICROCODE_LINES_CYCLE_ADD_R0_AT_INFINITY) length += len(self.MICROCODE_LINES_CYCLE_ADD_R1_AT_INFINITY) length += len(self.MICROCODE_LINES_CYCLE_ADD_REGULAR) length += len(self.MICROCODE_LINES_CYCLE_K0) length += len(self.MICROCODE_LINES_CYCLE_K1) length += len(self.MICROCODE_LINES_CONVERT) if mode == 1: length += len(self.MICROCODE_LINES_INVERT_P256) if mode == 2: length += len(self.MICROCODE_LINES_INVERT_P384) print("Total number of micro-operations (w/o stops): %s" % (length)) self.__addr = 0 print("\n -=-=-=-=-=- CUT AND PASTE BELOW -=-=-=-=-=-\n") num_mul_cycle = 0 num_mul_invert_p256 = 0 num_mul_invert_p384 = 0 offset_prepare = self.__addr; print("// PREPARE"); for line in self.MICROCODE_LINES_PREPARE: self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_double_r0 = self.__addr; print("// CYCLE_DOUBLE_R0"); for line in self.MICROCODE_LINES_CYCLE_DOUBLE_R0: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_double_r1 = self.__addr; print("// CYCLE_DOUBLE_R1"); for line in self.MICROCODE_LINES_CYCLE_DOUBLE_R1: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_add = self.__addr; print("// CYCLE_ADD"); for line in self.MICROCODE_LINES_CYCLE_ADD: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_add_r0_at_infinity = self.__addr; print("// CYCLE_ADD_R0_AT_INFINITY"); for line in self.MICROCODE_LINES_CYCLE_ADD_R0_AT_INFINITY: self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_add_r1_at_infinity = self.__addr; print("// CYCLE_ADD_R1_AT_INFINITY"); for line in self.MICROCODE_LINES_CYCLE_ADD_R1_AT_INFINITY: self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_add_regular = self.__addr; print("// CYCLE_ADD_REGULAR"); for line in self.MICROCODE_LINES_CYCLE_ADD_REGULAR: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_k0 = self.__addr; print("// CYCLE_K0"); for line in self.MICROCODE_LINES_CYCLE_K0: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_cycle_k1 = self.__addr; print("// CYCLE_K1"); for line in self.MICROCODE_LINES_CYCLE_K1: self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) offset_convert = self.__addr; print("// CONVERT"); for line in self.MICROCODE_LINES_CONVERT: num_mul_cycle += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) if mode == 1: offset_invert_p256 = self.__addr; print("// INVERT_P256"); for line in self.MICROCODE_LINES_INVERT_P256: num_mul_invert_p256 += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) if mode == 2: offset_invert_p384 = self.__addr; print("// INVERT_P384"); for line in self.MICROCODE_LINES_INVERT_P384: num_mul_invert_p384 += self.__format_line(line) self.__format_line(self.MICROCODE_LINE_STOP) print("\n") self.__format_offset("UOP_OFFSET_PREPARE ", offset_prepare) self.__format_offset("UOP_OFFSET_CYCLE_DOUBLE_R0 ", offset_cycle_double_r0) self.__format_offset("UOP_OFFSET_CYCLE_DOUBLE_R1 ", offset_cycle_double_r1) self.__format_offset("UOP_OFFSET_CYCLE_ADD ", offset_cycle_add) self.__format_offset("UOP_OFFSET_CYCLE_ADD_R0_AT_INFINITY ", offset_cycle_add_r0_at_infinity) self.__format_offset("UOP_OFFSET_CYCLE_ADD_R1_AT_INFINITY ", offset_cycle_add_r1_at_infinity) self.__format_offset("UOP_OFFSET_CYCLE_ADD_REGULAR ", offset_cycle_add_regular) self.__format_offset("UOP_OFFSET_CYCLE_K0 ", offset_cycle_k0) self.__format_offset("UOP_OFFSET_CYCLE_K1 ", offset_cycle_k1) self.__format_offset("UOP_OFFSET_CONVERT ", offset_convert) if mode == 1: self.__format_offset("UOP_OFFSET_INVERT_P256 ", offset_invert_p256) if mode == 2: self.__format_offset("UOP_OFFSET_INVERT_P384 ", offset_invert_p384) print("") print("num_mul_cycle = %d" % num_mul_cycle) print("num_mul_invert_p256 = %d" % num_mul_invert_p256) print("num_mul_invert_p384 = %d" % num_mul_invert_p384) def __format_line(self, line): line = self.MICROCODE_FORMAT_LINE % (self.__addr, line) print(line) self.__addr += 1 is_mul = line.find(self.MICROCODE_V_NAME_OPCODE_MUL) if is_mul >= 0: return 1 return 0 def __format_offset(self, name, offset): print(self.MICROCODE_FORMAT_OFFSET % (name, offset)) def __try_start_parsing(self): piece = self.MICROCODE_PIECE_ENUM.NONE begin_marker = re.match("^/\*\s*" + self.MARKER_BEGIN_MICROCODE + "\s*" + self.MATCH_GROUP_09AZ + "\s*\*/$", self.__next_c_line); if begin_marker: piece = self.MICROCODE_PIECE_DICT[begin_marker.group(1)] return piece def __encode_uop(self, opcode, banks, src1, src2, dst): return "{%s, %s, %s, %s, %s}" % (opcode, banks, src1, src2, dst) def __continue_parsing(self): end_marker = re.match("^/\*\s*" + self.MARKER_END_MICROCODE + "\s*\*/$", self.__next_c_line); if end_marker: return False # cmpz? uop_cmpz = re.match("^" + self.MICROCODE_C_NAME_UOP_CMPZ + "\(\s*" + self.MATCH_GROUP_BANK + "\,\s*" + self.MATCH_GROUP_09AZ + "\)\;$", self.__next_c_line, re.IGNORECASE) if uop_cmpz: ok = self.__parse_uop_cmpz(uop_cmpz) if ok: return True else: self.__print_parse_error("parse_uop_cmpz() failed!") self.__abort() # move? uop_move = re.match("^" + self.MICROCODE_C_NAME_UOP_MOVE + "\(\s*" + self.MATCH_GROUP_BANK + "\,\s*" + self.MATCH_GROUP_09AZ + "\,\s*" + self.MATCH_GROUP_BANK + "\,\s*" + self.MATCH_GROUP_09AZ + "\)\;$", self.__next_c_line, re.IGNORECASE) if uop_move: ok = self.__parse_uop_move(uop_move) if ok: return True else: self.__print_parse_error("parse_uop_move() failed!") self.__abort() # calc? uop_calc = re.match("^" + self.MATCH_GROUP_CALC + "\s*\(" + self.MATCH_GROUP_MATH + "\,\s*" + self.MATCH_GROUP_BANK + "\,\s*" + self.MATCH_GROUP_09AZ + "\,\s*" + self.MATCH_GROUP_09AZ + "\,\s*" + self.MATCH_GROUP_BANK + "\,\s*" + self.MATCH_GROUP_09AZ + "\)\;$", self.__next_c_line, re.IGNORECASE) if uop_calc: ok = self.__parse_uop_calc(uop_calc) if ok: return True else: self.__print_parse_error("parse_uop_calc() failed!") self.__abort() # cycle? uop_cycle = re.match("^" + self.MICROCODE_C_NAME_UOP_CYCLE + "\(" + self.MATCH_GROUP_NUMBER + "\)\;$", self.__next_c_line, re.IGNORECASE) if uop_cycle: ok = self.__parse_uop_cycle(uop_cycle) if ok: return True else: self.__print_parse_error("parse_uop_cycle() failed!") self.__abort() # repeat? uop_repeat = re.match("^" + self.MICROCODE_C_NAME_UOP_REPEAT + "\(" + "\)\;$", self.__next_c_line, re.IGNORECASE) if uop_repeat: ok = self.__parse_uop_repeat() if ok: return True else: self.__print_parse_error("__parse_uop_repeat() failed!") self.__abort() self.__print_parse_error("unknown micro-operation!") self.__abort() def __check_math(self, math): if not math in self.MICROCODE_MATH_DICT: print_parse_error("bad math!") return False return True def __check_banks(self, src, dst): if not src in self.MICROCODE_BANK_DICT: print_parse_error("bad src bank!") return False if not dst in self.MICROCODE_BANK_DICT: print_parse_error("bad dst bank!") return False if src == dst: print_parse_error("src bank == dst bank!") return False return True def __check_bank(self, src): if not src in self.MICROCODE_BANK_DICT: print_parse_error("bad src bank!") return False return True def __check_op3(self, src1, src2, dst): if not src1 in self.MICROCODE_OPERAND_DICT: self.__print_parse_error("bad src1 operand!") return False if src2 != "" and not src2 in self.MICROCODE_OPERAND_DICT: self.__print_parse_error("bad src2 operand!") return False if dst != "" and not dst in self.MICROCODE_OPERAND_DICT: self.__print_parse_error("bad dst operand!") return False return True def __check_op2(self, src, dst): return self.__check_op3(src, "", dst) def __check_op1(self, src): return self.__check_op2(src, "") def __parse_uop_move(self, params): bank_src = params.group(1) bank_dst = params.group(3) op_src = params.group(2) op_dst = params.group(4) if not self.__check_banks(bank_src, bank_dst): self.__print_parse_error("check_banks() failed!") return False if not self.__check_op2(op_src, op_dst): self.__print_parse_error("check_op2() failed!") return False opcode = self.MICROCODE_V_NAME_OPCODE_MOVE bank = self.MICROCODE_BANK_DICT[bank_src] src1 = self.MICROCODE_OPERAND_DICT[op_src] src2 = self.MICROCODE_V_NAME_OPERAND_DONTCARE dst = self.MICROCODE_OPERAND_DICT[op_dst] data = self.__encode_uop(opcode, bank, src1, src2, dst) self.__store_uop(data) return True def __parse_uop_cmpz(self, params): bank_src = params.group(1) op_src = params.group(2) if not self.__check_bank(bank_src): self.__print_parse_error("check_bank() failed!") return False if not self.__check_op1(op_src): self.__print_parse_error("check_op1() failed!") return False opcode = self.MICROCODE_V_NAME_OPCODE_CMPZ bank = self.MICROCODE_BANK_DICT[bank_src] src1 = self.MICROCODE_OPERAND_DICT[op_src] src2 = self.MICROCODE_V_NAME_OPERAND_DONTCARE dst = self.MICROCODE_V_NAME_OPERAND_DONTCARE data = self.__encode_uop(opcode, bank, src1, src2, dst) self.__store_uop(data) return True def __parse_uop_calc(self, params): calc = params.group(1) math = params.group(2) bank_src = params.group(3) bank_dst = params.group(6) op_src1 = params.group(4) op_src2 = params.group(5) op_dst = params.group(7) if not self.__check_math(math): self.__print_parse_error("check_calc() failed!") return False if not self.__check_banks(bank_src, bank_dst): self.__print_parse_error("check_banks() failed!") return False if not self.__check_op3(op_src1, op_src2, op_dst): self.__print_parse_error("check_op3() failed!") return False opcode = self.MICROCODE_MATH_DICT[math] banks = self.MICROCODE_BANK_DICT[bank_src] src1 = self.MICROCODE_OPERAND_DICT[op_src1] src2 = self.MICROCODE_OPERAND_DICT[op_src2] dst = self.MICROCODE_OPERAND_DICT[op_dst] data = self.__encode_uop(opcode, banks, src1, src2, dst) if calc == self.MICROCODE_C_NAME_UOP_CALC: self.__store_uop(data) elif calc == self.MICROCODE_C_NAME_UOP_CALC_EVEN: self.__loop_even = data elif calc == self.MICROCODE_C_NAME_UOP_CALC_ODD: self.__loop_odd = data else: return False return True def __parse_uop_cycle(self, params): self.__loop_iters = int(params.group(1)) return True def __parse_uop_repeat(self): print(" Unrolling loop (%d iters)..." % (self.__loop_iters)) for i in range(0, self.__loop_iters): if i % 2 == 0: self.__store_uop(self.__loop_even) else: self.__store_uop(self.__loop_odd) return True def __store_uop(self, data): #print("\t" + data) if self.__current_piece == self.MICROCODE_PIECE_ENUM.PREPARE: self.MICROCODE_LINES_PREPARE.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_DOUBLE_R0: self.MICROCODE_LINES_CYCLE_DOUBLE_R0.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_DOUBLE_R1: self.MICROCODE_LINES_CYCLE_DOUBLE_R1.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD: self.MICROCODE_LINES_CYCLE_ADD.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD_R0_AT_INFINITY: self.MICROCODE_LINES_CYCLE_ADD_R0_AT_INFINITY.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD_R1_AT_INFINITY: self.MICROCODE_LINES_CYCLE_ADD_R1_AT_INFINITY.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD_REGULAR: self.MICROCODE_LINES_CYCLE_ADD_REGULAR.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_K0: self.MICROCODE_LINES_CYCLE_K0.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_K1: self.MICROCODE_LINES_CYCLE_K1.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.INVERT_P256: self.MICROCODE_LINES_INVERT_P256.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.INVERT_P384: self.MICROCODE_LINES_INVERT_P384.append(data) elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CONVERT: self.MICROCODE_LINES_CONVERT.append(data) def __print_parse_error(self, msg): print("PARSE ERROR: %s" % (msg)) def __abort(self): sys.exit("Stopped at line #%d:\n%s" % (self.__line_num, self.__next_c_line)) # ----------------------------------------------------------------------------- def main(filenames): # ----------------------------------------------------------------------------- parser = MICROCODE_PARSER(filenames) parser.parse() parser.format() # ----------------------------------------------------------------------------- if __name__ == "__main__": # ----------------------------------------------------------------------------- main(C_FILES) # # End-of-File #