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文字以内のものにしてください。

project_base.py 8.2KB

  1. import os, re
  2. import socket
  3. from .protocol import SocketTool
  4. import numpy as np
  5. def to_hex(v, nb_bits=16):
  6. try:
  7. v_hex = v.hex()
  8. except AttributeError:
  9. v_hex = hex(v)[2:]
  10. return '0'*(nb_bits//4-len(v_hex)) + v_hex
  11. def split_octet(hexstr):
  12. return [hexstr[i:i+2] for i in range(0, len(hexstr), 2)]
  13. def to_signed_hex(v, nb_bits=16):
  14. try:
  15. return split_octet(to_hex(v & (2**nb_bits-1), nb_bits=nb_bits))
  16. except TypeError as err:
  17. raise TypeError('Error to transform a <{}> into signed hex.'.format(type(v))) from err
  18. def write(_input, uintXX, nb_bits=16):
  19. uintXX = to_signed_hex(uintXX, nb_bits=nb_bits)
  20. for i in range(nb_bits//8):
  21. _input.write(uintXX[i]+'\n')
  22. def write_list(_input, uint16_list):
  23. for uint16 in uint16_list:
  24. write(_input, uint16)
  25. def launch_simulation(quiet=False, **kwargs):
  26. try:
  27. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  28. s.connect(('localhost', 5000))
  29. SocketTool.send_data(s, kwargs)
  30. if not SocketTool.get_ack(s):
  31. raise RuntimeError("NACK received: The request has been refused !")
  32. else:
  33. data = SocketTool.get_data(s)
  34. if data['error'] and not quiet:
  35. raise Exception("The simulation return an error.")
  36. return data['output'], data['error']
  37. s.close()
  38. except IOError as err:
  39. raise RuntimeError("The connection refused. Has the ELMO server been switch on ?") from err
  40. class SimulationProject:
  41. _nb_bits_for_nb_challenges = 16
  42. _project_directory = None
  43. ### Define the project
  44. @classmethod
  45. def get_project_directory(cl):
  46. if cl._project_directory:
  47. return cl._project_directory
  48. else:
  49. raise NotImplementedError()
  50. @classmethod
  51. def set_project_directory(cl, project_directory):
  52. cl._project_directory = project_directory
  53. @classmethod
  54. def get_project_label(cl):
  55. return cl.get_project_directory()
  56. @classmethod
  57. def get_make_directory(cl):
  58. return ''
  59. @classmethod
  60. def get_binary(cl):
  61. raise NotImplementedError()
  62. @classmethod
  63. def get_parameters_names(cl):
  64. return set()
  65. @classmethod
  66. def adapt_project(cl, parameters):
  67. return
  68. def get_challenge_format(self):
  69. raise NotImplementedError()
  70. ### Tools to realize the simulation of the project
  71. def __init__(self, challenges=None):
  72. self.elmo_folder = os.path.dirname(os.path.abspath(__file__))+'/elmo'
  73. self.challenges = challenges
  74. self.is_executed = False
  75. def set_challenges(self, challenges):
  76. self.challenges = challenges
  77. def get_writable_input_file(self):
  78. return open('{}/input.txt'.format(self.elmo_folder), 'w')
  79. def set_input_for_each_challenge(self, input, challenge):
  80. format = self.get_challenge_format()
  81. def aux(sizes, data):
  82. if len(sizes) == 0:
  83. write(input, data)
  84. else:
  85. assert len(data) == sizes[0], 'Incorrect format for challenge. Get {} instead of {}'.format(len(data), sizes[0])
  86. for i in range(sizes[0]):
  87. aux(sizes[1:], data[i])
  88. for num_part in range(len(format)):
  89. aux(format[num_part], challenge[num_part])
  90. def set_input(self, input):
  91. assert len(self.challenges) < 2**16, 'The number of challenges must be strictly lower than 65536. Currently, there are {} challenges.'.format(len(self.challenges))
  92. write(input, len(self.challenges), nb_bits=self._nb_bits_for_nb_challenges)
  93. for challenge in self.challenges:
  94. self.set_input_for_each_challenge(input, challenge)
  95. def run(self):
  96. with open('{}/input.txt'.format(self.elmo_folder), 'w') as _input:
  97. self.set_input(_input)
  98. from .manage import execute_simulation
  99. execute_simulation(self)
  100. self.is_executed = True
  101. def run_online(self):
  102. with open('{}/input.txt'.format(self.elmo_folder), 'w') as _input:
  103. self.set_input(_input)
  104. launch_simulation(project=self.get_project_label(), quiet=False)
  105. self.is_executed = True
  106. def get_asmtrace_filename(self):
  107. return '{}/output/asmoutput/asmtrace00001.txt'.format(self.elmo_folder)
  108. def get_asmtrace(self):
  109. with open(self.get_asmtrace_filename(), 'r') as _file:
  110. return [line.strip() for line in _file.readlines()]
  111. def get_indexes_of(self, condition):
  112. with open(self.get_asmtrace_filename(), 'r') as _file:
  113. asmtrace = _file.readlines()
  114. return [i for i, instr in enumerate(asmtrace) if condition(instr)]
  115. def get_number_of_traces(self):
  116. return len(self.challenges)
  117. def get_results(self, only_filenames=False, reorganise=None, indexes=None):
  118. assert self.is_executed
  119. nb_traces = self.get_number_of_traces()
  120. trace_filenames = []
  121. for filename in os.listdir('{}/output/traces/'.format(self.elmo_folder)):
  122. if re.search(r'^trace\d+\.trc$', filename):
  123. trace_filenames.append('{}/output/traces/{}'.format(self.elmo_folder, filename))
  124. if len(trace_filenames) >= nb_traces:
  125. break
  126. assert len(trace_filenames) == nb_traces
  127. results = trace_filenames
  128. if not only_filenames:
  129. for i in range(len(results)):
  130. with open(results[i], 'r') as _file:
  131. if indexes is not None:
  132. results[i] = list(map(float, _file.readlines()[indexes]))
  133. else:
  134. results[i] = list(map(float, _file.readlines()))
  135. if reorganise is not None:
  136. results = reorganise(results)
  137. return results
  138. def get_traces(self, reorganise=None, indexes=None):
  139. results = self.get_results(only_filenames=False, reorganise=reorganise,indexes=indexes)
  140. nb_traces = self.get_number_of_traces()
  141. trace_length = len(results[0])
  142. traces = np.zeros((nb_traces, trace_length))
  143. for i in range(nb_traces):
  144. traces[i,:] = results[i]
  145. if reorganise is not None:
  146. traces = reorganise(traces)
  147. return traces
  148. def get_printed_data(self):
  149. with open('{}/output/printdata.txt'.format(self.elmo_folder), 'r') as _file:
  150. data = list(map(lambda x: int(x, 16), _file.readlines()))
  151. nb_traces = self.get_number_of_traces()
  152. nb_data_per_trace = len(data) // nb_traces
  153. return [data[nb_data_per_trace*i:nb_data_per_trace*(i+1)] for i in range(nb_traces)]
  154. def analyse_operands(self, num_line, num_trace=1):
  155. num_str = str(num_trace)
  156. num_str = '0'*(5-len(num_str)) + num_str
  157. operands_filename = self.elmo_folder + '/output/operands/operands{}.txt'.format(num_str)
  158. trace_filename = self.elmo_folder + '/output/traces/trace0000{}.trc'.format(num_trace)
  159. is_multiple = (type(num_line) is list)
  160. if not is_multiple:
  161. num_line = [num_line]
  162. output = [{}]*len(num_line)
  163. with open(operands_filename, 'r') as _file:
  164. lines = _file.readlines()
  165. for i, num in enumerate(num_line):
  166. line = lines[num].split()
  167. data = list(map(int, line[0:7]))
  168. output[i]['previous'] = data[0:2]
  169. output[i]['current'] = data[2:4]
  170. output[i]['triplet'] = data[4:7]
  171. output[i]['other'] = list(map(float, line[7:]))
  172. with open(trace_filename, 'r') as _file:
  173. lines = _file.readlines()
  174. for i, num in enumerate(num_line):
  175. line = lines[num]
  176. output[i]['power'] = float(line)
  177. return output if is_multiple else output[0]