def testReporter(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check the synthesis reporter self.assertTrue( callable(project.get_reporter()) )
def testReporter(self): project = Project() project.add_config('reporter', self.reporter_path) # Check the synthesis reporter self.assertTrue( callable(project.get_reporter()) )
def test_reporter(self): project = Project() project.load_project(self.project_path) # Check the synthesis reporter self.assertTrue( callable(project.get_reporter()) )
def test_reporter(self): project = Project() project.add_config('reporter', self.reporter_path) # Check the synthesis reporter self.assertTrue( callable(project.get_reporter()) )
def test_generics(self): project = Project() project.load_project(self.project_path) # Check the synthesis generics self.assertDictEqual( self.project_generics, project.get_generics(), )
def testProjectPart(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check project part self.assertEqual( self.project_part, project.get_fpga_part() )
def test_simulation_Tool_name(self): project = Project() project.load_project(self.project_path) # Check simulation tool name self.assertEqual( self.simulation_tool_name, project.get_simulation_tool_name() )
def test_synthesis_tool_name(self): project = Project() project.load_project(self.project_path) # Check synthesis tool name self.assertEqual( self.synthesis_tool_name, project.get_synthesis_tool_name() )
def testSynthesisDirectory(self): project = Project() project.load_project(self.project_path) abs_path = os.path.join( os.path.abspath(self.root), self.synthesis_directory ) self.assertEqual(project.get_synthesis_directory(), abs_path)
def test_project_part(self): project = Project() project.load_project(self.project_path) # Check project part self.assertEqual( self.project_part, project.get_fpga_part() )
def testGenerics(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check the synthesis generics self.assertDictEqual( self.project_generics, project.get_generics(), )
def test_reporter(self): """If the user incorrectly defines a reporter it should fail gracefully and return None.""" project = Project() project.add_config('reporter', self.reporter_path) self.assertIsNone( project.get_reporter() )
def testPreprocessor(self): project = Project() XmlProjectParser.load_project(self.project_path, project) files = project.get_files() preprocessors = list( filter(lambda x: os.path.exists(x.preprocessor), files)) self.assertTrue(len(preprocessors) > 0) project.run_preprocessors()
def testSimulationToolName(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check simulation tool name self.assertEqual( self.simulation_tool_name, project.get_simulation_tool_name() )
def testSynthesisToolName(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check synthesis tool name self.assertEqual( self.synthesis_tool_name, project.get_synthesis_tool_name() )
def testProjectConstraints(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check the project constraints self.assertEqual( self.project_constraints, [os.path.basename(c.path) for c in project.get_constraints()], )
def testSimulationDirectory(self): project = Project() XmlProjectParser.load_project(self.project_path, project) abs_path = os.path.join( os.path.abspath(self.root), self.simulation_directory ) self.assertEqual(project.get_simulation_directory(), abs_path)
def test_simulation_directory(self): project = Project() project.load_project(self.project_path) abs_path = os.path.join( os.path.abspath(self.root), self.simulation_directory ) self.assertEqual(project.get_simulation_directory(), abs_path)
def testReporter(self): """If the user incorrectly defines a reporter it should fail gracefully and return None.""" project = Project() project.add_config('reporter', self.reporter_path) self.assertIsNone( project.get_reporter() )
def __init__(self, project=None): super(CommandLine, self).__init__() prj = '' if project is None: try: self.project = Project() projects = self.locateProjects() if len(projects) > 0: prj = ( 'Type ' + term.colourise( '\'load_project <path>\'', fg='yellow' ) + ' to load a project.\n' ) prj += ( 'The current directory contains ' + 'the following projects:\n' ) prj += term.colourise( '\n'.join('\t{0}: {1}'.format( idx+1, path ) for idx, path in enumerate(projects)), fg='yellow' ) self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) except exceptions.ProjectFileException: log.error( 'The project file contains errors, ' + 'fix them and then type \'reload\'' ) except: log.error( 'The software has to terminate due to the following error:' ) log.error(traceback.format_exc()) sys.exit(1) else: self.project = project prj = ( 'Project contains ' + term.colourise( str(len(self.project.get_files())), fg='yellow' ) + ' file(s) and ' + term.colourise( str(len(self.project.get_tests())), fg='yellow' ) + ' test(s).' ) self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) self.test_set = set()
def setUpClass(cls): """ The *setUpClass* method prepares the ChipTools simulation environment if it has not already been loaded. If this test case is loaded via the ChipTools Project API it will be initialised via a call to the *load_environment* method, which pulls the simulation environment information from the parent Project instance. If this test case is loaded via an external tool such as Nosetests the setUpClass method will attempt to load the project file pointed to by the project path stored in the *project* attribute. When you create your test case you can specify this attribute in your test class to allow an external runner like Nosetests to call your test cases. If the environment was not already initialised by ChipTools and a valid project file path is not stored in the *project* attribute, this method will raise an EnvironmentError and cause your test to fail. This method overloads the unittest.TestCase.setUpClass classmethod, which is called once when a TestCase class is instanced. """ log.debug('setUpClass of {0} called...'.format(cls)) # Check to see if the environment that this class is initialised for # matches the project path (if specified). If the environment was # initialised by the ChipTools internal loaded then skip these steps. if cls._environment_type != 'chiptools': if cls._loaded_path != cls.project: project = Project() project.load_project(cls.project) # Using external test runner (such as Nosetests) to execute this # test. The test environment therefore needs to be loaded from # the Project instance: simulator, root, libs = cls.get_environment(project) cls._loaded_path = cls.project cls._simulator = simulator cls._simulation_root = root cls._simulation_libraries = libs cls._environment_type = 'external' # Compile the design if required (simulators with caching will # perform this step once). cls._simulator.compile_project( includes=cls._simulation_libraries ) log.debug( '...finished initialising environment for {0}'.format(cls) ) if cls._environment_type is None: raise EnvironmentError( 'The simulation environment for this TestCase is not ' + 'initialised so the test cases cannot be executed. ' + 'If you are running this test directly ensure that ' + 'the TestCase class has a "project" attribute which ' + 'holds a path to a valid ChipTools project file.' )
def testPreprocessor(self): project = Project() XmlProjectParser.load_project(self.project_path, project) files = project.get_files() preprocessors = list( filter( lambda x: os.path.exists(x.preprocessor), files ) ) self.assertTrue(len(preprocessors) > 0) project.run_preprocessors()
def test_preprocessor(self): project = Project() project.load_project(self.project_path) files = project.get_files() preprocessors = list( filter( lambda x: os.path.exists(x.preprocessor), files ) ) self.assertTrue(len(preprocessors) > 0) self.run_and_check_preprocessors(project)
def test_preprocessor(self): project = Project() for libname in self.project_structure.keys(): files = self.project_structure[libname] project.add_files( root=os.path.join(self.root, libname), library=libname, pattern='*.vhd', preprocessor=self.preprocessor_path ) self.run_and_check_preprocessors(project)
def setUpClass(cls): """ The *setUpClass* method prepares the ChipTools simulation environment if it has not already been loaded. If this test case is loaded via the ChipTools Project API it will be initialised via a call to the *load_environment* method, which pulls the simulation environment information from the parent Project instance. If this test case is loaded via an external tool such as Nosetests the setUpClass method will attempt to load the project file pointed to by the project path stored in the *project* attribute. When you create your test case you can specify this attribute in your test class to allow an external runner like Nosetests to call your test cases. If the environment was not already initialised by ChipTools and a valid project file path is not stored in the *project* attribute, this method will raise an EnvironmentError and cause your test to fail. This method overloads the unittest.TestCase.setUpClass classmethod, which is called once when a TestCase class is instanced. """ log.debug("setUpClass of {0} called...".format(cls)) # Check to see if the environment that this class is initialised for # matches the project path (if specified). If the environment was # initialised by the ChipTools internal loaded then skip these steps. if cls._environment_type != "chiptools": if cls._loaded_path != cls.project: project = Project() project.load_project(cls.project) # Using external test runner (such as Nosetests) to execute this # test. The test environment therefore needs to be loaded from # the Project instance: simulator, root, libs = cls.get_environment(project) cls._loaded_path = cls.project cls._simulator = simulator cls._simulation_root = root cls._simulation_libraries = libs cls._environment_type = "external" # Compile the design if required (simulators with caching will # perform this step once). cls._simulator.compile_project(includes=cls._simulation_libraries) log.debug("...finished initialising environment for {0}".format(cls)) if cls._environment_type is None: raise EnvironmentError( "The simulation environment for this TestCase is not " + "initialised so the test cases cannot be executed. " + "If you are running this test directly ensure that " + 'the TestCase class has a "project" attribute which ' + "holds a path to a valid ChipTools project file." )
def testFileSet(self): project = Project() expected_files = [] for libname in self.project_structure.keys(): files = self.project_structure[libname] for path in files: expected_files.append(os.path.basename(path)) project.add_file(path, libname) self.assertEqual( sorted(expected_files), sorted([os.path.basename(f.path) for f in project.get_files()]), )
def testFileSet(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check the file set loaded from the project expected_files = [] for libname in self.project_structure.keys(): files = self.project_structure[libname] for path in files: expected_files.append(os.path.basename(path)) self.assertEqual( sorted(expected_files), sorted([os.path.basename(f.path) for f in project.get_files()]), )
def test_preprocessor(self): """Invalid preprocessors should not be executed on files.""" project = Project() project.load_project(self.project_path) files = project.get_files() preprocessors = list( filter( lambda x: os.path.exists(x.preprocessor), files ) ) self.assertTrue(len(preprocessors) > 0) project.run_preprocessors() regex = re.compile('library ieee;') for libname in self.project_structure.keys(): files = self.project_structure[libname] for path in files: path = os.path.join(self.root, libname, path) with open(path, 'r') as f: data = f.readlines() match = regex.match(data[0]) self.assertIsNotNone( match, msg='File {0} was not correctly preserved.'.format( path ) )
def test_constraints(self): project = Project() for constraints in self.project_constraints: project.add_constraints(constraints, flow='dummy_flow') constraints = project.get_constraints() self.assertEquals( len(constraints), len(self.project_constraints), msg='Incorrect number of constraints added to project.' ) self.assertTrue( len(constraints) > 0, msg='Not correctly tested as no constraints are present.' ) for idx in range(len(constraints)): self.assertEquals( constraints[idx].path, os.path.abspath(self.project_constraints[idx]), msg='Constraints path was incorrectly processed.' )
def locateProjects(self): """ Return a list of projects found in the current path. """ projects = [] logging.getLogger("chiptools").setLevel(logging.CRITICAL) for filePath in os.listdir(os.getcwd()): if filePath.endswith('.xml'): try: tempProject = Project() # Load the XML file XmlProjectParser.load_project(filePath, tempProject) # If the project contains files we can add it to our list files = tempProject.get_files() files = files if files is not None else [] if len(files) != 0: projects.append(filePath) except: pass logging.getLogger("chiptools").setLevel(logging.INFO) return projects
def locateProjects(self): """ Return a list of projects found in the current path. """ projects = [] logging.getLogger("chiptools").setLevel( logging.CRITICAL ) for filePath in os.listdir(os.getcwd()): if filePath.endswith('.xml'): try: tempProject = Project() # Load the XML file XmlProjectParser.load_project(filePath, tempProject) # If the project contains files we can add it to our list files = tempProject.get_files() files = files if files is not None else [] if len(files) != 0: projects.append(filePath) except: pass logging.getLogger("chiptools").setLevel(logging.INFO) return projects
def testAddAll(self): project = Project() expected_files = [] expected_libs = [] for libname in self.project_structure.keys(): files = self.project_structure[libname] expected_libs.append(libname) project.add_files( root=os.path.join(self.root, libname), library=libname, pattern='*.vhd' ) for path in files: expected_files.append(os.path.basename(path)) self.assertEqual( sorted(expected_files), sorted([os.path.basename(f.path) for f in project.get_files()]), ) self.assertEqual( sorted(expected_libs), sorted(list(project.get_libraries()),) )
def testAddAll(self): project = Project() expected_files = [] expected_libs = [] for libname in self.project_structure.keys(): files = self.project_structure[libname] expected_libs.append(libname) project.add_files(root=os.path.join(self.root, libname), library=libname, pattern='*.vhd') for path in files: expected_files.append(os.path.basename(path)) self.assertEqual( sorted(expected_files), sorted([os.path.basename(f.path) for f in project.get_files()]), ) self.assertEqual(sorted(expected_libs), sorted(list(project.get_libraries()), ))
def test_project_load(self): project = Project() project.load_project(self.project_path)
def testProjectLoad(self): project = Project() XmlProjectParser.load_project(self.project_path, project)
""" This script provides an example of how to use the ChipTools scripted flow. """ try: # Import the Project class from chiptools.core.project from chiptools.core.project import Project except ImportError: import sys print("ChipTools is not installed on your system.") sys.exit(1) # Create a new Project project = Project() # Configure project, you may wish to edit some of these settings depending # on which simulation/synthesis tools are installed on your system. config = { 'simulation_directory': 'simulation', 'synthesis_directory': 'synthesis', 'simulator': 'modelsim', 'synthesiser': 'ise', 'part': 'xc7a100tcsg324-1', } # The Project class provides an add_config or add_config_dict method. We use # the add_config_dict method here to load the config dictionary, you can set # individual configuration items using add_config. project.add_config_dict(**config) # Some unit tests have been written for the max_hold component and stored in # max_hold_tests.py. The Project class provides an 'add_unittest' method for # adding unit tests to the project, it expects a path to the unit test file.
def testSimulationToolName(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check simulation tool name self.assertEqual(self.simulation_tool_name, project.get_simulation_tool_name())
def testSynthesisToolName(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check synthesis tool name self.assertEqual(self.synthesis_tool_name, project.get_synthesis_tool_name())
""" This script provides an example of how to use the ChipTools scripted flow. """ import os try: # Import the Project class from chiptools.core.project from chiptools.core.project import Project except ImportError: import sys print("ChipTools is not installed on your system.") sys.exit(1) project_root = os.path.dirname(__file__) # Create a new Project project = Project(root=project_root) # Configure project, you may wish to edit some of these settings depending # on which simulation/synthesis tools are installed on your system. config = { 'simulation_directory': 'simulation', 'synthesis_directory': 'synthesis', 'simulator': 'vivado', 'synthesiser': 'vivado', 'part': 'xc7z030sbg485-2', } # The Project class provides an add_config or add_config_dict method. We use # the add_config_dict method here to load the config dictionary, you can set # individual configuration items using add_config. project.add_config_dict(**config)
def testReporter(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check the synthesis reporter self.assertTrue(callable(project.get_reporter()))
class CommandLine(cmd.Cmd): def __init__(self, project=None): super(CommandLine, self).__init__() prj = '' if project is None: try: self.project = Project() projects = self.locateProjects() if len(projects) > 0: prj = ('Type ' + term.colourise('\'load_project <path>\'', fg='yellow') + ' to load a project.\n') prj += ('The current directory contains ' + 'the following projects:\n') prj += term.colourise('\n'.join( '\t{0}: {1}'.format(idx + 1, path) for idx, path in enumerate(projects)), fg='yellow') self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) except exceptions.ProjectFileException: log.error('The project file contains errors, ' + 'fix them and then type \'reload\'') except: log.error( 'The software has to terminate due to the following error:' ) log.error(traceback.format_exc()) sys.exit(1) else: self.project = project prj = ('Project contains ' + term.colourise(str(len(self.project.get_files())), fg='yellow') + ' file(s) and ' + term.colourise(str(len(self.project.get_tests())), fg='yellow') + ' test(s).') self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) self.test_set = set() def locateProjects(self): """ Return a list of projects found in the current path. """ projects = [] logging.getLogger("chiptools").setLevel(logging.CRITICAL) for filePath in os.listdir(os.getcwd()): if filePath.endswith('.xml'): try: tempProject = Project() # Load the XML file XmlProjectParser.load_project(filePath, tempProject) # If the project contains files we can add it to our list files = tempProject.get_files() files = files if files is not None else [] if len(files) != 0: projects.append(filePath) except: pass logging.getLogger("chiptools").setLevel(logging.INFO) return projects @wraps_do_commands def do_load_project(self, path): """Load the given project XML file: load_project <path_to_project>""" path = os.path.abspath(path) if os.path.exists(path) and os.path.isfile(path): try: log.info( 'Loading {0} in current working directory: {1}'.format( path, os.getcwd())) XmlProjectParser.load_project(path, self.project) except: log.error('The project could not be loaded due to an error:') log.error(traceback.format_exc()) else: log.error('File not found: {0}'.format(path)) @wraps_do_commands def do_exit(self, command): return True @wraps_do_commands def do_compile(self, command): self.project.compile() @wraps_do_commands def do_show_synthesis_fileset(self, command): """Print out the synthesis file set""" items = self.project.get_synthesis_fileset().items() if len(items) == 0: log.info('There are no synthesisable files loaded.') return for libName, fileList in items: log.info('Library: ' + libName) for file in fileList: log.info('\t\t' + file.path) @wraps_do_commands def do_synthesise(self, command): """Synthesise the design using the chosen synthesis tool and report any errors Example: (Cmd) simulate my_library.my_entity""" command_elems = command.split(' ') fpga_part = None if len(command_elems) == 3: target, tool_name, fpga_part = command_elems elif len(command_elems) == 2: target, tool_name = command_elems else: target = command_elems[0] tool_name = None try: library, entity = target.split('.') except ValueError: log.error('Command \"' + command + '\" not understood.') log.error( "Please specify a library and entity.\n" + "Example: (Cmd) synthesise my_library.my_entity [tool_name]") return self.project.synthesise(library, entity, tool_name=tool_name, fpga_part=fpga_part) @wraps_do_commands def do_run_preprocessors(self, command): """For each project file in the design run any associated preprocessors. You can use this command to test that a preprocessor is running on your file correctly. Preprocessors are called automatically when you run synthesis""" log.info('Running preprocessors...') self.project.run_preprocessors() log.info('...done') @wraps_do_commands def do_simulate(self, command): """Compile the given entity in the given library using the chosen simulator and invoke the simulator GUI. Example: (Cmd) simulate my_library.my_entity""" command_elems = command.split(' ') if len(command_elems) == 2: target, tool_name = command_elems else: target = command_elems[0] tool_name = None try: library, entity = target.split('.') except ValueError: log.error('Command \"' + command + '\" not understood.') log.error( "Please specify a library and entity.\n" + "Example: (Cmd) simulate my_library.my_entity [tool_name]") return self.project.simulate(library, entity, gui=True, tool_name=tool_name) @wraps_do_commands def do_clean(self, command): """Clear the file cache""" # Delete libraries from the simulation area simpath = self.project.get_simulation_directory() if simpath is None: log.error('No simulation path is set, aborting operation.') return log.info('Cleaning simulation folder: ' + simpath) for tool_name in self.project.cache.get_tool_names(): for libname in self.project.cache.get_libraries(tool_name): path = os.path.join(simpath, libname) if os.path.exists(path): log.info('Removing ' + path) shutil.rmtree(path) log.info('...done') self.project.cache.initialise_cache() @wraps_do_commands def do_pwd(self, command): print( term.colourise('Working directory: ', fg='yellow') + term.colourise('{0}', fg='green').format(os.getcwd())) @wraps_do_commands def do_plugins(self, command): simulators = self.project.get_available_simulators() synthesisers = self.project.get_available_synthesisers() for i, plugin_registry in enumerate([simulators, synthesisers]): print(term.yellow(['Simulator Plugins:', 'Synthesis Plugins:'][i])) for name, inst in plugin_registry.items(): plugin_path = sys.modules[inst.__module__].__file__ plugin_file = os.path.basename(plugin_path) print(SEP * 1 + term.darkgray(plugin_file) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format('Plugin Path', term.green(plugin_path)) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format('Name', term.green(str(name))) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format('Tool Path', [ term.red('(not found) ' + str(inst.path)), term.green(str(inst.path)) ][inst.installed])) @wraps_do_commands def do_show_config(self, command): """Print out the project settings""" available_simulator_string = '' for name, inst in self.project.get_available_simulators().items(): available_simulator_string += ( SEP * 2 + '{:<15}: ' + ['(not found) ' + term.red('{:<35}'), term.green('{:<35}')][inst.installed] + '\n').format( name, inst.path) available_synthesiser_string = '' for name, inst in self.project.get_available_synthesisers().items(): available_synthesiser_string += ( SEP * 2 + '{:<15}: ' + ['(not found) ' + term.red('{:<35}'), term.green('{:<35}')][inst.installed] + '\n').format( name, inst.path) msg = ( '\n' + term.yellow(term.bold('System Configuration: ')) + term.green('%(options)s') + '\n' + term.darkgray(SEP + 'Working directory:\n') + SEP * 2 + term.green('%(working_directory)s') + '\n' + term.darkgray(SEP + 'Available simulators:\n') + available_simulator_string + term.darkgray(SEP + 'Available synthesisers:\n') + available_synthesiser_string + term.darkgray(SEP + 'Simulation libraries:\n') + ''.join( (SEP * 2 + '{:<15}: ' + term.green('{:<35}') + '\n').format(k, v) for k, v in (self.project.get_simulator_library_dependencies().items())) + '\n' + term.yellow(term.bold('Project Configuration: ')) + term.green('%(project)s') + '\n' + term.darkgray(SEP + 'Simulation directory set to:\n') + SEP * 2 + term.green('%(simulation_directory)s') + '\n' + term.darkgray(SEP + 'Using the simulation tool:\n') + SEP * 2 + term.green('%(simulation_tool_name)s') + '\n' + term.darkgray(SEP + 'Synthesis directory set to:\n') + SEP * 2 + term.green('%(synthesis_directory)s') + '\n' + term.darkgray(SEP + 'Using the synthesis tool:\n') + SEP * 2 + term.green('%(synthesis_tool_name)s') + '\n' + term.darkgray(SEP + 'Targeting FPGA part:\n') + SEP * 2 + term.green('%(fpga_part)s') + '\n' + term.darkgray(SEP + 'Using synthesis generic binding:\n') + SEP * 2 + term.green('%(synthesis_generics)s') + '\n' + term.darkgray(SEP + 'Modelsim Specific Arguments:\n') + SEP * 2 + 'vsim: ' + term.green('%(modelsim_vsim_args)s') + '\n') print( msg % dict(working_directory=os.getcwd(), options=self.project.get_system_config_path(), simulation_directory=self.project.get_simulation_directory(), simulation_tool_name=self.project.get_simulation_tool_name(), synthesis_directory=self.project.get_synthesis_directory(), synthesis_tool_name=self.project.get_synthesis_tool_name(), fpga_part=self.project.get_fpga_part(), modelsim_vsim_args=self.project.get_tool_arguments( 'modelsim', 'simulate'), project='', synthesis_generics=''.join( str(k) + ':' + str(v) + ', ' for k, v in self.project.get_generics().items()))) @wraps_do_commands def do_show_tests(self, command): """ Show the tests available in the current project. """ tests = self.project.get_tests() if len(tests) == 0: log.info('There are no tests available.') return testUniqueId = 0 for file_object in tests: file_name = os.path.basename(file_object.path) print(term.yellow(file_name)) for test_group in file_object.testsuite: for testId, test in enumerate(test_group): if testId == 0: print(SEP + term.green(str(test.__class__.__name__))) doc = test.shortDescription() if doc is None: doc = term.darkred('No description') if testUniqueId in self.test_set: msg = SEP * 2 + '[' + term.blue( 'ID ' + str(testUniqueId) + ' ' + test.id().split('.')[-1]) + ']' else: msg = SEP * 2 + term.lightgray('ID ' + str( testUniqueId) + ' ' + test.id().split('.')[-1]) print(msg) print( term.darkgray( textwrap.fill( doc, width=80, initial_indent=SEP * 2, subsequent_indent=SEP * 2, ))) testUniqueId += 1 def show_test_selection(self): """ Show the currently selected tests in the current project. Add or remove tests using the add_tests and remove_tests commands respectively. """ ids_list = list(self.test_set) tests = [] for file_object in self.project.get_tests(): file_name = os.path.basename(file_object.path) print(term.yellow(file_name)) for test_group in file_object.testsuite: for testId, test in enumerate(test_group): if testId == 0: groupName = str(test.__class__.__name__) testName = test.id().split('.')[-1] tests.append((file_name, groupName, testName, test)) # Filter out any invalid indices ids_list = list(filter(lambda x: x < len(tests), ids_list)) for idx, (fileName, groupName, testName, test) in enumerate([tests[idx] for idx in ids_list]): print('{:<5}'.format(str(ids_list[idx]) + ':') + '[' + term.yellow(fileName) + ']' + '[' + term.green(groupName) + ']' + '[' + term.blue(testName) + ']') @wraps_do_commands def do_add_tests(self, command): """ Add the given tests to the test suite. Tests should be supplied as comma separated numbers or numeric ranges, for example: add_tests 1-3, 5, 6, 7 Would add tests 1, 2, 3, 5, 6, 7 to the test suite. You can check which tests are available by issuing the show_tests command or remove tests that have been added to the suite by issuing the remove_tests command. """ try: ids = utils.parseRange(command) except ValueError: log.error('Invalid test range specified: ' + command) return for testId in ids: self.test_set.add(testId) self.show_test_selection() @wraps_do_commands def do_remove_tests(self, command): """ Remove the given tests from the test suite. Tests should be supplied as comma separated numbers or numeric ranges, for example: remove_tests 1-3, 5, 6, 7 Would remove tests 1, 2, 3, 5, 6, 7 from the test suite. You can check which tests are available by issuing the show_tests command or add tests by issuing the add_tests command. """ try: ids = utils.parseRange(command) except ValueError: log.error('Invalid test range specified: ' + command) return for testId in ids: try: self.test_set.remove(testId) except KeyError: pass self.show_test_selection() @wraps_do_commands def do_run_tests(self, command): """ Run the tests that were selected via the add_tests command and report the results. """ if len(command) > 0: tool_name = command else: tool_name = None self.show_test_selection() self.project.run_tests(self.test_set, tool_name=tool_name)
class CommandLine(cmd.Cmd): def __init__(self, project=None): super(CommandLine, self).__init__() prj = '' if project is None: try: self.project = Project() projects = self.locateProjects() if len(projects) > 0: prj = ( 'Type ' + term.colourise( '\'load_project <path>\'', fg='yellow' ) + ' to load a project.\n' ) prj += ( 'The current directory contains ' + 'the following projects:\n' ) prj += term.colourise( '\n'.join('\t{0}: {1}'.format( idx+1, path ) for idx, path in enumerate(projects)), fg='yellow' ) self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) except exceptions.ProjectFileException: log.error( 'The project file contains errors, ' + 'fix them and then type \'reload\'' ) except: log.error( 'The software has to terminate due to the following error:' ) log.error(traceback.format_exc()) sys.exit(1) else: self.project = project prj = ( 'Project contains ' + term.colourise( str(len(self.project.get_files())), fg='yellow' ) + ' file(s) and ' + term.colourise( str(len(self.project.get_tests())), fg='yellow' ) + ' test(s).' ) self.intro = INTRO_TEMPL % dict( version=_version.__version__, projects=prj, ) self.test_set = set() def locateProjects(self): """ Return a list of projects found in the current path. """ projects = [] logging.getLogger("chiptools").setLevel( logging.CRITICAL ) for filePath in os.listdir(os.getcwd()): if filePath.endswith('.xml'): try: tempProject = Project() # Load the XML file XmlProjectParser.load_project(filePath, tempProject) # If the project contains files we can add it to our list files = tempProject.get_files() files = files if files is not None else [] if len(files) != 0: projects.append(filePath) except: pass logging.getLogger("chiptools").setLevel(logging.INFO) return projects @wraps_do_commands def do_load_project(self, path): """Load the given project XML file: load_project <path_to_project>""" path = os.path.abspath(path) if os.path.exists(path) and os.path.isfile(path): try: log.info( 'Loading {0} in current working directory: {1}'.format( path, os.getcwd() ) ) XmlProjectParser.load_project(path, self.project) except: log.error('The project could not be loaded due to an error:') log.error(traceback.format_exc()) else: log.error('File not found: {0}'.format(path)) @wraps_do_commands def do_exit(self, command): return True @wraps_do_commands def do_compile(self, command): self.project.compile() @wraps_do_commands def do_show_synthesis_fileset(self, command): """Print out the synthesis file set""" items = self.project.get_synthesis_fileset().items() if len(items) == 0: log.info('There are no synthesisable files loaded.') return for libName, fileList in items: log.info('Library: ' + libName) for file in fileList: log.info('\t\t' + file.path) @wraps_do_commands def do_synthesise(self, command): """Synthesise the design using the chosen synthesis tool and report any errors Example: (Cmd) simulate my_library.my_entity""" command_elems = command.split(' ') fpga_part = None if len(command_elems) == 3: target, tool_name, fpga_part = command_elems elif len(command_elems) == 2: target, tool_name = command_elems else: target = command_elems[0] tool_name = None try: library, entity = target.split('.') except ValueError: log.error('Command \"' + command + '\" not understood.') log.error( "Please specify a library and entity.\n" + "Example: (Cmd) synthesise my_library.my_entity [tool_name]" ) return self.project.synthesise( library, entity, tool_name=tool_name, fpga_part=fpga_part ) @wraps_do_commands def do_run_preprocessors(self, command): """For each project file in the design run any associated preprocessors. You can use this command to test that a preprocessor is running on your file correctly. Preprocessors are called automatically when you run synthesis""" log.info('Running preprocessors...') self.project.run_preprocessors() log.info('...done') @wraps_do_commands def do_simulate(self, command): """Compile the given entity in the given library using the chosen simulator and invoke the simulator GUI. Example: (Cmd) simulate my_library.my_entity""" command_elems = command.split(' ') if len(command_elems) == 2: target, tool_name = command_elems else: target = command_elems[0] tool_name = None try: library, entity = target.split('.') except ValueError: log.error('Command \"' + command + '\" not understood.') log.error( "Please specify a library and entity.\n" + "Example: (Cmd) simulate my_library.my_entity [tool_name]" ) return self.project.simulate(library, entity, gui=True, tool_name=tool_name) @wraps_do_commands def do_clean(self, command): """Clear the file cache""" # Delete libraries from the simulation area simpath = self.project.get_simulation_directory() if simpath is None: log.error('No simulation path is set, aborting operation.') return log.info('Cleaning simulation folder: ' + simpath) for tool_name in self.project.cache.get_tool_names(): for libname in self.project.cache.get_libraries(tool_name): path = os.path.join(simpath, libname) if os.path.exists(path): log.info('Removing ' + path) shutil.rmtree(path) log.info('...done') self.project.cache.initialise_cache() @wraps_do_commands def do_pwd(self, command): print( term.colourise('Working directory: ', fg='yellow') + term.colourise('{0}', fg='green').format(os.getcwd()) ) @wraps_do_commands def do_plugins(self, command): simulators = self.project.get_available_simulators() synthesisers = self.project.get_available_synthesisers() for i, plugin_registry in enumerate([simulators, synthesisers]): print(term.yellow(['Simulator Plugins:', 'Synthesis Plugins:'][i])) for name, inst in plugin_registry.items(): plugin_path = sys.modules[inst.__module__].__file__ plugin_file = os.path.basename(plugin_path) print( SEP * 1 + term.darkgray(plugin_file) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format( 'Plugin Path', term.green(plugin_path) ) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format( 'Name', term.green(str(name)) ) + '\n' + SEP * 2 + '{:<15}: {:<35}'.format( 'Tool Path', [ term.red('(not found) ' + str(inst.path)), term.green(str(inst.path)) ][inst.installed] ) ) @wraps_do_commands def do_show_config(self, command): """Print out the project settings""" available_simulator_string = '' for name, inst in self.project.get_available_simulators().items(): available_simulator_string += ( SEP * 2 + '{:<15}: ' + [ '(not found) ' + term.red('{:<35}'), term.green('{:<35}') ][inst.installed] + '\n' ).format(name, inst.path) available_synthesiser_string = '' for name, inst in self.project.get_available_synthesisers().items(): available_synthesiser_string += ( SEP * 2 + '{:<15}: ' + [ '(not found) ' + term.red('{:<35}'), term.green('{:<35}') ][inst.installed] + '\n' ).format(name, inst.path) msg = ( '\n' + term.yellow(term.bold('System Configuration: ')) + term.green('%(options)s') + '\n' + term.darkgray(SEP + 'Working directory:\n') + SEP * 2 + term.green('%(working_directory)s') + '\n' + term.darkgray(SEP + 'Available simulators:\n') + available_simulator_string + term.darkgray(SEP + 'Available synthesisers:\n') + available_synthesiser_string + term.darkgray(SEP + 'Simulation libraries:\n') + ''.join( (SEP * 2 + '{:<15}: ' + term.green('{:<35}') + '\n').format( k, v ) for k, v in ( self.project.get_simulator_library_dependencies().items() ) ) + '\n' + term.yellow(term.bold('Project Configuration: ')) + term.green('%(project)s') + '\n' + term.darkgray(SEP + 'Simulation directory set to:\n') + SEP * 2 + term.green('%(simulation_directory)s') + '\n' + term.darkgray(SEP + 'Using the simulation tool:\n') + SEP * 2 + term.green('%(simulation_tool_name)s') + '\n' + term.darkgray(SEP + 'Synthesis directory set to:\n') + SEP * 2 + term.green('%(synthesis_directory)s') + '\n' + term.darkgray(SEP + 'Using the synthesis tool:\n') + SEP * 2 + term.green('%(synthesis_tool_name)s') + '\n' + term.darkgray(SEP + 'Targeting FPGA part:\n') + SEP * 2 + term.green('%(fpga_part)s') + '\n' + term.darkgray(SEP + 'Using synthesis generic binding:\n') + SEP * 2 + term.green('%(synthesis_generics)s') + '\n' + term.darkgray(SEP + 'Modelsim Specific Arguments:\n') + SEP * 2 + 'vsim: ' + term.green('%(modelsim_vsim_args)s') + '\n' ) print(msg % dict( working_directory=os.getcwd(), options=self.project.get_system_config_path(), simulation_directory=self.project.get_simulation_directory(), simulation_tool_name=self.project.get_simulation_tool_name(), synthesis_directory=self.project.get_synthesis_directory(), synthesis_tool_name=self.project.get_synthesis_tool_name(), fpga_part=self.project.get_fpga_part(), modelsim_vsim_args=self.project.get_tool_arguments( 'modelsim', 'simulate' ), project='', synthesis_generics=''.join( str(k) + ':' + str(v) + ', ' for k, v in self.project.get_generics().items() )) ) @wraps_do_commands def do_show_tests(self, command): """ Show the tests available in the current project. """ tests = self.project.get_tests() if len(tests) == 0: log.info('There are no tests available.') return testUniqueId = 0 for file_object in tests: file_name = os.path.basename(file_object.path) print(term.yellow(file_name)) for test_group in file_object.testsuite: for testId, test in enumerate(test_group): if testId == 0: print( SEP + term.green(str(test.__class__.__name__)) ) doc = test.shortDescription() if doc is None: doc = term.darkred('No description') if testUniqueId in self.test_set: msg = SEP * 2 + '[' + term.blue('ID ' + str( testUniqueId) + ' ' + test.id().split('.')[-1] ) + ']' else: msg = SEP * 2 + term.lightgray('ID ' + str( testUniqueId) + ' ' + test.id().split('.')[-1] ) print(msg) print(term.darkgray(textwrap.fill( doc, width=80, initial_indent=SEP * 2, subsequent_indent=SEP * 2, ))) testUniqueId += 1 def show_test_selection(self): """ Show the currently selected tests in the current project. Add or remove tests using the add_tests and remove_tests commands respectively. """ ids_list = list(self.test_set) tests = [] for file_object in self.project.get_tests(): file_name = os.path.basename(file_object.path) print(term.yellow(file_name)) for test_group in file_object.testsuite: for testId, test in enumerate(test_group): if testId == 0: groupName = str(test.__class__.__name__) testName = test.id().split('.')[-1] tests.append((file_name, groupName, testName, test)) # Filter out any invalid indices ids_list = list(filter(lambda x: x < len(tests), ids_list)) for idx, (fileName, groupName, testName, test) in enumerate( [tests[idx] for idx in ids_list] ): print( '{:<5}'.format(str(ids_list[idx]) + ':') + '[' + term.yellow(fileName) + ']' + '[' + term.green(groupName) + ']' + '[' + term.blue(testName) + ']' ) @wraps_do_commands def do_add_tests(self, command): """ Add the given tests to the test suite. Tests should be supplied as comma separated numbers or numeric ranges, for example: add_tests 1-3, 5, 6, 7 Would add tests 1, 2, 3, 5, 6, 7 to the test suite. You can check which tests are available by issuing the show_tests command or remove tests that have been added to the suite by issuing the remove_tests command. """ try: ids = utils.parseRange(command) except ValueError: log.error('Invalid test range specified: ' + command) return for testId in ids: self.test_set.add(testId) self.show_test_selection() @wraps_do_commands def do_remove_tests(self, command): """ Remove the given tests from the test suite. Tests should be supplied as comma separated numbers or numeric ranges, for example: remove_tests 1-3, 5, 6, 7 Would remove tests 1, 2, 3, 5, 6, 7 from the test suite. You can check which tests are available by issuing the show_tests command or add tests by issuing the add_tests command. """ try: ids = utils.parseRange(command) except ValueError: log.error('Invalid test range specified: ' + command) return for testId in ids: try: self.test_set.remove(testId) except KeyError: pass self.show_test_selection() @wraps_do_commands def do_run_tests(self, command): """ Run the tests that were selected via the add_tests command and report the results. """ if len(command) > 0: tool_name = command else: tool_name = None self.show_test_selection() self.project.run_tests(self.test_set, tool_name=tool_name)
def testSynthesisDirectory(self): project = Project() XmlProjectParser.load_project(self.project_path, project) abs_path = os.path.join(os.path.abspath(self.root), self.synthesis_directory) self.assertEqual(project.get_synthesis_directory(), abs_path)
def testProjectPart(self): project = Project() XmlProjectParser.load_project(self.project_path, project) # Check project part self.assertEqual(self.project_part, project.get_fpga_part())
def testProjectLoad(self): project = Project() project.load_project(self.project_path)