#
# \brief  Test to start and call RPC entrypoint on all available CPUs
# \author Stefan Kalkowski
# \author Norman Feske
# \author Alexander Boettcher
#

if { [get_cmd_switch --autopilot] && [have_include "power_on/qemu"] } {
	puts "Run script does not support autopilot mode on Qemu"
	exit 0
}

if { [have_spec muen] } {
	puts "Run script is not supported on this platform"
	exit 0
}

build "core init test/smp"

create_boot_directory

install_config {
	<config>
		<parent-provides>
			<service name="LOG"/>
			<service name="CPU"/>
			<service name="ROM"/>
			<service name="PD"/>
		</parent-provides>
		<default-route>
			<any-service> <parent/> </any-service>
		</default-route>
		<default caps="100"/>
		<start name="test-smp">
			<resource name="RAM" quantum="10M"/>
		</start>
	</config>
}

build_boot_image "core ld.lib.so init test-smp"

if {[have_include "power_on/qemu"]} {
	# in general we want to have at least 2 CPUs
	set want_cpus 2

	# pbxa9 - foc does only use 1 cpu even if more are configured
	# pbxa9 - hw does not support multiple CPUs
	if {[have_spec pbxa9]} { set want_cpus 1 }
	# kernels only using one CPU even if more are configured
	if {[have_spec okl4]}                       { set want_cpus 1 }
	if {[have_spec pistachio]}                  { set want_cpus 1 }
	if {[have_spec fiasco]}                     { set want_cpus 1 }
	if {[have_spec zynq]}                       { set want_cpus 1 }

	append qemu_args " -nographic  -smp $want_cpus,cores=$want_cpus "
}

# run the test
run_genode_until {\[init -\> test-smp\] --- SMP testsuite finished.*\n} 120

set cpus [regexp -inline {Detected [0-9x]+ CPU[s\.]} $output]
set cpus [regexp -all -inline {[0-9]+} $cpus]
set cpus [expr [lindex $cpus 0] * [lindex $cpus 1]]

if {[have_include "power_on/qemu"]} {
	if {$want_cpus != $cpus} {
		puts "CPU count is not as expected: $want_cpus != $cpus"
		exit 1;
	}
}

set original_output $output
grep_output {\[init -\> test-smp\] RPC:}
unify_output {transfer cap [a-f0-9]+} "transfer cap UNIFIED"
unify_output {yes - idx [a-f0-9]+} "yes - idx UNIFIED"
unify_output {\- received cap [a-f0-9]+} "- received cap UNIFIED"

set good_string {[init -> test-smp] RPC: --- test started ---
}
for {set r 0} {$r < $cpus} {incr r} {
	append good_string {[init -> test-smp] RPC: call server on CPU }
	append good_string "$r\n"
	append good_string {[init -> test-smp] RPC: function test_untyped: got value }
	append good_string "$r\n"
}
for {set r 0} {$r < $cpus} {incr r} {
	append good_string {[init -> test-smp] RPC: call server on CPU }
	append good_string "$r - transfer cap UNIFIED\n"
	append good_string {[init -> test-smp] RPC: function test_cap: capability is valid ? yes - idx UNIFIED}
	append good_string "\n"
}
for {set r 0} {$r < $cpus} {incr r} {
	append good_string {[init -> test-smp] RPC: call server on CPU }
	append good_string "$r - transfer cap UNIFIED\n"
	append good_string {[init -> test-smp] RPC: function test_cap_reply: capability is valid ? yes - idx UNIFIED}
	append good_string "\n"
	append good_string {[init -> test-smp] RPC: got from server on CPU }
	append good_string "$r - received cap UNIFIED\n"
}
compare_output_to $good_string
puts "RPC test: passed"

set output $original_output
grep_output {\[init -\> test-smp\] Affinity: Round}
set rounds "10"
set good_string {}
for {set r 0} {$r <= $rounds} {incr r} {
	append good_string {[init -> test-smp] Affinity: Round } 
	append good_string [format "%02d" $r]
	append good_string ":"
	for {set i 0} {$i < $cpus} {incr i} {
		append good_string "  A"
	}
	append good_string "\n"
}
compare_output_to $good_string
puts "Affinity test: passed"

set output $original_output
grep_output {no RM attachment }
unify_output {pf_addr=0x[a-f0-9]+} "ADDR"
unify_output {pf_ip=0x[a-f0-9]+} "IP"
set good_string ""
for {set r 1} {$r < $cpus} {incr r} {
	append good_string {no RM attachment (READ ADDR IP from pager_object: pd='init -> test-smp' thread='tlb_thread')}
	append good_string "\n"
}
compare_output_to $good_string
puts "TLB test: passed"