diff --git a/docs/run/img/get_seed_and_runner_cfg.html b/docs/run/img/get_seed_and_runner_cfg.html
new file mode 100644
index 000000000..63c2e78cd
--- /dev/null
+++ b/docs/run/img/get_seed_and_runner_cfg.html
@@ -0,0 +1,2 @@
+
constant global_seed : string := get_seed(runner_cfg, "Optional salt");
+
diff --git a/docs/run/img/get_seed_wo_runner_cfg.html b/docs/run/img/get_seed_wo_runner_cfg.html
new file mode 100644
index 000000000..5c56cc549
--- /dev/null
+++ b/docs/run/img/get_seed_wo_runner_cfg.html
@@ -0,0 +1,5 @@
+randomizing_process : process is
+ variable local_seed : string_seed_t; -- string_seed_t = string(1 to 16)
+begin
+ get_seed(local_seed, salt => randomizing_process'path_name);
+
diff --git a/docs/run/img/get_uniform_seed.html b/docs/run/img/get_uniform_seed.html
new file mode 100644
index 000000000..c4842b882
--- /dev/null
+++ b/docs/run/img/get_uniform_seed.html
@@ -0,0 +1,5 @@
+get_uniform_seed(seed1, seed2, "Optional salt");
+
+uniform(seed1, seed2, a_random_value);
+uniform(seed1, seed2, another_random_value);
+
diff --git a/docs/run/img/list.html b/docs/run/img/list.html
index 9b98fcbae..bed81644a 100644
--- a/docs/run/img/list.html
+++ b/docs/run/img/list.html
@@ -1,4 +1,8 @@
> python run.py --list
+lib.tb_fail_on_warning.Test that fails on an assert
+lib.tb_fail_on_warning.Test that crashes on boundary problems
+lib.tb_fail_on_warning.Test that fails on VUnit check procedure
+lib.tb_fail_on_warning.Test that a warning passes
lib.tb_magic_paths.all
lib.tb_minimal.all
lib.tb_running_test_case.Test scenario A
@@ -6,11 +10,13 @@
lib.tb_running_test_case.Test something else
lib.tb_run_all_in_same_sim.Test to_string for integer again
lib.tb_run_all_in_same_sim.Test to_string for boolean again
+lib.tb_seed.all
lib.tb_standalone.Test that fails on VUnit check procedure
lib.tb_standalone.Test to_string for boolean
lib.tb_stopping_failure.Test that fails on an assert
lib.tb_stopping_failure.Test that crashes on boundary problems
lib.tb_stopping_failure.Test that fails on VUnit check procedure
+lib.tb_stopping_failure.Test that a warning passes
lib.tb_stop_level.Test that fails multiple times but doesn't stop
lib.tb_with_lower_level_control.Test something
lib.tb_with_lower_level_control.Test something else
@@ -19,5 +25,5 @@
lib.tb_with_watchdog.Test that stalls
lib.tb_with_watchdog.Test to_string for boolean
lib.tb_with_watchdog.Test that needs longer timeout
-Listed 20 tests
+Listed 26 tests
diff --git a/docs/run/img/seed_option.html b/docs/run/img/seed_option.html
new file mode 100644
index 000000000..9a02b5673
--- /dev/null
+++ b/docs/run/img/seed_option.html
@@ -0,0 +1 @@
+> python run.py "lib.tb_seed.Test that fails" --seed fb19f3cca859d69c
diff --git a/docs/run/img/tb_magic_paths_stdout.html b/docs/run/img/tb_magic_paths_stdout.html
index ae539385a..68af5fe36 100644
--- a/docs/run/img/tb_magic_paths_stdout.html
+++ b/docs/run/img/tb_magic_paths_stdout.html
@@ -1,18 +1,19 @@
> python run.py -v
Starting lib.tb_magic_paths.all
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_magic_paths.all_243b3c717ce1d4e82490245d1b7e8fe8797f5e94\output.txt
+Seed for lib.tb_magic_paths.all: 3680f2e2321cdac3
0 fs - default - INFO - Directory containing testbench: C:/github/vunit/docs/run/src/
0 fs - default - INFO - Test output directory: C:/github/vunit/docs/run/src/vunit_out/test_output/lib.tb_magic_paths.all_243b3c717ce1d4e82490245d1b7e8fe8797f5e94/
simulation stopped @0ms with status 0
-pass (P=1 S=0 F=0 T=1) lib.tb_magic_paths.all (0.5 seconds)
+pass (P=1 S=0 F=0 T=1) lib.tb_magic_paths.all (0.6 s)
==== Summary ==================================
-pass lib.tb_magic_paths.all (0.5 seconds)
+pass lib.tb_magic_paths.all (0.6 s)
===============================================
pass 1 of 1
===============================================
-Total time was 0.5 seconds
-Elapsed time was 0.5 seconds
+Total time was 0.6 s
+Elapsed time was 0.6 s
===============================================
All passed!
diff --git a/docs/run/img/tb_minimal_stdout.html b/docs/run/img/tb_minimal_stdout.html
index 36c933ffa..33b883caf 100644
--- a/docs/run/img/tb_minimal_stdout.html
+++ b/docs/run/img/tb_minimal_stdout.html
@@ -1,15 +1,15 @@
> python run.py
Starting lib.tb_minimal.all
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_minimal.all_42aa262c7c96c708ab3f3960f033f2328c642136\output.txt
-pass (P=1 S=0 F=0 T=1) lib.tb_minimal.all (0.5 seconds)
+pass (P=1 S=0 F=0 T=1) lib.tb_minimal.all (0.6 s)
==== Summary ==============================
-pass lib.tb_minimal.all (0.5 seconds)
+pass lib.tb_minimal.all (0.6 s)
===========================================
pass 1 of 1
===========================================
-Total time was 0.5 seconds
-Elapsed time was 0.5 seconds
+Total time was 0.6 s
+Elapsed time was 0.6 s
===========================================
All passed!
diff --git a/docs/run/img/tb_running_test_case_stdout.html b/docs/run/img/tb_running_test_case_stdout.html
index 11b105f58..3ed29dc13 100644
--- a/docs/run/img/tb_running_test_case_stdout.html
+++ b/docs/run/img/tb_running_test_case_stdout.html
@@ -1,25 +1,25 @@
> python run.py
Starting lib.tb_running_test_case.Test scenario A
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_running_test_case.Test_scenario_A_b118fcdf82c6ba5772e038ce7455962692f50c2a\output.txt
-pass (P=1 S=0 F=0 T=3) lib.tb_running_test_case.Test scenario A (0.5 seconds)
+pass (P=1 S=0 F=0 T=3) lib.tb_running_test_case.Test scenario A (0.6 s)
-Starting lib.tb_running_test_case.Test scenario B
+(22:55:49) Starting lib.tb_running_test_case.Test scenario B
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_running_test_case.Test_scenario_B_8cd407ec92589901f9b4594c0f27835478242f2c\output.txt
-pass (P=2 S=0 F=0 T=3) lib.tb_running_test_case.Test scenario B (0.5 seconds)
+pass (P=2 S=0 F=0 T=3) lib.tb_running_test_case.Test scenario B (0.6 s)
-Starting lib.tb_running_test_case.Test something else
+(22:55:50) Starting lib.tb_running_test_case.Test something else
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_running_test_case.Test_something_else_27dcc1aa8d44993b6b2d0b0a017fa6001b4c2aa7\output.txt
-pass (P=3 S=0 F=0 T=3) lib.tb_running_test_case.Test something else (0.5 seconds)
+pass (P=3 S=0 F=0 T=3) lib.tb_running_test_case.Test something else (0.6 s)
==== Summary ========================================================
-pass lib.tb_running_test_case.Test scenario A (0.5 seconds)
-pass lib.tb_running_test_case.Test scenario B (0.5 seconds)
-pass lib.tb_running_test_case.Test something else (0.5 seconds)
+pass lib.tb_running_test_case.Test scenario A (0.6 s)
+pass lib.tb_running_test_case.Test scenario B (0.6 s)
+pass lib.tb_running_test_case.Test something else (0.6 s)
=====================================================================
pass 3 of 3
=====================================================================
-Total time was 1.6 seconds
-Elapsed time was 1.6 seconds
+Total time was 1.8 s
+Elapsed time was 1.8 s
=====================================================================
All passed!
diff --git a/docs/run/img/tb_seed_stdout.html b/docs/run/img/tb_seed_stdout.html
new file mode 100644
index 000000000..18cc5e1b7
--- /dev/null
+++ b/docs/run/img/tb_seed_stdout.html
@@ -0,0 +1,28 @@
+> python run.py
+Starting lib.tb_seed.Test that passes
+Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_seed.Test_that_passes_4125d67fe52dadd934f892b1209f41e7a94a39bd\output.txt
+Seed for lib.tb_seed.Test that passes: 8c5c0ea80b58a8ee
+simulation stopped @0ms with status 0
+pass (P=1 S=0 F=0 T=2) lib.tb_seed.Test that passes (0.5 s)
+
+(09:37:45) Starting lib.tb_seed.Test that fails
+Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_seed.Test_that_fails_0f173e63967af845f06d4a86c622bba76f3ffb3d\output.txt
+Seed for lib.tb_seed.Test that fails: fb19f3cca859d69c
+ 0 fs - default - ERROR - Something bad happened
+C:\repos\vunit\vunit\vhdl\core\src\core_pkg.vhd:85:7:@0ms:(report failure): Stop simulation on log level error
+ghdl:error: report failed
+ghdl:error: simulation failed
+fail (P=1 S=0 F=1 T=2) lib.tb_seed.Test that fails (0.5 s)
+
+==== Summary ========================================
+pass lib.tb_seed.Test that passes (0.5 s)
+fail lib.tb_seed.Test that fails (0.5 s)
+=====================================================
+pass 1 of 2
+fail 1 of 2
+=====================================================
+Total time was 1.0 s
+Elapsed time was 1.0 s
+=====================================================
+Some failed!
+
diff --git a/docs/run/img/tb_stop_level_stdout.html b/docs/run/img/tb_stop_level_stdout.html
index 6bd1ac5d1..6d8548bee 100644
--- a/docs/run/img/tb_stop_level_stdout.html
+++ b/docs/run/img/tb_stop_level_stdout.html
@@ -1,26 +1,23 @@
> python run.py
Starting lib.tb_stop_level.Test that fails multiple times but doesn't stop
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_stop_level.Test_that_fails_multiple_times_but_doesn't_stop_d08f48d859442d0bc71e2bcdd8b429119f7cc17c\output.txt
+Seed for lib.tb_stop_level.Test that fails multiple times but doesn't stop: 7a0e979de335b966
0 fs - check - ERROR - Equality check failed - Got 17. Expected 18.
0 fs - check - ERROR - Equality check failed - Got 17. Expected 19.
FAILURE - Logger check has 2 errors
-C:\github\vunit\vunit\vhdl\core\src\core_pkg.vhd:84:7:@0ms:(report failure): Final log check failed
-C:\ghdl\bin\ghdl.exe:error: report failed
-in process .tb_stop_level(tb).test_runner
- from: vunit_lib.logger_pkg.final_log_check at logger_pkg-body.vhd:1249
- from: vunit_lib.run_pkg.test_runner_cleanup at run.vhd:114
- from: process lib.tb_stop_level(tb).test_runner at tb_stop_level.vhd:29
-C:\ghdl\bin\ghdl.exe:error: simulation failed
-fail (P=0 S=0 F=1 T=1) lib.tb_stop_level.Test that fails multiple times but doesn't stop (0.5 seconds)
+C:\github\vunit\vunit\vhdl\core\src\core_pkg.vhd:85:7:@0ms:(report failure): Final log check failed
+ghdl:error: report failed
+ghdl:error: simulation failed
+fail (P=0 S=0 F=1 T=1) lib.tb_stop_level.Test that fails multiple times but doesn't stop (0.6 s)
==== Summary =============================================================================
-fail lib.tb_stop_level.Test that fails multiple times but doesn't stop (0.5 seconds)
+fail lib.tb_stop_level.Test that fails multiple times but doesn't stop (0.6 s)
==========================================================================================
pass 0 of 1
fail 1 of 1
==========================================================================================
-Total time was 0.5 seconds
-Elapsed time was 0.5 seconds
+Total time was 0.6 s
+Elapsed time was 0.6 s
==========================================================================================
Some failed!
diff --git a/docs/run/img/tb_stopping_failure_stdout.html b/docs/run/img/tb_stopping_failure_stdout.html
index 63d7964a7..2bf20d824 100644
--- a/docs/run/img/tb_stopping_failure_stdout.html
+++ b/docs/run/img/tb_stopping_failure_stdout.html
@@ -1,40 +1,43 @@
> python run.py
Starting lib.tb_stopping_failure.Test that fails on an assert
-Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_fails_on_an_assert_f53b930e2c7649bc33253af52f8ea89a9c05f07b\output.txt
-C:\repos\vunit\docs\run\src\tb_stopping_failure.vhd:24:9:@0ms:(assertion error): Assertion violation
+Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_fails_on_an_assert_f53b930e2c7649bc33253af52f8ea89a9c05f07b\output.txt
+Seed for lib.tb_stopping_failure.Test that fails on an assert: a866d0986a663e6b
+C:\github\vunit\docs\run\src\tb_stopping_failure.vhd:24:9:@0ms:(assertion error): Assertion violation
ghdl:error: assertion failed
ghdl:error: simulation failed
-fail (P=0 S=0 F=1 T=4) lib.tb_stopping_failure.Test that fails on an assert (0.5 s)
+fail (P=0 S=0 F=1 T=4) lib.tb_stopping_failure.Test that fails on an assert (0.6 s)
-(11:35:31) Starting lib.tb_stopping_failure.Test that crashes on boundary problems
-Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_crashes_on_boundary_problems_b53105615efefaa16d0cf9ee1bad37b5d3369e95\output.txt
-ghdl:error: index (314) out of bounds (1 to 17) at C:\repos\vunit\docs\run\src\tb_stopping_failure.vhd:26
+(22:55:55) Starting lib.tb_stopping_failure.Test that crashes on boundary problems
+Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_crashes_on_boundary_problems_b53105615efefaa16d0cf9ee1bad37b5d3369e95\output.txt
+Seed for lib.tb_stopping_failure.Test that crashes on boundary problems: cbcb543764149e78
+ghdl:error: index (340) out of bounds (1 to 17) at C:\github\vunit\docs\run\src\tb_stopping_failure.vhd:26
ghdl:error: simulation failed
-fail (P=0 S=0 F=2 T=4) lib.tb_stopping_failure.Test that crashes on boundary problems (0.5 s)
+fail (P=0 S=0 F=2 T=4) lib.tb_stopping_failure.Test that crashes on boundary problems (0.6 s)
-(11:35:31) Starting lib.tb_stopping_failure.Test that fails on VUnit check procedure
-Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_fails_on_VUnit_check_procedure_717a6f8ff044e3d5fa7d7d3ec5a32971d74864dd\output.txt
+(22:55:55) Starting lib.tb_stopping_failure.Test that fails on VUnit check procedure
+Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_fails_on_VUnit_check_procedure_717a6f8ff044e3d5fa7d7d3ec5a32971d74864dd\output.txt
+Seed for lib.tb_stopping_failure.Test that fails on VUnit check procedure: 6581894e9ea614b1
0 fs - check - ERROR - Equality check failed - Got 17. Expected 18.
-C:\repos\vunit\vunit\vhdl\core\src\core_pkg.vhd:85:7:@0ms:(report failure): Stop simulation on log level error
+C:\github\vunit\vunit\vhdl\core\src\core_pkg.vhd:85:7:@0ms:(report failure): Stop simulation on log level error
ghdl:error: report failed
ghdl:error: simulation failed
-fail (P=0 S=0 F=3 T=4) lib.tb_stopping_failure.Test that fails on VUnit check procedure (0.5 s)
+fail (P=0 S=0 F=3 T=4) lib.tb_stopping_failure.Test that fails on VUnit check procedure (0.6 s)
-(11:35:32) Starting lib.tb_stopping_failure.Test that a warning passes
-Output file: C:\repos\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_a_warning_passes_7db91f3b27aea5f89e74e39ea51ce6d61558674e\output.txt
-pass (P=1 S=0 F=3 T=4) lib.tb_stopping_failure.Test that a warning passes (0.4 s)
+(22:55:56) Starting lib.tb_stopping_failure.Test that a warning passes
+Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_stopping_failure.Test_that_a_warning_passes_7db91f3b27aea5f89e74e39ea51ce6d61558674e\output.txt
+pass (P=1 S=0 F=3 T=4) lib.tb_stopping_failure.Test that a warning passes (0.6 s)
==== Summary ============================================================================
-pass lib.tb_stopping_failure.Test that a warning passes (0.4 s)
-fail lib.tb_stopping_failure.Test that fails on an assert (0.5 s)
-fail lib.tb_stopping_failure.Test that crashes on boundary problems (0.5 s)
-fail lib.tb_stopping_failure.Test that fails on VUnit check procedure (0.5 s)
+pass lib.tb_stopping_failure.Test that a warning passes (0.6 s)
+fail lib.tb_stopping_failure.Test that fails on an assert (0.6 s)
+fail lib.tb_stopping_failure.Test that crashes on boundary problems (0.6 s)
+fail lib.tb_stopping_failure.Test that fails on VUnit check procedure (0.6 s)
=========================================================================================
pass 1 of 4
fail 3 of 4
=========================================================================================
-Total time was 1.8 s
-Elapsed time was 1.8 s
+Total time was 2.4 s
+Elapsed time was 2.4 s
=========================================================================================
Some failed!
diff --git a/docs/run/img/tb_with_lower_level_control_stdout.html b/docs/run/img/tb_with_lower_level_control_stdout.html
index 2593def3b..1225640e3 100644
--- a/docs/run/img/tb_with_lower_level_control_stdout.html
+++ b/docs/run/img/tb_with_lower_level_control_stdout.html
@@ -1,20 +1,20 @@
> python run.py
Starting lib.tb_with_lower_level_control.Test something
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_lower_level_control.Test_something_a280708dc2f527dff5e45e7a7d2b48df39330b4f\output.txt
-pass (P=1 S=0 F=0 T=2) lib.tb_with_lower_level_control.Test something (0.5 seconds)
+pass (P=1 S=0 F=0 T=2) lib.tb_with_lower_level_control.Test something (0.6 s)
-Starting lib.tb_with_lower_level_control.Test something else
+(22:55:51) Starting lib.tb_with_lower_level_control.Test something else
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_lower_level_control.Test_something_else_e47dc199cab8c612d9a0f46b8be7d141576fc970\output.txt
-pass (P=2 S=0 F=0 T=2) lib.tb_with_lower_level_control.Test something else (0.5 seconds)
+pass (P=2 S=0 F=0 T=2) lib.tb_with_lower_level_control.Test something else (0.6 s)
==== Summary ===============================================================
-pass lib.tb_with_lower_level_control.Test something (0.5 seconds)
-pass lib.tb_with_lower_level_control.Test something else (0.5 seconds)
+pass lib.tb_with_lower_level_control.Test something (0.6 s)
+pass lib.tb_with_lower_level_control.Test something else (0.6 s)
============================================================================
pass 2 of 2
============================================================================
-Total time was 1.1 seconds
-Elapsed time was 1.1 seconds
+Total time was 1.2 s
+Elapsed time was 1.2 s
============================================================================
All passed!
diff --git a/docs/run/img/tb_with_test_cases_stdout.html b/docs/run/img/tb_with_test_cases_stdout.html
index 8fc2ae2f8..ea9f2d12c 100644
--- a/docs/run/img/tb_with_test_cases_stdout.html
+++ b/docs/run/img/tb_with_test_cases_stdout.html
@@ -1,20 +1,20 @@
> python run.py
Starting lib.tb_with_test_cases.Test to_string for integer
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_test_cases.Test_to_string_for_integer_f5d39e15e865eddcda2b57f65dddc2428c994af4\output.txt
-pass (P=1 S=0 F=0 T=2) lib.tb_with_test_cases.Test to_string for integer (0.6 seconds)
+pass (P=1 S=0 F=0 T=2) lib.tb_with_test_cases.Test to_string for integer (0.6 s)
-Starting lib.tb_with_test_cases.Test to_string for boolean
+(22:55:48) Starting lib.tb_with_test_cases.Test to_string for boolean
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_test_cases.Test_to_string_for_boolean_38c3f897030cff968430d763a9bbc23202de1a7b\output.txt
-pass (P=2 S=0 F=0 T=2) lib.tb_with_test_cases.Test to_string for boolean (0.5 seconds)
+pass (P=2 S=0 F=0 T=2) lib.tb_with_test_cases.Test to_string for boolean (0.6 s)
==== Summary =============================================================
-pass lib.tb_with_test_cases.Test to_string for integer (0.6 seconds)
-pass lib.tb_with_test_cases.Test to_string for boolean (0.5 seconds)
+pass lib.tb_with_test_cases.Test to_string for integer (0.6 s)
+pass lib.tb_with_test_cases.Test to_string for boolean (0.6 s)
==========================================================================
pass 2 of 2
==========================================================================
-Total time was 1.1 seconds
-Elapsed time was 1.1 seconds
+Total time was 1.2 s
+Elapsed time was 1.2 s
==========================================================================
All passed!
diff --git a/docs/run/img/tb_with_watchdog_stdout.html b/docs/run/img/tb_with_watchdog_stdout.html
index b3352ae40..1bf9c79d1 100644
--- a/docs/run/img/tb_with_watchdog_stdout.html
+++ b/docs/run/img/tb_with_watchdog_stdout.html
@@ -1,37 +1,31 @@
> python run.py
Starting lib.tb_with_watchdog.Test that stalls
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_watchdog.Test_that_stalls_7f50c5908f9e9f9df5075e065f984eef1c2f7b2b\output.txt
+Seed for lib.tb_with_watchdog.Test that stalls: abf6f593955b8927
10000000000000 fs - runner - ERROR - Test runner timeout after 10000000000000 fs.
-C:\github\vunit\vunit\vhdl\core\src\core_pkg.vhd:84:7:@10ms:(report failure): Stop simulation on log level error
-C:\ghdl\bin\ghdl.exe:error: report failed
-in process .tb_with_watchdog(tb).P0
- from: vunit_lib.logger_pkg.decrease_stop_count at logger_pkg-body.vhd:736
- from: vunit_lib.logger_pkg.decrease_stop_count at logger_pkg-body.vhd:731
- from: vunit_lib.logger_pkg.log at logger_pkg-body.vhd:910
- from: vunit_lib.logger_pkg.error at logger_pkg-body.vhd:969
- from: vunit_lib.run_pkg.test_runner_watchdog at run.vhd:308
- from: process lib.tb_with_watchdog(tb).P0 at tb_with_watchdog.vhd:37
-C:\ghdl\bin\ghdl.exe:error: simulation failed
-fail (P=0 S=0 F=1 T=3) lib.tb_with_watchdog.Test that stalls (0.5 seconds)
+C:\github\vunit\vunit\vhdl\core\src\core_pkg.vhd:85:7:@10ms:(report failure): Stop simulation on log level error
+ghdl:error: report failed
+ghdl:error: simulation failed
+fail (P=0 S=0 F=1 T=3) lib.tb_with_watchdog.Test that stalls (0.6 s)
-Starting lib.tb_with_watchdog.Test to_string for boolean
+(22:55:53) Starting lib.tb_with_watchdog.Test to_string for boolean
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_watchdog.Test_to_string_for_boolean_f167e524924d51144c5a6913c63e9fa5c6c7988c\output.txt
-pass (P=1 S=0 F=1 T=3) lib.tb_with_watchdog.Test to_string for boolean (0.5 seconds)
+pass (P=1 S=0 F=1 T=3) lib.tb_with_watchdog.Test to_string for boolean (0.6 s)
-Starting lib.tb_with_watchdog.Test that needs longer timeout
+(22:55:53) Starting lib.tb_with_watchdog.Test that needs longer timeout
Output file: C:\github\vunit\docs\run\src\vunit_out\test_output\lib.tb_with_watchdog.Test_that_needs_longer_timeout_5494104827c61d0022a75acbab4c0c6de9e29643\output.txt
-pass (P=2 S=0 F=1 T=3) lib.tb_with_watchdog.Test that needs longer timeout (0.5 seconds)
+pass (P=2 S=0 F=1 T=3) lib.tb_with_watchdog.Test that needs longer timeout (0.6 s)
==== Summary ===============================================================
-pass lib.tb_with_watchdog.Test to_string for boolean (0.5 seconds)
-pass lib.tb_with_watchdog.Test that needs longer timeout (0.5 seconds)
-fail lib.tb_with_watchdog.Test that stalls (0.5 seconds)
+pass lib.tb_with_watchdog.Test to_string for boolean (0.6 s)
+pass lib.tb_with_watchdog.Test that needs longer timeout (0.6 s)
+fail lib.tb_with_watchdog.Test that stalls (0.6 s)
============================================================================
pass 2 of 3
fail 1 of 3
============================================================================
-Total time was 1.6 seconds
-Elapsed time was 1.6 seconds
+Total time was 1.8 s
+Elapsed time was 1.8 s
============================================================================
Some failed!
diff --git a/docs/run/src/run.py b/docs/run/src/run.py
index a44edc9d5..c0b732f35 100644
--- a/docs/run/src/run.py
+++ b/docs/run/src/run.py
@@ -126,9 +126,24 @@ def extract_snippets():
snippet,
)
+ for snippet in [
+ "get_seed_and_runner_cfg",
+ "get_seed_wo_runner_cfg",
+ "get_uniform_seed",
+ ]:
+ highlight_code(
+ root / "tb_seed.vhd",
+ root / ".." / "img" / f"{snippet}.html",
+ snippet,
+ )
+
extract_snippets()
+seed_option_path = root / "seed_option.txt"
+seed_option_path.write_text('> python run.py "lib.tb_seed.Test that fails" --seed fb19f3cca859d69c')
+highlight_log(seed_option_path, root / ".." / "img" / "seed_option.html")
+
def post_run(log_registry):
def _post_run(results):
@@ -142,6 +157,8 @@ def _post_run(results):
cli = VUnitCLI()
args = cli.parse_args()
+print(args.test_patterns)
+
if args.compile or args.list:
test_patterns = ["*"]
elif args.test_patterns[0] != "*":
@@ -155,6 +172,7 @@ def _post_run(results):
"lib.tb_with_watchdog*",
"lib.tb_stopping_failure*",
"lib.tb_stop_level*",
+ "lib.tb_seed*",
"lib.tb_magic_paths*",
]
@@ -181,6 +199,8 @@ def _post_run(results):
tb_with_lower_level_control = lib.test_bench("tb_with_lower_level_control")
tb_with_lower_level_control.scan_tests_from_file(root / "test_control.vhd")
+ lib.test_bench("tb_seed").test("Test that fails").set_sim_option("seed", "fb19f3cca859d69c")
+
log_registry = LogRegistry()
vu.set_compile_option("rivierapro.vcom_flags", ["-dbg"])
diff --git a/docs/run/src/tb_seed.vhd b/docs/run/src/tb_seed.vhd
new file mode 100644
index 000000000..41a1c4d0a
--- /dev/null
+++ b/docs/run/src/tb_seed.vhd
@@ -0,0 +1,59 @@
+-- This Source Code Form is subject to the terms of the Mozilla Public
+-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
+-- You can obtain one at http://mozilla.org/MPL/2.0/.
+--
+-- Copyright (c) 2014-2025, Lars Asplund lars.anders.asplund@gmail.com
+
+library vunit_lib;
+context vunit_lib.vunit_context;
+
+library ieee;
+use ieee.math_real.uniform;
+
+entity tb_seed is
+ generic (runner_cfg : string);
+end entity;
+
+architecture tb of tb_seed is
+ -- start_snippet get_seed_and_runner_cfg
+ constant global_seed : string := get_seed(runner_cfg, "Optional salt");
+ -- end_snippet get_seed_and_runner_cfg
+
+ -- Placeholder for a non-standard RNG
+ procedure init_rng(seed : string) is
+ begin
+ info("RNG seeded with " & seed);
+ end;
+begin
+ test_runner : process
+ variable seed1, seed2 : positive;
+ variable a_random_value, another_random_value : real;
+ begin
+ test_runner_setup(runner, runner_cfg);
+
+ while test_suite loop
+ if run("Test that passes") then
+ -- start_snippet get_uniform_seed
+ get_uniform_seed(seed1, seed2, "Optional salt");
+
+ uniform(seed1, seed2, a_random_value);
+ uniform(seed1, seed2, another_random_value);
+ -- end_snippet get_uniform_seed
+
+ elsif run("Test that fails") then
+ error("Something bad happened");
+ end if;
+ end loop;
+
+ test_runner_cleanup(runner);
+ end process;
+
+ -- start_snippet get_seed_wo_runner_cfg
+ randomizing_process : process is
+ variable local_seed : string_seed_t; -- string_seed_t = string(1 to 16)
+ begin
+ get_seed(local_seed, salt => randomizing_process'path_name);
+ -- end_snippet get_seed_wo_runner_cfg
+ wait;
+ end process;
+end architecture;
diff --git a/docs/run/user_guide.rst b/docs/run/user_guide.rst
index be74a1979..964d20179 100644
--- a/docs/run/user_guide.rst
+++ b/docs/run/user_guide.rst
@@ -174,7 +174,7 @@ The ``run_all_in_same_sim`` attribute can also be set from the run script, see :
.. important::
When setting ``run_all_in_same_sim`` from the run script, the setting must be identical for all configurations
of the testbench.
-
+
The VUnit Watchdog
------------------
@@ -238,6 +238,63 @@ failure by setting the ``fail_on_warning`` flag.
.. raw:: html
:file: img/tb_stop_level_stdout.html
+Seeds for Random Number Generation
+----------------------------------
+
+The Python test runner automatically generates a 64-bit base seed, which serves as the foundation for deriving new seeds
+to initialize one or more random number generators (RNGs) within the simulation. This base seed is calculated using the
+system time and a thread identifier, ensuring that it varies between simulations. This variability enhances test
+coverage since randomized test will cover different areas in each simulation. By running the same randomized test in
+several parallel threads but with different base seeds we can also shorten the execution time while maintaining the same
+level of test coverage.
+
+.. note::
+ VHDL-2019 introduces an interface for obtaining the system time. However, as of this writing, support for this
+ feature is limited, and where available, it only offers second-level resolution. If used for base seed generation,
+ simulations in parallel threads would receive the same base seed when started simultaneously.
+
+ To address this, the Python test runner uses system time with microsecond resolution combined with an additional
+ thread identifier as the source of entropy. This approach ensures the uniqueness of base seeds across parallel threads.
+
+The base seed is provided via the ``runner_cfg`` generic and new derived seeds can be obtained by calling the
+``get_seed`` function with ``runner_cfg`` and a salt string. The salt string is hashed together with the base seed to
+ensure the uniqueness of each derived seed (with very high probability). The ``salt`` parameter can be omitted if only a
+single seed is needed:
+
+.. raw:: html
+ :file: img/get_seed_and_runner_cfg.html
+
+A seed can also be obtained without referencing ``runner_cfg``, which is particularly useful when the seed is created
+within a process that is not part of the top-level testbench. However, this is only possible **after**
+``test_runner_setup`` has been executed. To prevent race conditions, the ``get_seed`` procedure will block execution
+until ``test_runner_setup`` has completed.
+
+.. raw:: html
+ :file: img/get_seed_wo_runner_cfg.html
+
+In the previous examples, the ``get_seed`` subprograms returned seeds as strings. However, ``get_seed`` subprograms are
+also available for ``integer`` seeds and 64-bit seeds of ``unsigned`` and ``signed`` type. To avoid any ambiguity that
+may arise, the following function aliases are defined: ``get_string_seed``, ``get_integer_seed``, ``get_unsigned_seed``,
+and ``get_signed_seed``. Additionally, the ``get_uniform_seed`` procedure is provided to support the standard
+``uniform`` procedure in ``ieee.math_real``. The ``uniform`` procedure requires two ``positive`` seeds, ``seed1`` and
+``seed2``, each with its own specific legal range that is smaller than the full ``positive`` range.
+
+.. raw:: html
+ :file: img/get_uniform_seed.html
+
+Reproducibility
+~~~~~~~~~~~~~~~
+
+The seed used for a test is logged in the test output file (``