######################################################################### # # # The CheckIt System for ELEC2041 Laboratory Experiments # # # ######################################################################### # Author: John Zaitseff # Date: 26th June, 2003 # Version: 2.4 # This file contains the necessary source code to implement the CheckIt # system for the ELEC2041 Microprocessors and Interfacing Laboratory # Experiments. It is NOT meant to be called directly by the user; rather, # individual checking scripts include this file as needed. # This script requires Expect 5.0 or later exp_version -exit 5.0 ######################################################################### # Important global variables and constants # You should only modify these variables if you know what you are doing! # In particular, the "prompt" variable is a TCL regular expression that # matches the GNU Debugger prompt. set debugger "arm-elf-gdb" set prompt {\(gdb\) +$} set logstr_pre "\n%%%%% " set logstr_post "\n(gdb) " set scriptname [file tail $argv0] set logfilename [format "/tmp/%s-%s" $scriptname \ [timestamp -format "%Y%m%d%H%M%S"]] #trap exit {SIGINT SIGTERM} #trap {exec kill -9 $pid; close} {SIGINT SIGTERM} set timeout 20 ######################################################################### proc logmsg {msg {use_post {1}}} { global logstr_pre logstr_post logfile send_log -- $logstr_pre send_log -- $msg flush $logfile if {$use_post} { send_log -- $logstr_post } } ######################################################################### # Procedure "abort" proc abort errmsg { global expect_out pid puts stderr "\nError: $errmsg\n" puts stderr "Last few lines of output are:" puts stderr $expect_out(buffer) logmsg "Error: $errmsg\n" close exit 1 } ######################################################################### # Procedure "do_cmd" # This procedure is the most fundamental one of all: it allows you to send # a command to the debugger and to compare the output with what you # expect. If the output is incorrect, the script is aborted. proc do_cmd {statusmsg cmd expstr errmsg} { global prompt debugger expect_out set use_statusmsg [expr {! [string equal $statusmsg {}]}] # Print the status message if {$use_statusmsg} { puts -nonewline "$statusmsg... " logmsg "$statusmsg..." } # Send the command to the debugger send -- $cmd send "\r" # Read in the command, echoed back by the debugger expect { -ex $cmd { } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort "$debugger is not responding" } } expect { -re {[\r\n]+} { } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort "$debugger is not responding" } } # Try to read the response expect { -re $expstr { } -re $prompt { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort $errmsg } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort $errmsg } } # Read in the prompt expect -re $prompt # Finish the procedure if {$use_statusmsg} { puts "OK" logmsg "$statusmsg... OK" } } ######################################################################### proc do_compare {statusmsg cmd expstr val {pos {0}} {isregexp {0}}} { global prompt debugger expect_out set use_statusmsg [expr {! [string equal $statusmsg {}]}] set errmsg "Could not determine the output of \"$cmd\"" # Print the status message if {$use_statusmsg} { puts -nonewline "$statusmsg... " logmsg "$statusmsg..." } # Send the command to the debugger send -- $cmd send "\r" # Read in the command, echoed back by the debugger expect { -ex $cmd { } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort "$debugger is not responding" } } expect { -re {[\r\n]+} { } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort "$debugger is not responding" } } # Try to read the response expect { -re $expstr { set actualval $expect_out($pos,string) } -re $prompt { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort $errmsg } default { if {$use_statusmsg} { puts "Failed" logmsg "$statusmsg... Failed" } abort $errmsg } } # Read in the prompt expect -re $prompt # Compare the results if {$isregexp} { if {[regexp $val $actualval]} { if {$use_statusmsg} { puts "OK" logmsg "$statusmsg... OK" } } else { if {$use_statusmsg} { puts "Failed: returned \"$actualval\"" logmsg "$statusmsg... Failed: returned \"$actualval\"" } else { puts "Failed \"$cmd\": returned \"$actualval\"" logmsg "Failed \"$cmd\": returned \"$actualval\"" } } } else { if {[string equal $val $actualval]} { if {$use_statusmsg} { puts "OK" logmsg "$statusmsg... OK" } } else { if {$use_statusmsg} { puts "Failed: returned \"$actualval\", not \"$val\"" logmsg \ "$statusmsg... Failed: returned \"$actualval\", not \"$val\"" } else { puts "Failed \"$cmd\": returned \"$actualval\", not \"$val\"" logmsg "Failed \"$cmd\": returned \"$actualval\", not \"$val\"" } } } } ######################################################################### proc do_p {statusmsg cmd val {isregexp {0}}} { set expstr {\$[0-9]+ = (.+?)[\r\n]+} do_compare $statusmsg $cmd $expstr $val 1 $isregexp } ######################################################################### proc do_x {statusmsg cmd val {isregexp {0}}} { set expstr {0x[0-9a-f]+\s*(<[^>]+>)?:\s+(.+?)[\r\n]+} do_compare $statusmsg $cmd $expstr $val 2 $isregexp } ######################################################################### proc do_continue {{cmd {}}} { if {[string equal $cmd {}]} { set cmd {continue} } do_cmd "" \ $cmd \ {Breakpoint [0-9]+, (0x[0-9a-f]+ in )?_?start } \ "Could not continue running the executable" } ######################################################################### # Simple sanity checking # Please note that the checking script must include the global variables # "default_executable" and "use_simulator". It must also define the # procedure "run_checks" that does the actual checking. if {! [info exists default_executable]} { puts stderr "Error: Variable \"default_executable\" not set" exit 1 } if {! [info exists use_simulator]} { puts stderr "Error: Variable \"use_simulator\" not set" exit 1 } if {[info procs run_checks] != {run_checks}} { puts stderr "Error: Procedure \"run_checks\" not defined" exit 1 } if {[info args run_checks] != {}} { puts stderr "Error: Procedure \"run_checks\" not defined correctly" exit 1 } # At the present time, the only debugger supported is the GNU Debugger # connected to the simulator if {$use_simulator != 1} { puts stderr \ "Error: At the present time, \"use_simulator\" must be set to 1" exit 1 } ######################################################################### # Check the command line parameters if {$argc == 0} { set executable $default_executable } elseif {$argc == 1} { set executable [lindex $argv 0] } else { puts stderr "Error: Too many command line arguments supplied" puts stderr "\nUsage:" puts stderr " $argv0 \[filename\]" exit 1 } ######################################################################### # Check if the file actually exists if {! [file exists $executable]} { puts stderr "Error: $executable: File not found" exit 1 } ######################################################################### # Start logging to the required file log_user 0 set logfile [open $logfilename w] log_file -a -open $logfile ######################################################################### # Start running the debugger on the executable puts "\nLoading $executable in $debugger" puts "Logging all output to $logfilename" logmsg "Loading $executable in $debugger" 0 logmsg "Logging all output to $logfilename" 0 logmsg \ "(Messages of this form are generated by $scriptname, not $debugger)\n\n" 0 spawn $debugger $executable expect { -re $prompt { } default { abort "Could not start $debugger" } } ######################################################################### # Set up the executable for testing do_cmd "" \ "target sim" \ "Connected to the simulator" \ "Could not connect to the simulator" do_cmd "" \ "load" \ {Transfer rate: [0-9]+ bits} \ "Could not load $executable" do_cmd "" \ "b _start" \ {Breakpoint [0-9]+ at} \ "Could not set a breakpoint at _start" do_cmd "" \ "run" \ {Breakpoint [0-9]+, (0x[0-9a-f]+ in )?_?start } \ "Could not start running $executable" do_cmd "" \ {p $lr=_start} \ {\$[0-9]+ = [0-9]+} \ "Could not set register LR to _start" ######################################################################### # Start the tests puts "Starting the tests on $executable\n" logmsg "Starting the tests on $executable" run_checks ######################################################################### # Terminate the debugger puts "\nFinishing the tests on $executable" logmsg "Finishing the tests on $executable" do_cmd "" \ "detach" \ "Ending simulator exec debugging" \ "Could not detach from the simulator" do_cmd "" \ "quit" \ {} \ "Could not quit $debugger" logmsg "End of logging output\n" 0 ######################################################################### # Finish the main script exit 0