Make output path for test outputs configurable.

In preparation for CI's and other test environments in which
the test outputs should be stored out-of-tree.

The new file test-utils.tcl provides a function that determines
the test output path (currently just by concatenating the filename
with a path from the environment). The Makefile_test.common sources
this utils file and the corresponding test file.

Since this adds a convenient test-utils.tcl file, this might also
be useful to put some testing boilerplate functionality there in
the future.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
diff --git a/Makefile_test.common b/Makefile_test.common
index ae874eb..3c9d0b3 100644
--- a/Makefile_test.common
+++ b/Makefile_test.common
@@ -17,6 +17,7 @@
 CXXFLAGS = $(shell yosys-config --cxxflags) -I.. -I$(GTEST_DIR)/include
 LDLIBS = $(shell yosys-config --ldlibs) -L$(GTEST_DIR)/build/lib -lgtest -lgtest_main -lpthread
 LDFLAGS = $(shell yosys-config --ldflags)
+TEST_UTILS=../../../test-utils/test-utils.tcl
 
 define test_tpl =
 $(1): $(1)/ok
@@ -37,7 +38,8 @@
 	@set +e; \
 	cd $(1); \
 	DESIGN_TOP=$(1) \
-	yosys -c $(1).tcl -q -l $(1).log; \
+	TEST_OUTPUT_PREFIX=./ \
+	yosys -c <(echo -e "source $(TEST_UTILS)\nsource $(1).tcl") -q -l $(1).log; \
 	RETVAL=$$$$?; \
 	if [ ! -z "$$($(1)_negative)" ] && [ $$($(1)_negative) -eq 1 ]; then \
 		if [ $$$$RETVAL -ne 0 ]; then \
diff --git a/design_introspection-plugin/tests/get_cells/get_cells.tcl b/design_introspection-plugin/tests/get_cells/get_cells.tcl
index c7660a6..047b150 100644
--- a/design_introspection-plugin/tests/get_cells/get_cells.tcl
+++ b/design_introspection-plugin/tests/get_cells/get_cells.tcl
@@ -7,7 +7,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 
-set fp [open "get_cells.txt" "w"]
+set fp [open [test_output_path "get_cells.txt"] "w"]
 
 puts "\n*inter* cells quiet"
 puts $fp "\n*inter* cells quiet"
diff --git a/design_introspection-plugin/tests/get_nets/get_nets.tcl b/design_introspection-plugin/tests/get_nets/get_nets.tcl
index a3af390..6ef2426 100644
--- a/design_introspection-plugin/tests/get_nets/get_nets.tcl
+++ b/design_introspection-plugin/tests/get_nets/get_nets.tcl
@@ -7,7 +7,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 
-set fp [open "get_nets.txt" "w"]
+set fp [open [test_output_path "get_nets.txt"] "w"]
 
 puts "\n*inter* nets quiet"
 puts $fp "*inter* nets quiet"
diff --git a/design_introspection-plugin/tests/get_pins/get_pins.tcl b/design_introspection-plugin/tests/get_pins/get_pins.tcl
index 515f850..d6a64fe 100644
--- a/design_introspection-plugin/tests/get_pins/get_pins.tcl
+++ b/design_introspection-plugin/tests/get_pins/get_pins.tcl
@@ -7,7 +7,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 
-set fp [open "get_pins.txt" "w"]
+set fp [open [test_output_path "get_pins.txt"] "w"]
 
 puts "\n*inter* pins quiet"
 puts $fp "\n*inter* pins quiet"
diff --git a/design_introspection-plugin/tests/get_ports/get_ports.tcl b/design_introspection-plugin/tests/get_ports/get_ports.tcl
index 34e2d11..47d8fce 100644
--- a/design_introspection-plugin/tests/get_ports/get_ports.tcl
+++ b/design_introspection-plugin/tests/get_ports/get_ports.tcl
@@ -7,7 +7,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 help get_ports
 
-set fp [open "get_ports.txt" "w"]
+set fp [open [test_output_path "get_ports.txt"] "w"]
 
 puts "\n signal_p port"
 puts $fp "signal_p port"
diff --git a/params-plugin/tests/pll/pll.tcl b/params-plugin/tests/pll/pll.tcl
index 72f37d1..86eb1b1 100644
--- a/params-plugin/tests/pll/pll.tcl
+++ b/params-plugin/tests/pll/pll.tcl
@@ -13,7 +13,7 @@
 if {[llength $phase] != 2} {
 	error "Getparam should return a list with 2 elements"
 }
