From 1f8d13bf8d2e813f0c5da653c4abffb7a817db9a Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Wed, 19 Dec 2018 16:03:08 +0300 Subject: * New hardware architecture * Randomized test vector --- ecdsa_microcode_parser.py | 694 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100644 ecdsa_microcode_parser.py (limited to 'ecdsa_microcode_parser.py') diff --git a/ecdsa_microcode_parser.py b/ecdsa_microcode_parser.py new file mode 100644 index 0000000..56aa94c --- /dev/null +++ b/ecdsa_microcode_parser.py @@ -0,0 +1,694 @@ +# +# ecdsa_microcode_parser.py +# +# Author: Pavel Shatov +# +# Copyright (c) 2018, NORDUnet A/S +# +# All rights reserved. +# +# 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 NORDUnet A/S 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 = 1 + CYCLE_ADD = 2 + + CYCLE_ADD_AT_INFINITY = 3 + CYCLE_ADD_SAME_X_SAME_Y = 4 + CYCLE_ADD_SAME_X = 5 + CYCLE_ADD_REGULAR = 6 + + CYCLE_K0 = 7 + CYCLE_K1 = 8 + + CONVERT = 9 + + CONVERT_AT_INFINITY = 10 + CONVERT_REGULAR = 11 + + INVERT_P256 = 12 + INVERT_P384 = 13 + + + # 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", + "CONST_HX", "CONST_HY", + "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_RX", "CYCLE_RY", "CYCLE_RZ", + "CYCLE_SX", "CYCLE_SY", "CYCLE_SZ", + "CYCLE_A", "CYCLE_A2", "CYCLE_B", + "CYCLE_C", "CYCLE_C2", "CYCLE_C2_2", + "CYCLE_D", "CYCLE_E", "CYCLE_F", + "CYCLE_G", "CYCLE_H", "CYCLE_J", + "CYCLE_Z2", + "CYCLE_T1", "CYCLE_T2", + "CYCLE_T3", "CYCLE_T4"] + + # 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": MICROCODE_PIECE_ENUM.CYCLE_DOUBLE, + "CYCLE_ADD": MICROCODE_PIECE_ENUM.CYCLE_ADD, + + "CYCLE_ADD_AT_INFINITY": MICROCODE_PIECE_ENUM.CYCLE_ADD_AT_INFINITY, + "CYCLE_ADD_SAME_X_SAME_Y": MICROCODE_PIECE_ENUM.CYCLE_ADD_SAME_X_SAME_Y, + "CYCLE_ADD_SAME_X": MICROCODE_PIECE_ENUM.CYCLE_ADD_SAME_X, + "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, + + "CONVERT_AT_INFINITY": MICROCODE_PIECE_ENUM.CONVERT_AT_INFINITY, + "CONVERT_REGULAR": MICROCODE_PIECE_ENUM.CONVERT_REGULAR} + + + # 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 = [] + MICROCODE_LINES_CYCLE_ADD = [] + + MICROCODE_LINES_CYCLE_ADD_AT_INFINITY = [] + MICROCODE_LINES_CYCLE_ADD_SAME_X_SAME_Y = [] + MICROCODE_LINES_CYCLE_ADD_SAME_X = [] + 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_LINES_CONVERT_AT_INFINITY = [] + MICROCODE_LINES_CONVERT_REGULAR = [] + + 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) == 0: sys.exit("sys.exit(): Empty CYCLE_DOUBLE piece!") + if len(self.MICROCODE_LINES_CYCLE_ADD) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD piece!") + + if len(self.MICROCODE_LINES_CYCLE_ADD_AT_INFINITY) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_AT_INFINITY piece!") + if len(self.MICROCODE_LINES_CYCLE_ADD_SAME_X_SAME_Y) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_SAME_X_SAME_Y piece!") + if len(self.MICROCODE_LINES_CYCLE_ADD_SAME_X) == 0: sys.exit("sys.exit(): Empty CYCLE_ADD_SAME_X 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!") + + if len(self.MICROCODE_LINES_CONVERT_AT_INFINITY) == 0: sys.exit("sys.exit(): Empty CONVERT_AT_INFINITY piece!") + if len(self.MICROCODE_LINES_CONVERT_REGULAR) == 0: sys.exit("sys.exit(): Empty CONVERT_REGULAR piece!") + + length = 0 + length += len(self.MICROCODE_LINES_PREPARE) + + length += len(self.MICROCODE_LINES_CYCLE_DOUBLE) + length += len(self.MICROCODE_LINES_CYCLE_ADD) + + length += len(self.MICROCODE_LINES_CYCLE_ADD_AT_INFINITY) + length += len(self.MICROCODE_LINES_CYCLE_ADD_SAME_X_SAME_Y) + length += len(self.MICROCODE_LINES_CYCLE_ADD_SAME_X) + 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) + + length += len(self.MICROCODE_LINES_CONVERT_AT_INFINITY) + length += len(self.MICROCODE_LINES_CONVERT_REGULAR) + + 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 = self.__addr; + print("// CYCLE_DOUBLE"); + for line in self.MICROCODE_LINES_CYCLE_DOUBLE: + 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_at_infinity = self.__addr; + print("// CYCLE_ADD_AT_INFINITY"); + for line in self.MICROCODE_LINES_CYCLE_ADD_AT_INFINITY: + self.__format_line(line) + self.__format_line(self.MICROCODE_LINE_STOP) + + offset_cycle_add_same_x_same_y = self.__addr; + print("// CYCLE_ADD_SAME_X_SAME_Y"); + for line in self.MICROCODE_LINES_CYCLE_ADD_SAME_X_SAME_Y: + self.__format_line(line) + self.__format_line(self.MICROCODE_LINE_STOP) + + offset_cycle_add_same_x = self.__addr; + print("// CYCLE_ADD_SAME_X"); + for line in self.MICROCODE_LINES_CYCLE_ADD_SAME_X: + 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) + + offset_convert_at_infinity = self.__addr; + print("// CONVERT_AT_INFINITY"); + for line in self.MICROCODE_LINES_CONVERT_AT_INFINITY: + self.__format_line(line) + self.__format_line(self.MICROCODE_LINE_STOP) + + offset_convert_regular = self.__addr; + print("// CONVERT_REGULAR"); + for line in self.MICROCODE_LINES_CONVERT_REGULAR: + 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 ", offset_cycle_double) + self.__format_offset("UOP_OFFSET_CYCLE_ADD ", offset_cycle_add) + self.__format_offset("UOP_OFFSET_CYCLE_ADD_AT_INFINITY ", offset_cycle_add_at_infinity) + self.__format_offset("UOP_OFFSET_CYCLE_ADD_SAME_X_SAME_Y", offset_cycle_add_same_x_same_y) + self.__format_offset("UOP_OFFSET_CYCLE_ADD_SAME_X ", offset_cycle_add_same_x) + 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) + self.__format_offset("UOP_OFFSET_CONVERT_AT_INFINITY ", offset_convert_at_infinity) + self.__format_offset("UOP_OFFSET_CONVERT_REGULAR ", offset_convert_regular) + 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: self.MICROCODE_LINES_CYCLE_DOUBLE.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_AT_INFINITY: self.MICROCODE_LINES_CYCLE_ADD_AT_INFINITY.append(data) + elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD_SAME_X_SAME_Y: self.MICROCODE_LINES_CYCLE_ADD_SAME_X_SAME_Y.append(data) + elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CYCLE_ADD_SAME_X: self.MICROCODE_LINES_CYCLE_ADD_SAME_X.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) + elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CONVERT_AT_INFINITY: self.MICROCODE_LINES_CONVERT_AT_INFINITY.append(data) + elif self.__current_piece == self.MICROCODE_PIECE_ENUM.CONVERT_REGULAR: self.MICROCODE_LINES_CONVERT_REGULAR.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 +# -- cgit v1.2.3