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.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

manage.py 6.2KB

  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. }