-set fp [open "pll.txt" "w"]
+set fp [open [test_output_path "pll.txt"] "w"]
 puts -nonewline $fp "Phase before: "
 if {$phase == $reference_phase} {
 	puts $fp "PASS"
@@ -39,8 +39,8 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp -iopad -run prepare:check
 
 # Map Xilinx tech library to 7-series VPR tech library.
-read_verilog -lib ./techmaps/cells_sim.v
-techmap -map  ./techmaps/cells_map.v
+read_verilog -lib [file dirname $::env(DESIGN_TOP)]/techmaps/cells_sim.v
+techmap -map  [file dirname $::env(DESIGN_TOP)]/techmaps/cells_map.v
 
 # opt_expr -undriven makes sure all nets are driven, if only by the $undef
 # net.
@@ -51,5 +51,5 @@
 stat
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
-write_blif -attr -param -cname -conn pll.eblif
+write_json [test_output_path "pll.json"]
+write_blif -attr -param -cname -conn [test_output_path "pll.eblif"]
diff --git a/sdc-plugin/tests/counter/counter.tcl b/sdc-plugin/tests/counter/counter.tcl
index d77f6cc..b8cd19d 100644
--- a/sdc-plugin/tests/counter/counter.tcl
+++ b/sdc-plugin/tests/counter/counter.tcl
@@ -16,11 +16,11 @@
 propagate_clocks
 
 # Write the clocks to file
-set fh [open $::env(DESIGN_TOP).txt w]
+set fh [open [test_output_path "counter.txt"] w]
 puts $fh [get_clocks]
 puts $fh [get_clocks -include_generated_clocks]
 close $fh
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
-write_json $::env(DESIGN_TOP).json
+write_sdc [test_output_path "counter.sdc"]
+write_json [test_output_path "counter.json"]
diff --git a/sdc-plugin/tests/counter2/counter2.tcl b/sdc-plugin/tests/counter2/counter2.tcl
index 8f25f6f..5b01c41 100644
--- a/sdc-plugin/tests/counter2/counter2.tcl
+++ b/sdc-plugin/tests/counter2/counter2.tcl
@@ -16,10 +16,10 @@
 propagate_clocks
 
 # Write the clocks to file
-set fh [open $::env(DESIGN_TOP).txt w]
+set fh [open [test_output_path "counter2.txt"] w]
 set clocks [get_clocks]
 puts $fh $clocks
 close $fh
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "counter2.sdc"]
diff --git a/sdc-plugin/tests/get_clocks/get_clocks.tcl b/sdc-plugin/tests/get_clocks/get_clocks.tcl
index 468e1cc..3dd8e23 100644
--- a/sdc-plugin/tests/get_clocks/get_clocks.tcl
+++ b/sdc-plugin/tests/get_clocks/get_clocks.tcl
@@ -18,7 +18,7 @@
 propagate_clocks
 
 # Write the clocks to file
-set fh [open $::env(DESIGN_TOP).txt w]
+set fh [open [test_output_path "get_clocks.txt"] w]
 
 puts $fh [get_clocks]
 
