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个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import os, shutil
  2. import re
  3. import inspect
  4. import subprocess
  5. def search_simulations_in_repository(repository, criteria=lambda x:True):
  6. """ To search simulation classes in the 'repository' verifying the 'criteria' """
  7. projects = {}
  8. from .project_base import SimulationProject, write
  9. for root, repositories, files in os.walk(repository):
  10. for filename in files:
  11. if re.fullmatch(r'.*project.*\.py', filename):
  12. # Encapsulation the project
  13. complete_filename = root+'/'+filename
  14. globals = {
  15. #'__builtins__': {'__build_class__': __build_class__},
  16. 'SimulationProject': SimulationProject,
  17. 'write': write,
  18. }
  19. locals = {}
  20. # Read the project code
  21. with open(complete_filename, 'r') as _file:
  22. project = '\n'.join(_file.readlines())
  23. exec(project, globals, locals)
  24. # Extract the simulations
  25. for key, obj in locals.items():
  26. if inspect.isclass(obj) and issubclass(obj, SimulationProject):
  27. if criteria(obj):
  28. if key in projects:
  29. print('Warning! Multiplie simulation with the same name. Simulation ignored: {} in {}'.format(key, complete_filename[len(repository)+1:]))
  30. else:
  31. obj.set_project_directory(os.path.abspath(root))
  32. projects[key] = obj
  33. return projects
  34. def search_simulations_in_module(criteria=lambda x:True):
  35. module_path = os.path.dirname(os.path.abspath(__file__))
  36. projects_path = module_path+'/projects'
  37. return search_simulations_in_repository(projects_path, criteria)
  38. def search_simulations(repository, criteria=lambda x:True):
  39. projects = search_simulations_in_repository(repository, criteria)
  40. module_projects = search_simulations_in_module(criteria)
  41. for key, project in module_projects.items():
  42. if key not in projects:
  43. projects[key] = project
  44. return projects
  45. class SimulationNotFoundError(Exception):
  46. pass
  47. class TooManySimulationsError(Exception):
  48. pass
  49. def get_simulation(repository, classname=None):
  50. """ Get a simulation class in the 'repository' with the specific 'classname' """
  51. criteria = lambda x: True
  52. if classname is not None:
  53. criteria = lambda x: x.__name__ == classname.strip()
  54. projects = search_simulations(repository, criteria)
  55. if len(projects) == 1:
  56. return list(projects.values())[0]
  57. elif len(projects) < 1:
  58. raise SimulationNotFoundError()
  59. else:
  60. raise TooManySimulationsError()
  61. def get_simulation_via_classname(classname):
  62. return get_simulation('.', classname)
  63. def create_simulation(repository, classname):
  64. """ Create a simulation class """
  65. try:
  66. os.makedirs(repository, exist_ok=False)
  67. except FileExistsError as err:
  68. raise FileExistsError('Error, a project with this repository already exists!') from err
  69. module_path = os.path.dirname(os.path.abspath(__file__))
  70. elmo_path = module_path+'/elmo'
  71. template_path = module_path+'/templates'
  72. project_path = repository
  73. ### Add contents in the project
  74. files_from_ELMO = [
  75. 'Examples/elmoasmfunctions.o',
  76. 'Examples/elmoasmfunctions.s',
  77. 'Examples/elmoasmfunctionsdef.h',
  78. 'Examples/DPATraces/MBedAES/vector.o',
  79. ]
  80. files_from_templates = [
  81. 'elmoasmfunctionsdef-extension.h',
  82. 'Makefile',
  83. 'project.c'
  84. ]
  85. for filename in files_from_ELMO:
  86. shutil.copy(elmo_path+'/'+filename, project_path)
  87. for filename in files_from_templates:
  88. shutil.copy(template_path+'/'+filename, project_path)
  89. shutil.copy(elmo_path+'/'+'Examples/DPATraces/MBedAES/MBedAES.ld', project_path+'/'+'project.ld')
  90. ### Create the project class
  91. with open(template_path+'/projectclass.py') as _source:
  92. code = ''.join(_source.readlines())
  93. code = code.replace('{{PROJECTCLASSNAME}}', classname)
  94. with open(project_path+'/'+'projectclass.py', 'w') as _dest:
  95. _dest.write(code)
  96. return os.path.abspath(project_path)
  97. def execute_simulation(project, data=None):
  98. """ Execute a simulation with 'data' """
  99. # Make the compilation
  100. if False:
  101. print('Compiling binary...')
  102. # Adapt the project source
  103. with open('binaries/Frodo/frodo-base.c', 'r') as _src_file:
  104. content = _src_file.read()
  105. with open('binaries/Frodo/frodo.c', 'w') as _dst_file:
  106. _dst_file.write(content.replace('%NEED_TO_FILL%', str(n)))
  107. # Compile the project
  108. make_directory = 'projects/{}/{}'.format(project.get_project_directory(), project.get_make_directory())
  109. process = subprocess.Popen('make', shell=True, cwd=make_directory, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  110. output, error = process.communicate()
  111. if error and ('error' in error.decode('latin-1')):
  112. print("Error to compile")
  113. print(error)
  114. raise Exception()
  115. # Save last compilation data
  116. global_variables[project_name] = {
  117. 'last_n': n,
  118. }
  119. # Generate the trace by launching ELMO
  120. command = './elmo "{}/{}"'.format(
  121. project.get_project_directory(),
  122. project.get_binary()
  123. )
  124. cwd = os.path.dirname(os.path.abspath(__file__))+'/elmo'
  125. process = subprocess.Popen(command, shell=True, cwd=cwd, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  126. output, error = process.communicate()
  127. output = output.decode('latin-1') if output else None
  128. error = error.decode('latin-1') if error else None
  129. nb_traces = output.count('TRACE NO')
  130. # Return results
  131. return {
  132. 'output': output,
  133. 'error': error,
  134. 'nb_traces': nb_traces,
  135. }