aboutsummaryrefslogtreecommitdiff
path: root/ecdsa_microcode_parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'ecdsa_microcode_parser.py')
-rw-r--r--ecdsa_microcode_parser.py694
1 files changed, 694 insertions, 0 deletions
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 <P256|P384>!")
+
+ 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
+#