diff --git a/sdc-plugin/tests/period_check/period_check.tcl b/sdc-plugin/tests/period_check/period_check.tcl
index 74d2b61..01101ae 100644
--- a/sdc-plugin/tests/period_check/period_check.tcl
+++ b/sdc-plugin/tests/period_check/period_check.tcl
@@ -13,4 +13,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "period_check.sdc"]
diff --git a/sdc-plugin/tests/period_format_check/period_format_check.tcl b/sdc-plugin/tests/period_format_check/period_format_check.tcl
index 74d2b61..ea0ea31 100644
--- a/sdc-plugin/tests/period_format_check/period_format_check.tcl
+++ b/sdc-plugin/tests/period_format_check/period_format_check.tcl
@@ -13,4 +13,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "period_format_check.sdc"]
diff --git a/sdc-plugin/tests/pll/pll.tcl b/sdc-plugin/tests/pll/pll.tcl
index 2a0b1b8..7db8970 100644
--- a/sdc-plugin/tests/pll/pll.tcl
+++ b/sdc-plugin/tests/pll/pll.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "pll.sdc"]
diff --git a/sdc-plugin/tests/pll_approx_equal/pll_approx_equal.tcl b/sdc-plugin/tests/pll_approx_equal/pll_approx_equal.tcl
index 2a0b1b8..b877a2d 100644
--- a/sdc-plugin/tests/pll_approx_equal/pll_approx_equal.tcl
+++ b/sdc-plugin/tests/pll_approx_equal/pll_approx_equal.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "pll_approx_equal.sdc"]
diff --git a/sdc-plugin/tests/pll_dangling_wires/pll_dangling_wires.tcl b/sdc-plugin/tests/pll_dangling_wires/pll_dangling_wires.tcl
index 2a0b1b8..aa9d35e 100644
--- a/sdc-plugin/tests/pll_dangling_wires/pll_dangling_wires.tcl
+++ b/sdc-plugin/tests/pll_dangling_wires/pll_dangling_wires.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "pll_dangling_wires.sdc"]
diff --git a/sdc-plugin/tests/pll_div/pll_div.tcl b/sdc-plugin/tests/pll_div/pll_div.tcl
index 2a0b1b8..bdce1f3 100644
--- a/sdc-plugin/tests/pll_div/pll_div.tcl
+++ b/sdc-plugin/tests/pll_div/pll_div.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "pll_div.sdc"]
diff --git a/sdc-plugin/tests/pll_fbout_phase/pll_fbout_phase.tcl b/sdc-plugin/tests/pll_fbout_phase/pll_fbout_phase.tcl
index 2a0b1b8..ceef986 100644
--- a/sdc-plugin/tests/pll_fbout_phase/pll_fbout_phase.tcl
+++ b/sdc-plugin/tests/pll_fbout_phase/pll_fbout_phase.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "pll_fbout_phase.sdc"]
diff --git a/sdc-plugin/tests/pll_propagated/pll_propagated.tcl b/sdc-plugin/tests/pll_propagated/pll_propagated.tcl
index c21422d..46b8f8a 100644
--- a/sdc-plugin/tests/pll_propagated/pll_propagated.tcl
+++ b/sdc-plugin/tests/pll_propagated/pll_propagated.tcl
@@ -17,4 +17,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc -include_propagated_clocks $::env(DESIGN_TOP).sdc
+write_sdc -include_propagated_clocks [test_output_path "pll_propagated.sdc"]
diff --git a/sdc-plugin/tests/restore_from_json/restore_from_json.tcl b/sdc-plugin/tests/restore_from_json/restore_from_json.tcl
index 0753901..beb58b3 100644
--- a/sdc-plugin/tests/restore_from_json/restore_from_json.tcl
+++ b/sdc-plugin/tests/restore_from_json/restore_from_json.tcl
@@ -6,9 +6,9 @@
 synth_xilinx
 create_clock -period 10 clk
 propagate_clocks
-write_sdc $::env(DESIGN_TOP)_1.sdc
-write_json $::env(DESIGN_TOP).json
+write_sdc [test_output_path "restore_from_json_1.sdc"]
+write_json [test_output_path "restore_from_json.json"]
 
 design -push
-read_json $::env(DESIGN_TOP).json
-write_sdc $::env(DESIGN_TOP)_2.sdc
+read_json [test_output_path "restore_from_json.json"]
+write_sdc [test_output_path "restore_from_json_2.sdc"]
diff --git a/sdc-plugin/tests/set_clock_groups/set_clock_groups.tcl b/sdc-plugin/tests/set_clock_groups/set_clock_groups.tcl
index b855c2e..cefcaca 100644
--- a/sdc-plugin/tests/set_clock_groups/set_clock_groups.tcl
+++ b/sdc-plugin/tests/set_clock_groups/set_clock_groups.tcl
@@ -12,4 +12,4 @@
 set_clock_groups -group clk7 clk8 -physically_exclusive -group clk9 clk10
 set_clock_groups -quiet -group clk11 clk12 -asynchronous -group clk13 clk14
 
-write_sdc set_clock_groups.sdc
+write_sdc [test_output_path "set_clock_groups.sdc"]
diff --git a/sdc-plugin/tests/set_false_path/set_false_path.tcl b/sdc-plugin/tests/set_false_path/set_false_path.tcl
index 1a45ca5..29c0178 100644
--- a/sdc-plugin/tests/set_false_path/set_false_path.tcl
+++ b/sdc-plugin/tests/set_false_path/set_false_path.tcl
@@ -18,4 +18,4 @@
 # -through bottom_inst/I
 set_false_path -through bottom_inst.I
 
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "set_false_path.sdc"]
diff --git a/sdc-plugin/tests/set_max_delay/set_max_delay.tcl b/sdc-plugin/tests/set_max_delay/set_max_delay.tcl
index 77bc0a0..92d4c55 100644
--- a/sdc-plugin/tests/set_max_delay/set_max_delay.tcl
+++ b/sdc-plugin/tests/set_max_delay/set_max_delay.tcl
@@ -15,4 +15,4 @@
 # -from clk to bottom_inst/I
 set_max_delay 3 -from clk -to bottom_inst.I
 
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "set_max_delay.sdc"]
diff --git a/sdc-plugin/tests/waveform_check/waveform_check.tcl b/sdc-plugin/tests/waveform_check/waveform_check.tcl
index 74d2b61..63bbe29 100644
--- a/sdc-plugin/tests/waveform_check/waveform_check.tcl
+++ b/sdc-plugin/tests/waveform_check/waveform_check.tcl
@@ -13,4 +13,4 @@
 propagate_clocks
 
 # Write out the SDC file after the clock propagation step
