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

  1. import os, shutil
  2. import re
  3. import inspect
  4. import subprocess
  5. def search_simulations(repository, criteria=lambda x:True, search_also_in_module=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. if search_also_in_module:
  34. module_path = os.path.dirname(os.path.abspath(__file__))
  35. module_projects = search_simulations(module_path+'/projects', criteria=lambda x:True, search_also_in_module=False)
  36. for key, project in module_projects.items():
  37. if key not in projects:
  38. projects[key] = project
  39. return projects
  40. class SimulationNotFoundError(Exception):
  41. pass
  42. class TooManySimulationsError(Exception):
  43. pass
  44. def get_simulation(repository, classname=None):
  45. """ Get a simulation class in the 'repository' with the specific 'classname' """
  46. criteria = lambda x: True
  47. if classname is not None:
  48. criteria = lambda x: x.__name__ == classname.strip()
  49. projects = search_simulations(repository, criteria)
  50. if len(projects) == 1:
  51. return list(projects.values())[0]
  52. elif len(projects) < 1:
  53. raise SimulationNotFoundError()
  54. else:
  55. raise TooManySimulationsError()
  56. def get_simulation_via_classname(classname):
  57. return get_simulation('.', classname)
  58. def create_simulation(repository, classname, verbose=True):
  59. """ Create a simulation class """
  60. try:
  61. os.makedirs(repository, exist_ok=False)
  62. except FileExistsError as err:
  63. raise FileExistsError('Error, a project with this repository already exists!') from err
  64. module_path = os.path.dirname(os.path.abspath(__file__))
  65. elmo_path = module_path+'/elmo'
  66. template_path = module_path+'/templates'
  67. project_path = repository
  68. ### Add contents in the project
  69. files_from_ELMO = [
  70. 'Examples/elmoasmfunctions.o',
  71. 'Examples/elmoasmfunctions.s',
  72. 'Examples/elmoasmfunctionsdef.h',
  73. 'Examples/DPATraces/MBedAES/vector.o',
  74. ]
  75. files_from_templates = [
  76. 'elmoasmfunctionsdef-extension.h',
  77. 'Makefile',
  78. 'project.c'
  79. ]
  80. for filename in files_from_ELMO:
  81. shutil.copy(elmo_path+'/'+filename, project_path)
  82. for filename in files_from_templates:
  83. shutil.copy(template_path+'/'+filename, project_path)
  84. shutil.copy(elmo_path+'/'+'Examples/DPATraces/MBedAES/MBedAES.ld', project_path+'/'+'project.ld')
  85. ### Create the project class
  86. with open(template_path+'/projectclass.py') as _source:
  87. code = ''.join(_source.readlines())
  88. code = code.replace('{{PROJECTCLASSNAME}}', classname)
  89. with open(project_path+'/'+'projectclass.py', 'w') as _dest:
  90. _dest.write(code)
  91. def execute_simulation(project, data=None):
  92. """ Execute a simulation with 'data' """
  93. # Make the compilation
  94. if False:
  95. print('Compiling binary...')
  96. # Adapt the project source
  97. with open('binaries/Frodo/frodo-base.c', 'r') as _src_file:
  98. content = _src_file.read()
  99. with open('binaries/Frodo/frodo.c', 'w') as _dst_file:
  100. _dst_file.write(content.replace('%NEED_TO_FILL%', str(n)))
  101. # Compile the project
  102. make_directory = 'projects/{}/{}'.format(project.get_project_directory(), project.get_make_directory())
  103. process = subprocess.Popen('make', shell=True, cwd=make_directory, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  104. output, error = process.communicate()
  105. if error and ('error' in error.decode('latin-1')):
  106. print("Error to compile")
  107. print(error)
  108. raise Exception()
  109. # Save last compilation data
  110. global_variables[project_name] = {
  111. 'last_n': n,
  112. }
  113. # Generate the trace by launching ELMO
  114. command = './elmo {}/{}'.format(
  115. project.get_project_directory(),
  116. project.get_binary()
  117. )
  118. cwd = os.path.dirname(os.path.abspath(__file__))+'/elmo'
  119. process = subprocess.Popen(command, shell=True, cwd=cwd, executable='/bin/bash', stdout=subprocess.PIPE)
  120. output, error = process.communicate()
  121. # Return results
  122. return (
  123. output.decode('latin-1') if output else None,
  124. error.decode('latin-1') if error else None,
  125. )