1818from vunit .sim_if .modelsim import ModelSimInterface
1919from vunit .project import Project
2020from vunit .ostools import renew_path , write_file
21+ from vunit .test .bench import Configuration
2122from vunit .vhdl_standard import VHDL
2223
2324
@@ -316,14 +317,60 @@ def test_overwrites_modelsim_ini_file_from_user(self):
316317 with open (modelsim_ini , "r" ) as fptr :
317318 self .assertEqual (fptr .read (), "user" )
318319
320+ @mock .patch ("vunit.sim_if.modelsim.LOGGER" , autospec = True )
321+ @mock .patch ("vunit.sim_if.check_output" , autospec = True , return_value = "" )
322+ @mock .patch ("vunit.sim_if.modelsim.Process" , autospec = True )
323+ @mock .patch ("vunit.sim_if.vsim_simulator_mixin.Process" , autospec = True )
324+ def test_optimize (self , vsim_simulator_mixin_process , modelsim_process , check_output , LOGGER ):
325+ simif = ModelSimInterface (prefix = self .prefix_path , output_path = self .output_path , persistent = False )
326+ project = Project ()
327+ project .add_library ("lib" , str (Path (self .libraries_path ) / "lib" ))
328+ write_file ("file.vhd" , "" )
329+ project .add_source_file ("file.vhd" , "lib" , file_type = "vhdl" , vhdl_standard = VHDL .standard ("2008" ))
330+ simif .compile_project (project )
331+ config = make_config (sim_options = {"modelsim.three_step_flow" :True })
332+
333+ # First call should optimize design
334+ simif .simulate (self .simulation_output_path , "test_suite_name" , config , False )
335+ design_to_optimize = "lib.tb(test)"
336+ expected_calls = [
337+ mock .call ("%s scheduled for optimization." , design_to_optimize ),
338+ mock .call ("Acquired library lock for %s to optimize %s." , "lib" , design_to_optimize ),
339+ mock .call ("Optimizing %s." , design_to_optimize ),
340+ mock .call ("%s optimization completed." , design_to_optimize ),
341+ ]
342+ self .assertEqual (LOGGER .debug .call_count , len (expected_calls ))
343+ LOGGER .debug .assert_has_calls (expected_calls )
344+
345+ # Second call should reuse the already optimized design
346+ LOGGER .reset_mock ()
347+ simif .simulate (self .simulation_output_path , "test_suite_name" , config , False )
348+ LOGGER .debug .assert_called_once_with ("Reusing optimized %s." , "lib.tb(test)" )
349+
350+ # Fake that design is being optimized and that it is being waited for
351+ LOGGER .reset_mock ()
352+ simif ._optimized_designs [design_to_optimize ]["optimized_design" ] = None
353+ simif .simulate (self .simulation_output_path , "test_suite_name" , config , False )
354+ expected_calls = [
355+ mock .call ("Waiting for %s to be optimized." , design_to_optimize ),
356+ mock .call ("Done waiting for %s to be optimized." , design_to_optimize ),
357+ ]
358+ self .assertEqual (LOGGER .debug .call_count , len (expected_calls ))
359+ LOGGER .debug .assert_has_calls (expected_calls )
360+
361+
319362 def setUp (self ):
320363 self .test_path = str (Path (__file__ ).parent / "test_modelsim_out" )
321364
322365 self .output_path = str (Path (self .test_path ) / "modelsim" )
323366 self .prefix_path = str (Path (self .test_path ) / "prefix" / "bin" )
367+ self .libraries_path = str (Path (self .output_path ) / "libraries" )
368+ self .simulation_output_path = str (Path (self .test_path ) / "test_output" / "lib.tb" )
324369 renew_path (self .test_path )
325370 renew_path (self .output_path )
326371 renew_path (self .prefix_path )
372+ renew_path (self .libraries_path )
373+ renew_path (self .simulation_output_path )
327374 installed_modelsim_ini = str (Path (self .prefix_path ) / ".." / "modelsim.ini" )
328375 write_file (installed_modelsim_ini , "[Library]" )
329376 self .project = Project ()
@@ -334,3 +381,23 @@ def tearDown(self):
334381 os .chdir (self .cwd )
335382 if Path (self .test_path ).exists ():
336383 rmtree (self .test_path )
384+
385+ def make_config (sim_options = None , generics = None , verilog = False ):
386+ """
387+ Utility to reduce boiler plate in tests
388+ """
389+ cfg = mock .Mock (spec = Configuration )
390+ cfg .library_name = "lib"
391+
392+ if verilog :
393+ cfg .entity_name = "tb"
394+ cfg .architecture_name = None
395+ else :
396+ cfg .entity_name = "tb"
397+ cfg .architecture_name = "test"
398+
399+ cfg .sim_options = {} if sim_options is None else sim_options
400+ cfg .generics = {} if generics is None else generics
401+ cfg .vhdl_configuration_name = None
402+ cfg .vhdl_assert_stop_level = "error"
403+ return cfg
0 commit comments