Python-ELMO is a Python library which offers an encapsulation of the binary tool ELMO, in order to manipulate it easily in Python and SageMath script.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

engine.py 8.7KB

  1. import numpy as np
  2. import os
  3. from enum import IntEnum, unique
  4. from .utils import binary_writing
  5. from .config import ELMO_TOOL_REPOSITORY
  6. @unique
  7. class Instruction(IntEnum):
  8. EOR = 0
  9. LSL = 1
  10. STR = 2
  11. LDR = 3
  12. MUL = 4
  13. OTHER = 5
  14. # Short name for 'Instruction' class
  15. Instr = Instruction
  16. PREVIOUS = 0
  17. CURRENT = 1
  18. SUBSEQUENT = 2
  19. class ELMOEngine:
  20. def __init__(self):
  21. self.load_coefficients()
  22. self.reset_points()
  23. def _extract_data(self, nb):
  24. coeffs = self.coefficients[self.pos:self.pos+nb]
  25. self.pos += nb
  26. return coeffs
  27. def load_coefficients(self):
  28. filename = os.path.join(
  29. os.path.dirname(os.path.abspath(__file__)),
  30. ELMO_TOOL_REPOSITORY,
  31. 'coeffs.txt',
  32. )
  33. self.coefficients = None
  34. with open(filename, 'r') as _file:
  35. self.coefficients = np.array([list(map(float, line.split())) for line in _file.readlines()[:2153]])
  36. if self.coefficients is None:
  37. raise IOError('Problem to read the coefficients.')
  38. self.pos = 0
  39. self.constant = np.squeeze(self._extract_data(1))
  40. self.PrvInstr = self._extract_data(4)
  41. self.SubInstr = self._extract_data(4)
  42. self.Operand1 = self._extract_data(32)
  43. self.Operand2 = self._extract_data(32)
  44. self.BitFlip1 = self._extract_data(32)
  45. self.BitFlip2 = self._extract_data(32)
  46. self.HWOp1PrvInstr = self._extract_data(4)
  47. self.HWOp2PrvInstr = self._extract_data(4)
  48. self.HDOp1PrvInstr = self._extract_data(4)
  49. self.HDOp2PrvInstr = self._extract_data(4)
  50. self.HWOp1SubInstr = self._extract_data(4)
  51. self.HWOp2SubInstr = self._extract_data(4)
  52. self.HDOp1SubInstr = self._extract_data(4)
  53. self.HDOp2SubInstr = self._extract_data(4)
  54. self.Operand1_bitinteractions = self._extract_data(496)
  55. self.Operand2_bitinteractions = self._extract_data(496)
  56. self.BitFlip1_bitinteractions = self._extract_data(496)
  57. self.BitFlip2_bitinteractions = self._extract_data(496)
  58. def reset_points(self):
  59. self.points = []
  60. self.power = None
  61. def add_point(self, triplet, previous_ops, current_ops):
  62. self.points.append((triplet, previous_ops, current_ops))
  63. def _dot(self, a, b):
  64. return np.sum(a * b, axis=0)
  65. def calculate_point(self, triplet, previous_ops, current_ops, debug=False):
  66. nb_points = triplet.shape[1]
  67. instructiontype = triplet[CURRENT]
  68. instructiontype = instructiontype % 5 # Type 5 = Instruction was not profiled
  69. # Previous
  70. previous_instruction_typedec = triplet[PREVIOUS]
  71. previous_instruction_type = np.zeros((5, nb_points))
  72. for i in range(nb_points):
  73. if previous_instruction_typedec[i] < 5:
  74. previous_instruction_type[previous_instruction_typedec[i],i] = 1
  75. # Current
  76. (current_op1_binary, hw_op1) = binary_writing(current_ops[0], with_hamming=True)
  77. (current_op2_binary, hw_op2) = binary_writing(current_ops[1], with_hamming=True)
  78. (current_op1_bitflip, hd_op1) = binary_writing(previous_ops[0] ^ current_ops[0], with_hamming=True)
  79. (current_op2_bitflip, hd_op2) = binary_writing(previous_ops[1] ^ current_ops[1], with_hamming=True)
  80. current_instruction_typedec = instructiontype
  81. current_instruction_type = np.zeros((5, nb_points))
  82. for i in range(nb_points):
  83. if triplet[CURRENT,i] < 5:
  84. current_instruction_type[current_instruction_typedec[i],i] = 1
  85. # Subsequent
  86. subsequent_instruction_typedec = triplet[SUBSEQUENT]
  87. subsequent_instruction_type = np.zeros((5, nb_points))
  88. for i in range(nb_points):
  89. if subsequent_instruction_typedec[i] < 5:
  90. subsequent_instruction_type[subsequent_instruction_typedec[i],i] = 1
  91. # Component variables
  92. PrvInstr_data = self._dot( previous_instruction_type[1:], self.PrvInstr[:,instructiontype] )
  93. SubInstr_data = self._dot( subsequent_instruction_type[1:], self.SubInstr[:,instructiontype] )
  94. Operand1_data = self._dot( current_op1_binary, self.Operand1[:,instructiontype] )
  95. Operand2_data = self._dot( current_op2_binary, self.Operand2[:,instructiontype] )
  96. BitFlip1_data = self._dot( current_op1_bitflip, self.BitFlip1[:,instructiontype] )
  97. BitFlip2_data = self._dot( current_op2_bitflip, self.BitFlip2[:,instructiontype] )
  98. HWOp1PrvInstr_data = hw_op1 * self._dot(previous_instruction_type[1:], self.HWOp1PrvInstr[:,instructiontype])
  99. HWOp2PrvInstr_data = hw_op2 * self._dot(previous_instruction_type[1:], self.HWOp2PrvInstr[:,instructiontype])
  100. HDOp1PrvInstr_data = hd_op1 * self._dot(previous_instruction_type[1:], self.HDOp1PrvInstr[:,instructiontype])
  101. HDOp2PrvInstr_data = hd_op2 * self._dot(previous_instruction_type[1:], self.HDOp2PrvInstr[:,instructiontype])
  102. HWOp1SubInstr_data = hw_op1 * self._dot(subsequent_instruction_type[1:], self.HWOp1SubInstr[:,instructiontype])
  103. HWOp2SubInstr_data = hw_op2 * self._dot(subsequent_instruction_type[1:], self.HWOp2SubInstr[:,instructiontype])
  104. HDOp1SubInstr_data = hd_op1 * self._dot(subsequent_instruction_type[1:], self.HDOp1SubInstr[:,instructiontype])
  105. HDOp2SubInstr_data = hd_op2 * self._dot(subsequent_instruction_type[1:], self.HDOp2SubInstr[:,instructiontype])
  106. Operand1_bitinteractions_data = np.zeros((nb_points))
  107. Operand2_bitinteractions_data = np.zeros((nb_points))
  108. BitFlip1_bitinteractions_data = np.zeros((nb_points))
  109. BitFlip2_bitinteractions_data = np.zeros((nb_points))
  110. count = 0
  111. for i in range(32):
  112. for j in range(i+1,32):
  113. Operand1_bitinteractions_data += self.Operand1_bitinteractions[count,instructiontype] * current_op1_binary[i] * current_op1_binary[j]
  114. Operand2_bitinteractions_data += self.Operand2_bitinteractions[count,instructiontype] * current_op2_binary[i] * current_op2_binary[j]
  115. BitFlip1_bitinteractions_data += self.BitFlip1_bitinteractions[count,instructiontype] * current_op1_bitflip[i] * current_op1_bitflip[j]
  116. BitFlip2_bitinteractions_data += self.BitFlip2_bitinteractions[count,instructiontype] * current_op2_bitflip[i] * current_op2_bitflip[j]
  117. count += 1
  118. power = self.constant[instructiontype] \
  119. + PrvInstr_data + SubInstr_data \
  120. + Operand1_data + Operand2_data \
  121. + BitFlip1_data + BitFlip2_data \
  122. + HWOp1PrvInstr_data + HWOp2PrvInstr_data \
  123. + HDOp1PrvInstr_data + HDOp2PrvInstr_data \
  124. + HWOp1SubInstr_data + HWOp2SubInstr_data \
  125. + HDOp1SubInstr_data + HDOp2SubInstr_data \
  126. + Operand1_bitinteractions_data + Operand2_bitinteractions_data \
  127. + BitFlip1_bitinteractions_data + BitFlip2_bitinteractions_data
  128. for i in range(nb_points):
  129. if triplet[CURRENT,i] == 5:
  130. power[i] = self.constant[triplet[CURRENT,i]]
  131. if debug:
  132. print([self.constant[instructiontype], \
  133. PrvInstr_data, SubInstr_data, \
  134. Operand1_data, Operand2_data, \
  135. BitFlip1_data, BitFlip2_data, \
  136. HWOp1PrvInstr_data, HWOp2PrvInstr_data, \
  137. HDOp1PrvInstr_data, HDOp2PrvInstr_data, \
  138. HWOp1SubInstr_data, HWOp2SubInstr_data, \
  139. HDOp1SubInstr_data, HDOp2SubInstr_data, \
  140. Operand1_bitinteractions_data, Operand2_bitinteractions_data, \
  141. BitFlip1_bitinteractions_data, BitFlip2_bitinteractions_data])
  142. return power
  143. def run(self):
  144. nb_points = len(self.points)
  145. triplet = np.array([p[0] for p in self.points]).T # shape = (3, nb_points)
  146. previous_ops = np.array([p[1] for p in self.points]).T # shape = (2, nb_points)
  147. current_ops = np.array([p[2] for p in self.points]).T # shape = (2, nb_points)
  148. self.power = self.calculate_point(triplet, previous_ops, current_ops)
  149. def oneshot_point(self, triplet, previous_ops, current_ops):
  150. self.reset_points()
  151. self.add_point(triplet, previous_ops, current_ops)
  152. self.run()
  153. return self.power