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.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
pirms 4 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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