#!/usr/bin/tclsh # Part of MCU 8051 IDE ( http://https://sourceforge.net/projects/mcu8051ide/ ) ############################################################################ # Copyright (C) 2011-2011 by Martin Ošmera # # martin.osmera@gmail.com # # # # Copyright (C) 2014 by Moravia Microsystems, s.r.o. # # martin.osmera@gmail.com # # # # This program is free software; you can redistribute it and#or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################ # >>> File inclusion guard if { ! [ info exists _ENGINE_TEXT_BASED_INTERFACE_TCL ] } { set _ENGINE_TEXT_BASED_INTERFACE_TCL _ # <<< File inclusion guard # -------------------------------------------------------------------------- # DESCRIPTION # # Command line interface for the simulator engine. Listens to simple commands, # like `read-sfr-by-name PCON'. Each command must be on separate line, empty # lines and everything after `#' characater are ignored. Response to every # command is either `DONE' or # `ERROR (line: ; command: ): '. Some commands # returns some values, in that case these values are printed before the `DONE' # string. Commands are case insensitive, but the same may not apply for their # arguments. # # Note: This interface is supposed to be available via main.tcl invoked with # --simulator option. That means that to access this inteface it should be # sufficient to run `mcu8051ide --simulator' command. # # List of commands: # ================ # # COMMAND DESCRIPTION # ------- ----------- # echo-on # echo-off # set-mcu # set-clock # set-xcode # set-xdata # load-code # load-code-adf # load-code-cdb # load-idata # load-xdata # load-eeprom # load-eram # dump-code # dump-idata # dump-xdata # dump-eeprom # dump-eram # write-code # write-idata # write-xdata # write-eeprom # write-eram # write-sfr # write-sfr # write-bit # read-code # read-idata # read-xdata # read-eeprom # read-eram # read-sfr # read-sfr-by-name # read-bit # step # step-back # list-changes # read-pc # write-pc # read-position # reset # run # input # output # hibernate # resume # core-dump # core-alter # exit # -------------------------------------------------------------------------- namespace eval SimulatorEngineCLI { variable command_line variable cmd_line_idx variable simulator variable line_counter variable echo variable error_reported class SimEngineWrapper { inherit Simulator_ENGINE Pale public common changed_registers [list] # TODO: get rid of these variables: public variable procData {} public variable P_option_mcu_type {} public variable P_option_mcu_xdata 0 public variable P_option_mcu_xcode 0 public variable projectPath {.} public method is_ready {} { if {[llength $procData]} { return 1 } else { return 0 } } public method Simulator_GUI_sync args { lappend changed_registers $args } public method Simulator_sync_PC_etc {} { } public method get_changed_registers {} { return $changed_registers } public method clear_changed_registers {} { set changed_registers [list] } } proc enter_main_loop {} { variable command_line variable cmd_line_idx variable simulator variable line_counter 0 variable echo 0 variable error_reported set simulator [SimEngineWrapper #auto] namespace eval ::Simulator { variable undefined_value 2 variable reverse_run_steps 100 } namespace eval ::X { variable critical_procedure_in_progress 0 } puts "READY" while {![eof stdin]} { incr line_counter set command_line [gets stdin] set command_line [regsub {#.*$} $command_line {}] set command_line [string trim $command_line] set cmd_line_idx 1 set error_reported 0 if {[catch { set command [string tolower [lindex $command_line 0]] }]} then { set tmp $command_line set command_line {} abort_now "Unable to understand line: \"$tmp\"" } # Do nothing with an empty line if {![string length $command_line]} { continue } if {$echo} { puts "> $command_line" } if {[lsearch -ascii -exact {set-mcu echo-on echo-off} $command] == -1 && ![$simulator is_ready]} { report_error "Processor type has to be specified first" continue } if {[command_switch $command]} { break } if {!$error_reported} { puts "OK" } } puts "EXITING" } proc command_switch {command} { variable echo switch -- $command { {echo-on} { expect_no_more_arguments command__echo_on } {echo-off} { expect_no_more_arguments command__echo_off } {set-mcu} { expect_string expect_no_more_arguments command__set_mcu } {set-clock} { expect_integer 1 99999 expect_no_more_arguments command__set_clock } {set-xcode} { expect_integer 0 65536 expect_no_more_arguments command__set_xcode } {set-xdata} { expect_integer 0 65536 expect_no_more_arguments command__set_xdata } {load-code} { expect_no_more_arguments command__load_code } {load-code-adf} { expect_string expect_no_more_arguments command__load_code_adf } {load-code-cdb} { expect_string expect_string expect_string expect_no_more_arguments command__load_code_cdb } {load-idata} { expect_no_more_arguments command__load_idata } {load-xdata} { expect_no_more_arguments command__load_xdata } {load-eeprom} { expect_no_more_arguments command__load_eeprom } {load-eram} { expect_no_more_arguments command__load_eram } {dump-code} { expect_no_more_arguments command__dump_code } {dump-idata} { expect_no_more_arguments command__dump_idata } {dump-xdata} { expect_no_more_arguments command__dump_xdata } {dump-eeprom} { expect_no_more_arguments command__dump_eeprom } {dump-eram} { expect_no_more_arguments command__dump_eram } {write-code} { expect_integer 0 65536 expect_integer 0 256 expect_no_more_arguments command__write_code } {write-idata} { expect_integer 0 256 expect_integer 0 256 expect_no_more_arguments command__write_idata } {write-xdata} { expect_integer 0 65536 expect_integer 0 256 expect_no_more_arguments command__write_xdata } {write-eeprom} { expect_integer 0 65536 expect_integer 0 256 expect_no_more_arguments command__write_eeprom } {write-eram} { expect_integer 0 65536 expect_integer 0 256 expect_no_more_arguments command__write_eram } {write-sfr} { expect_integer 128 256 expect_integer 0 256 expect_no_more_arguments command__write_sfr } {write-sfr} { expect_string expect_integer 0 256 expect_no_more_arguments command__write_sfr_by_name } {write-bit} { expect_integer 0 256 expect_integer 0 256 expect_no_more_arguments command__write_bit } {read-code} { expect_integer 0 65536 expect_no_more_arguments command__read_code } {read-idata} { expect_integer 0 256 expect_no_more_arguments command__read_idata } {read-xdata} { expect_integer 0 65536 expect_no_more_arguments command__read_xdata } {read-eeprom} { expect_integer 0 65536 expect_no_more_arguments command__read_eeprom } {read-eram} { expect_integer 0 65536 expect_no_more_arguments command__read_eram } {read-sfr} { expect_integer 128 256 expect_no_more_arguments command__read_sfr } {read-sfr-by-name} { expect_string expect_no_more_arguments command__read_sfr_by_name } {read-bit} { expect_integer 0 256 expect_no_more_arguments command__read_bit } {step} { expect_no_more_arguments command__step } {step-back} { expect_no_more_arguments command__step_back } {list-changes} { expect_no_more_arguments command__list_changes } {read-pc} { expect_no_more_arguments command__read_pc } {write-pc} { expect_integer 0 65536 expect_no_more_arguments command__write_pc } {read-position} { expect_no_more_arguments command__read_position } {reset} { expect_no_more_arguments command__reset } {run} { expect_no_more_arguments command__run } {input} { expect_integer 0 4 expect_no_more_arguments command__input } {output} { expect_integer 0 4 expect_no_more_arguments command__output } {hibernate} { expect_string expect_no_more_arguments command__hibernate } {resume} { expect_string expect_no_more_arguments command__resume } {core-dump} { expect_no_more_arguments command__core_dump } {core-alter} { expect_string expect_no_more_arguments command__core_alter } {exit} { expect_no_more_arguments return 1 } default { report_error "Unrecognised command: \"$command\"" } } return 0 } proc abort_now {info} { report_error $info puts "ABORTING" exit 1 } proc report_error {info} { variable error_reported variable line_counter variable command_line set error_reported 1 puts stderr "ERROR (line: $line_counter; command: [lindex $command_line 0]): $info" } proc expect_no_more_arguments {} { variable command_line variable cmd_line_idx if {[llength $command_line] > $cmd_line_idx} { abort_now "Too many aguments given to to command [lindex $command_line 0]" } } proc expect_string {{max_length {}}} { variable command_line variable cmd_line_idx set arg [lindex $command_line $cmd_line_idx] if {![string length $arg]} { abort_now "Argument missing for command [lindex $command_line 0] at index $cmd_line_idx" } elseif {$max_length != {} && [string length $arg] > $max_length} { abort_now "Agrument given to command [lindex $command_line 0] at index $cmd_line_idx is too long, mimum allowed length is $max_length" } incr cmd_line_idx } proc expect_integer {{min {}} {max {}}} { variable command_line variable cmd_line_idx set arg [lindex $command_line $cmd_line_idx] if {![string is digit -strict $arg]} { abort_now "Non integer agrument given to command [lindex $command_line 0] at index $cmd_line_idx" } elseif {($min != {} && $arg < $min) || ($max != {} && $arg > $max)} { abort_now "Integer agrument given to command [lindex $command_line 0] at index $cmd_line_idx is out of its allowed range \[$min;$max\]" } incr cmd_line_idx } proc load_hex {set_command memory_size} { variable simulator set hex_data {} while {![eof stdin]} { set line [gets stdin] append hex_data $line "\n" # Stop when EOF sequnce is found if {[string range $line 7 8] == {01}} { break } } ::IHexTools::free_resources ::IHexTools::load_hex_data $hex_data if {${::IHexTools::error_count}} { report_error ${::IHexTools::error_string} return } if {${::IHexTools::highest_addr} >= $memory_size} { report_error "You are attempting to load more data than the memory capacity allows. Capacity: $memory_size; Required: [expr {${::IHexTools::highest_addr} + 1}]" } set val {} for {set i 0} {$i < ${::IHexTools::highest_addr}} {incr i} { set val [::IHexTools::get_value $i] if {$val == -1} { set val {} } $simulator $set_command $i $val } for {} {$i < $memory_size} {incr i} { $simulator $set_command $i {} } } # ---------------------------------------------------------------------- # COMMANDS # ---------------------------------------------------------------------- proc command__echo_on {} { variable echo 1 } proc command__echo_off {} { variable echo 0 } proc command__set_mcu {} { variable simulator variable command_line set new_processor [string toupper [lindex $command_line 1]] if {[lsearch -ascii -exact [SelectMCU::get_available_processors] $new_processor] == -1} { abort_now "Unsupported processor: [lindex $command_line 1]" } $simulator configure -P_option_mcu_type $new_processor set proc_data [SelectMCU::get_processor_details $new_processor] if {$proc_data == {}} { abort_now "Internal error" } $simulator configure -procData $proc_data $simulator simulator_initialize_mcu } proc command__set_clock {} { variable simulator variable command_line $simulator setEngineClock [lindex $command_line 1] } proc command__set_xcode {} { variable simulator variable command_line set arg [lindex $command_line 1] set icode [expr {[lindex [$simulator cget -procData] 2] * 1024}] if {$arg > (0xFFFF - $icode)} { abort_now "This MCU has CODE memory limit 0x10000 B (65536)" } if {[lindex [$simulator cget -procData] 1] != {yes}} { abort_now "This MCU cannot have connected external program memory" } else { $simulator configure -P_option_mcu_xcode $arg $simulator simulator_resize_code_memory $arg } } proc command__set_xdata {} { variable simulator variable command_line set arg [lindex $command_line 1] if {[lindex [$simulator cget -procData] 0] != {yes}} { abort_now "This MCU cannot have connected external data memory" } else { $simulator configure -P_option_mcu_xdata $arg $simulator simulator_resize_xdata_memory $arg } } proc command__reset {} { variable simulator $simulator master_reset - } proc command__load_code {} { variable simulator variable command_line load_hex setCodeDEC [expr {[$simulator cget -P_option_mcu_xcode] + ([lindex [$simulator cget -procData] 2] * 1024)}] } proc command__load_code_adf {} { variable simulator variable command_line if {[catch { set file [open [lindex $command_line 1] {r}] }]} then { abort_now "Unable to open file: [lindex $command_line 1]" } $simulator load_program_from_adf $file foreach filename [$simulator simulator_get_list_of_filenames] { $simulator Simulator_import_breakpoints $filename [list] } catch { close $file } } proc command__load_code_cdb {} { variable simulator variable command_line set filename [lindex $command_line 1] set cdb_flnm [lindex $command_line 2] set ihx_flnm [lindex $command_line 3] set cdb_file {} set ihx_file {} if {![file exists $filename]} { report_error "File does not exist: \"$filename\"" return } if {[catch { set cdb_file [open $cdb_flnm {r}] }]} then { report_error "Cannot open file: \"$cdb_flnm\"" return } if {[catch { set ihx_file [open $ihx_flnm {r}] }]} then { catch {close $cdb_file} report_error "Cannot open file: \"$ihx_flnm\"" return } if {![$simulator load_program_from_cdb $filename $cdb_file $ihx_file]} { report_error ${::IHexTools::error_string} } else { foreach filename [$simulator simulator_get_list_of_filenames] { $simulator Simulator_import_breakpoints $filename [list] } } catch {close $cdb_file} catch {close $ihx_file} } proc command__load_idata {} { variable simulator variable command_line load_hex setDataDEC [lindex [$simulator cget -procData] 3] } proc command__load_xdata {} { variable simulator variable command_line load_hex setXdataDEC [$simulator cget -P_option_mcu_xdata] } proc command__load_eeprom {} { variable simulator variable command_line load_hex setEepromDEC [lindex [$simulator cget -procData] 32] } proc command__load_eram {} { variable simulator variable command_line load_hex setEramDEC [lindex [$simulator cget -procData] 8] } proc command__dump_code {} { variable simulator variable command_line set capacity [expr {[$simulator cget -P_option_mcu_xcode] + ([lindex [$simulator cget -procData] 2] * 1024)}] ::IHexTools::free_resources for {set addr 0} {$addr < $capacity} {incr addr} { ::IHexTools::content [$simulator getCode $addr] } puts -nonewline [::IHexTools::get_hex_data] } proc command__dump_idata {} { variable simulator variable command_line set capacity [lindex [$simulator cget -procData] 3] ::IHexTools::free_resources for {set addr 0} {$addr < $capacity} {incr addr} { ::IHexTools::content [$simulator getData $addr] } puts -nonewline [::IHexTools::get_hex_data] } proc command__dump_xdata {} { variable simulator variable command_line set capacity [$simulator cget -P_option_mcu_xdata] ::IHexTools::free_resources for {set addr 0} {$addr < $capacity} {incr addr} { ::IHexTools::content [$simulator getXdata $addr] } puts -nonewline [::IHexTools::get_hex_data] } proc command__dump_eeprom {} { variable simulator variable command_line set capacity [lindex [$simulator cget -procData] 32] ::IHexTools::free_resources for {set addr 0} {$addr < $capacity} {incr addr} { ::IHexTools::content [$simulator getEeprom $addr] } puts -nonewline [::IHexTools::get_hex_data] } proc command__dump_eram {} { variable simulator variable command_line set capacity [lindex [$simulator cget -procData] 8] ::IHexTools::free_resources for {set addr 0} {$addr < $capacity} {incr addr} { ::IHexTools::content [$simulator getEram $addr] } puts -nonewline [::IHexTools::get_hex_data] } proc command__write_code {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range C $addr]} { report_error "Invalid address: $addr" } else { $simulator setCodeDEC $addr $val } } proc command__write_idata {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range I $addr]} { report_error "Invalid I-DATA address: $addr" } else { $simulator setDataDEC $addr $val } } proc command__write_xdata {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range X $addr]} { report_error "Invalid X-DATA address: $addr" } else { $simulator setXdataDEC $addr $val } } proc command__write_eeprom {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range P $addr]} { report_error "Invalid EEPROM address: $addr" } else { $simulator setEepromDEC $addr $val } } proc command__write_eram {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range E $addr]} { report_error "Invalid ERAM address: $addr" } else { $simulator setEramDEC $addr $val } } proc command__write_sfr {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range S $addr]} { report_error "Invalid SFR address: $addr" } else { if {$addr == $::Simulator_ENGINE::symbol(SBUFR)} { set addr $::Simulator_ENGINE::symbol(SBUFT) } $simulator setSfrDEC $addr $val } } proc command__write_sfr_by_name {} { variable simulator variable command_line set name [lindex $command_line 1] set val [lindex $command_line 2] if {[lsearch -ascii -exact [array names ::Simulator_ENGINE::symbol] [string toupper $name]] == -1} { report_error "Invalid SFR name: $name" } else { set addr $::Simulator_ENGINE::symbol([string toupper $name]) if {![$simulator simulator_address_range S $addr]} { report_error "Invalid SFR address: $addr" } else { if {$addr == $::Simulator_ENGINE::symbol(SBUFR)} { set addr $::Simulator_ENGINE::symbol(SBUFT) } $simulator setSfrDEC $addr $val } } } proc command__write_bit {} { variable simulator variable command_line set addr [lindex $command_line 1] set val [lindex $command_line 2] if {![$simulator simulator_address_range B $addr]} { report_error "Invalid BIT address: $addr" } else { $simulator setBit $addr } } proc command__read_code {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range C $addr]} { report_error "Invalid address: $addr" } else { puts [$simulator getCodeDEC $addr] } } proc command__read_idata {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range I $addr]} { report_error "Invalid I-DATA address: $addr" } else { puts [$simulator getDataDEC $addr] } } proc command__read_xdata {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range X $addr]} { report_error "Invalid X-DATA address: $addr" } else { puts [$simulator getXdataDEC $addr] } } proc command__read_eeprom {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range P $addr]} { report_error "Invalid EEPROM address: $addr" } else { puts [$simulator getEepromDEC $addr] } } proc command__read_eram {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range E $addr]} { report_error "Invalid ERAM address: $addr" } else { puts [$simulator getEramDEC $addr] } } proc command__read_sfr {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range S $addr]} { report_error "Invalid SFR address: $addr" } else { puts [$simulator getSfrDEC $addr] } } proc command__read_sfr_by_name {} { variable simulator variable command_line set name [lindex $command_line 1] set val [lindex $command_line 2] if {[lsearch -ascii -exact [array names ::Simulator_ENGINE::symbol] [string toupper $name]] == -1} { report_error "Invalid SFR name: $name" } else { set addr $::Simulator_ENGINE::symbol([string toupper $name]) if {![$simulator simulator_address_range S $addr]} { report_error "Invalid SFR address: $addr" } else { puts [$simulator getSfrDEC $addr] } } } proc command__read_bit {} { variable simulator variable command_line set addr [lindex $command_line 1] if {![$simulator simulator_address_range B $addr]} { report_error "Invalid BIT address: $addr" } else { puts [$simulator getBit $addr] } } proc command__step {} { variable simulator $simulator clear_changed_registers $simulator step } proc command__step_back {} { variable simulator $simulator clear_changed_registers puts [$simulator stepback] } proc command__list_changes {} { variable simulator variable command_line puts [$simulator get_changed_registers] } proc command__read_pc {} { variable simulator puts [$simulator getPC] } proc command__write_pc {} { variable simulator variable command_line $simulator setPC [lindex $command_line 1] } proc command__read_position {} { variable simulator variable command_line set pos [$simulator simulator_getCurrentLine] puts "F: \"[$simulator simulator_get_filename [lindex $pos 1]]\"" puts "L: [lindex $pos 0]" puts "V: [lindex $pos 2]" puts "B: [lindex $pos 3]" } proc command__run {} { variable simulator $simulator sim_run } proc command__input {} { variable simulator variable command_line # TODO: Complete it } proc command__output {} { variable simulator variable command_line # TODO: Complete it } proc command__hibernate {} { variable simulator variable command_line # TODO: Complete it } proc command__resume {} { variable simulator variable command_line # TODO: Complete it } proc command__core_dump {} { variable simulator variable command_line # TODO: Complete it } proc command__core_alter {} { variable simulator variable command_line # TODO: Complete it } } # >>> File inclusion guard } # <<< File inclusion guard