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 7.6KB

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