-write_sdc $::env(DESIGN_TOP).sdc
+write_sdc [test_output_path "waveform_check.sdc"]
diff --git a/selection-plugin/tests/counter/counter.tcl b/selection-plugin/tests/counter/counter.tcl
index f2caee5..0361a84 100644
--- a/selection-plugin/tests/counter/counter.tcl
+++ b/selection-plugin/tests/counter/counter.tcl
@@ -3,7 +3,7 @@
 yosys -import  ;# ingest plugin commands
 
 proc selection_to_tcl_list_through_file { selection } {
-    set file_name "[pid].txt"
+    set file_name [test_output_path "[pid].txt"]
     select $selection -write $file_name
     set fh [open $file_name r]
     set result [list]
@@ -31,7 +31,7 @@
 hierarchy -check -auto-top
 
 # Test the selection command and write results to file
-set rfh [open counter.txt w]
+set rfh [open [test_output_path "counter.txt"] w]
 
 set selection_tests [list "t:*" "w:*" "*"]
 foreach test $selection_tests {
diff --git a/test-utils/test-utils.tcl b/test-utils/test-utils.tcl
new file mode 100644
index 0000000..cc215ae
--- /dev/null
+++ b/test-utils/test-utils.tcl
@@ -0,0 +1,7 @@
+# Utility functions to be used in tests.
+
+# Return path where the test output file "filename"
+# is to be written.
+proc test_output_path { filename } {
+    return "$::env(TEST_OUTPUT_PREFIX)${filename}"
+}
diff --git a/xdc-plugin/tests/counter/counter.tcl b/xdc-plugin/tests/counter/counter.tcl
index 0256fc6..1eca366 100644
--- a/xdc-plugin/tests/counter/counter.tcl
+++ b/xdc-plugin/tests/counter/counter.tcl
@@ -10,7 +10,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 #Read the design constraints
-read_xdc -part_json ../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+read_xdc -part_json [file dirname $::env(DESIGN_TOP)]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
+write_json [test_output_path "counter.json"]
diff --git a/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl b/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
index 0256fc6..fdbe896 100644
--- a/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
+++ b/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
@@ -10,7 +10,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 #Read the design constraints
-read_xdc -part_json ../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+read_xdc -part_json [file dirname $::env(DESIGN_TOP)]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
+write_json [test_output_path "io_loc_pairs.json"]
diff --git a/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl b/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
index a0bd85b..5bdef63 100644
--- a/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
+++ b/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
@@ -10,7 +10,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 #Read the design constraints
-read_xdc -part_json ../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+read_xdc -part_json [file dirname [info script]]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
+write_json [test_output_path "minilitex_ddr_arty.json"]
diff --git a/xdc-plugin/tests/package_pins/package_pins.tcl b/xdc-plugin/tests/package_pins/package_pins.tcl
index 4f57399..796b5ed 100644
--- a/xdc-plugin/tests/package_pins/package_pins.tcl
+++ b/xdc-plugin/tests/package_pins/package_pins.tcl
@@ -9,7 +9,7 @@
 synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
 
 #Read the design constraints
-read_xdc -part_json ../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+read_xdc -part_json [file dirname [info script]]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
+write_json [test_output_path "package_pins.json"]
diff --git a/xdc-plugin/tests/port_indexes/port_indexes.tcl b/xdc-plugin/tests/port_indexes/port_indexes.tcl
index 44cc45a..ba7d15c 100644
--- a/xdc-plugin/tests/port_indexes/port_indexes.tcl
+++ b/xdc-plugin/tests/port_indexes/port_indexes.tcl
@@ -13,7 +13,7 @@
 	rename unknown ""
 }
 proc unknown args {return "'unknown' proc command handler"}
-set fp [open "port_indexes.txt" "w"]
+set fp [open [test_output_path "port_indexes.txt"] "w"]
 if {[catch {invalid command} result]} {
 	close $fp
 	error "Command should be handled by the 'unknown' proc"
@@ -21,7 +21,7 @@
 	puts $fp $result
 }
 #Read the design constraints
-read_xdc -part_json ../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+read_xdc -part_json [file dirname [info script]]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
 
 if {[catch {invalid command} result]} {
 	close $fp
@@ -32,4 +32,4 @@
 close $fp
 
 # Write the design in JSON format.
-write_json $::env(DESIGN_TOP).json
+write_json [test_output_path "port_indexes.json"]