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.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

engine.py 8.9KB

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