summaryrefslogtreecommitdiff
path: root/lib/simulator/engine/engine_mcu_configuration.tcl
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
commit5b8466f7fae0e071c0f4eda13051c93313910028 (patch)
tree7061957f770e5e245ba00666dad912a2d44e7fdc /lib/simulator/engine/engine_mcu_configuration.tcl
Import Upstream version 1.3.7
Diffstat (limited to 'lib/simulator/engine/engine_mcu_configuration.tcl')
-rwxr-xr-xlib/simulator/engine/engine_mcu_configuration.tcl555
1 files changed, 555 insertions, 0 deletions
diff --git a/lib/simulator/engine/engine_mcu_configuration.tcl b/lib/simulator/engine/engine_mcu_configuration.tcl
new file mode 100755
index 0000000..7701583
--- /dev/null
+++ b/lib/simulator/engine/engine_mcu_configuration.tcl
@@ -0,0 +1,555 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# 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. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Part of simulator engine functionality.
+#
+# --------------------------------------------------------------------------
+# MCU CONFIGURATION RELATED PROCEDURES
+# --------------------------------------------------------------------------
+
+
+## Increment program overall time
+ # This function also manages watchdog and data EEPROM
+ # @parm Int num - Number of instruction cycles
+ # @return Bool - 1 == device reseted; 0 == normal
+private method increment_program_time {num} {
+ # Increment counter of instruction cycles
+ incr overall_instructions $num
+ incr run_statistics(2) $num
+
+ # Increment overall time
+ if {$controllers_conf(X2)} {
+ set num [expr {$num / 2.0}]
+ }
+ set overall_time [expr {$overall_time + $num}]
+ incr run_statistics(1) [expr {int($num * 12)}]
+ if {$clock_kHz != 0 && $clock_kHz != {}} {
+ incr run_statistics(0) [expr {int($num * (12000000.0 / $clock_kHz))}]
+ }
+
+ eeprom_controller $num
+ return [watchdog_controller]
+}
+
+## Adjust configuration acording to new value of the given bit
+ # @parm Int addr - Bit address
+ # @return void
+private method evaluate_bit {addr} {
+ if {$addr < 128} {
+ if {$sync_ena} {
+ $this Simulator_sync_reg [getRegOfBit $addr]
+ }
+ } {
+ evaluate_sfr [getRegOfBit $addr]
+ }
+}
+
+## Evaluate list of interrupt priorities acording to values of IP and IPH
+ # @return void
+private method evaluate_interrupt_priorities {} {
+ # Determinate value of Interrupt Priority High register
+ if {$feature_avaliable(iph)} {
+ set iph $sfr(183)
+ } {
+ set iph 0
+ }
+
+ # Lists of priority flags
+ set ip_0 {}
+ set ip_1 {}
+ set ip_2 {}
+ set ip_3 {}
+
+ # Lists of priority levels
+ set pl_0 {}
+ set pl_1 {}
+ set pl_2 {}
+ set pl_3 {}
+ set ip 0
+
+ # Determinate list of priority flags and priority levels in decremental order
+ foreach key {PX0 PT0 PX1 PT1 PS PT2 PC} mask {1 2 4 8 16 32 64} {
+ set ip 0
+ if {[expr {$sfr(184) & $mask}]} {
+ incr ip
+ }
+ if {[expr {$iph & $mask}]} {
+ incr ip 2
+ }
+ switch -- $ip {
+ 0 {lappend ip_0 $key}
+ 1 {lappend ip_1 $key}
+ 2 {lappend ip_2 $key}
+ 3 {lappend ip_3 $key}
+ }
+ lappend pl_${ip} $ip
+ }
+ set controllers_conf(IP) [concat $ip_3 $ip_2 $ip_1 $ip_0]
+ set controllers_conf(IP_level) [concat $pl_3 $pl_2 $pl_1 $pl_0]
+
+ # Determinate list of interrupts flags and priority levels in decremental order
+ set interrupt_pri_flg {}
+ set interrupt_pri_num {}
+ foreach flag $controllers_conf(IP) ip $controllers_conf(IP_level) {
+ switch -- $flag {
+ PS {
+ if {$feature_avaliable(uart)} {
+ lappend interrupt_pri_flg RI TI
+ lappend interrupt_pri_num $ip $ip
+ }
+ if {$feature_avaliable(spi)} {
+ lappend interrupt_pri_flg SPIF
+ lappend interrupt_pri_num $ip
+ }
+ }
+ PT2 {
+ if {!$feature_avaliable(t2)} {continue}
+ lappend interrupt_pri_flg EXF2 TF2
+ lappend interrupt_pri_num $ip $ip
+ }
+ PX0 {
+ lappend interrupt_pri_flg IE0
+ lappend interrupt_pri_num $ip
+ }
+ PT0 {
+ lappend interrupt_pri_flg TF0
+ lappend interrupt_pri_num $ip
+ }
+ PX1 {
+ lappend interrupt_pri_flg IE1
+ lappend interrupt_pri_num $ip
+ }
+ PT1 {
+ lappend interrupt_pri_flg TF1
+ lappend interrupt_pri_num $ip
+ }
+ PC {
+ if {!$feature_avaliable(acomparator)} {continue}
+ lappend interrupt_pri_flg CF
+ lappend interrupt_pri_num $ip
+ }
+ }
+ }
+
+ # Adjust interrup monitor
+ $this interrupt_monitor_intr_prior $interrupt_pri_flg
+}
+
+## Adjust configuration acording to new value of the given SFR
+ # @parm Int - Register address
+ # @parm Bool = 1 - Synchronize this SFR with external interface
+ # @return void
+private method evaluate_sfr args {
+ set addr [lindex $args 0]
+ set sync [lindex $args 1]
+
+ switch -- $addr {
+ 135 { ;# PCON 0x87
+ set SMOD0_prev $controllers_conf(SMOD0)
+
+ write_conf 135 {SMOD1 SMOD0 PWMEN POF GF1 GF0 PD IDL}
+
+ if {$SMOD0_prev != $controllers_conf(SMOD0)} {
+ $this simulator_gui_SMOD0_changed
+ }
+ }
+ 168 { ;# IE 0xA8
+ write_conf 168 {EA EC ET2 ES ET1 EX1 ET0 EX0}
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_ena_dis
+ }
+ 184 { ;# IP 0xB8
+ evaluate_interrupt_priorities
+ }
+ 152 { ;# SCON 0x98
+ write_conf 152 {- SM1 SM2 REN TB8 RB8 TI RI}
+
+ # Determinate SM0 and FE
+ if {$controllers_conf(SMOD0)} {
+ set controllers_conf(FE) [expr {($sfr(152) & 0x80) ? 1 : 0}]
+ } {
+ set controllers_conf(SM0) [expr {($sfr(152) & 0x80) ? 1 : 0}]
+ }
+
+ # Determinate UART operating mode
+ set UART_M_prev $controllers_conf(UART_M)
+ set controllers_conf(UART_M) [expr {$controllers_conf(SM0) * 2 + $controllers_conf(SM1)}]
+ if {$timer_0_running && $UART_M_prev != $controllers_conf(UART_M)} {
+ $this simulator_invalid_uart_mode_change $pc $Line($pc)
+ internal_shutdown
+ }
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags]
+ }
+ 136 { ;# TCON 0x88
+ write_conf 136 {TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0}
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags]
+ }
+ 137 { ;# TMOD 0x89
+ write_conf 137 {GATE1 CT1 M11 M01 GATE0 CT0 M10 M00}
+
+ set T0_MOD_prev $controllers_conf(T0_MOD)
+ set T1_MOD_prev $controllers_conf(T1_MOD)
+
+ set controllers_conf(T0_MOD) [expr {$controllers_conf(M10) * 2 + $controllers_conf(M00)}]
+ set controllers_conf(T1_MOD) [expr {$controllers_conf(M11) * 2 + $controllers_conf(M01)}]
+
+ # Manual: It is important to stop timer/counter before changing modes
+ if {$timer_0_running && $T0_MOD_prev != $controllers_conf(T0_MOD)} {
+ $this simulator_invalid_timer_mode_change 0 $pc $Line($pc)
+ internal_shutdown
+ }
+ if {$timer_1_running && $T1_MOD_prev != $controllers_conf(T1_MOD)} {
+ $this simulator_invalid_timer_mode_change 1 $pc $Line($pc)
+ internal_shutdown
+ }
+ }
+ 208 { ;# PSW 0xD0
+ set bank [expr {($sfr(208) & 24) >> 3}]
+ }
+ 224 { ;# A 0xE0
+ set A 0
+ set count 0
+ set mask 1
+ for {set i 0} {$i < 8} {incr i} {
+ if {[expr {$sfr(224) & $mask}] > 0} {
+ incr count
+ }
+ set mask [expr {$mask << 1}]
+ }
+
+ if {[expr {$count % 2}] == 1} {
+ setBit $symbol(P) 1
+ } {
+ setBit $symbol(P) 0
+ }
+ }
+
+ 162 { ;# AUXR1 0xA2
+ set DPS_org $controllers_conf(DPS)
+ write_conf 162 {- - - - - - - DPS}
+
+ # Switch visible dual DPTR
+ if {!$feature_avaliable(hddptr)} {
+ if {$controllers_conf(DPS)} {
+ set DPL {DP1L}
+ set DPH {DP1H}
+ } {
+ set DPL {DP0L}
+ set DPH {DP0H}
+ }
+
+ # Switch hidden dual DPTR
+ } elseif {$DPS_org != $controllers_conf(DPS)} {
+ if {$DPS_org} {
+ set hidden_DPTR1 [list $sfr($symbol(DP0L)) $sfr($symbol(DP0H))]
+ } {
+ set hidden_DPTR0 [list $sfr($symbol(DP0L)) $sfr($symbol(DP0H))]
+ }
+ if {$controllers_conf(DPS)} {
+ set sfr($symbol(DP0L)) [lindex $hidden_DPTR1 0]
+ set sfr($symbol(DP0H)) [lindex $hidden_DPTR1 1]
+ } {
+ set sfr($symbol(DP0L)) [lindex $hidden_DPTR0 0]
+ set sfr($symbol(DP0H)) [lindex $hidden_DPTR0 1]
+ }
+ if {$sync_ena} {
+ $this Simulator_GUI_sync S $symbol(DP0L)
+ $this Simulator_GUI_sync S $symbol(DP0H)
+ }
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change S $symbol(DP0L)
+ stepback_reg_change S $symbol(DP0H)
+ }
+ }
+ }
+ 142 { ;# AUXR 0x8E
+ if {$feature_avaliable(wdtcon)} {
+ if {$feature_avaliable(intelpe)} {
+ write_conf 142 {- - - - - - IPE DISALE}
+ } {
+ write_conf 142 {- - - - - - EXTRAM DISALE}
+ }
+ } {
+ write_conf 142 {- - - WDIDLE DISRTO - EXTRAM DISALE}
+ }
+ }
+ 166 { ;# WDTRST 0xA6
+ if {$controllers_conf(HWDT)} {
+ if {$sfr(166) == 225 && $wdtrst_prev_val == 30} {
+ set controllers_conf(WatchDogTimer) 1
+ set watchdog_value -$time
+
+ if {$feature_avaliable(wdtcon)} {
+ set controllers_conf(WDTEN) 1
+ set sfr(167) [expr {$sfr(167) | 1}]
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change S 167
+ }
+ if {$sync_ena} {
+ $this Simulator_GUI_sync S 167
+ }
+ }
+ }
+ set wdtrst_prev_val $sfr(166)
+ }
+ }
+ 200 { ;# T2CON 0xC8
+ write_conf 200 {TF2 EXF2 RCLK TCLK EXEN2 TR2 CT2 CPRL2}
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags]
+ }
+ 201 { ;# T2MOD 0xC9
+ write_conf 201 {- - - - - - T2OE DCEN}
+ }
+ 143 { ;# CLKREG/CKCON 0x8F
+ write_conf 143 {- - - - - - PWDEX X2}
+ }
+ 151 { ;# ACSR 0x97
+ write_conf 151 {- - - CF CEN CM2 CM1 CM0}
+
+ set controllers_conf(AC_MOD) [expr {
+ $controllers_conf(CM0) * 1 +
+ $controllers_conf(CM1) * 2 +
+ $controllers_conf(CM2) * 4
+ }]
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags]
+ }
+ 183 { ;# IPH 0xB7
+ evaluate_interrupt_priorities
+ }
+ 213 { ;# SPCR 0xD5
+ write_conf 213 {SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0}
+ }
+ 170 { ;# SPSR 0xAA
+ write_conf 170 {SPIF WCOL LDEN - - - DISSO ENH}
+
+ # Inform interrupt monitor
+ $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags]
+ }
+ 167 { ;# WDTCON/WDTPRG 0xA7
+ if {$feature_avaliable(wdtprg)} {
+ write_conf 167 {- - - - - PS2 PS1 PS0}
+ } {
+ write_conf 167 {PS2 PS1 PS0 WDIDLE DISRTO HWDT WSWRST WDTEN}
+ }
+ set controllers_conf(WatchDogPrescaler) 0
+ if {$controllers_conf(PS2)} {
+ incr controllers_conf(WatchDogPrescaler) 4
+ }
+ if {$controllers_conf(PS1)} {
+ incr controllers_conf(WatchDogPrescaler) 2
+ }
+ if {$controllers_conf(PS0)} {
+ incr controllers_conf(WatchDogPrescaler) 1
+ }
+ set controllers_conf(WatchDogPrescaler) \
+ [expr {int(pow(2,$controllers_conf(WatchDogPrescaler)))}]
+ }
+ 150 { ;# EECON 0x96
+ set bit_RDYBSY $controllers_conf(RDYBSY)
+ set bit_WRTINH $controllers_conf(WRTINH)
+
+ write_conf 150 {- - EELD EEMWE EEMEN DPS RDYBSY WRTINH}
+
+ # Bits RDYBSY and WRTINH are READ-ONLY
+ if {
+ $controllers_conf(RDYBSY) != $bit_RDYBSY
+ ||
+ $controllers_conf(WRTINH) != $bit_WRTINH
+ } then {
+ set sfr(150) [expr {(($sfr(150) & 0xFC) | $bit_RDYBSY * 2) | $bit_WRTINH}]
+ }
+ set controllers_conf(RDYBSY) $bit_RDYBSY
+ set controllers_conf(WRTINH) $bit_WRTINH
+
+ if {$controllers_conf(DPS)} {
+ set DPL {DP1L}
+ set DPH {DP1H}
+ } {
+ set DPL {DP0L}
+ set DPH {DP0H}
+ }
+ }
+ default { ;# Nothing to do ...
+ }
+ }
+
+ # Synchronize with an external interface
+ if {$sync_ena && $sync != {0}} {
+ $this Simulator_GUI_sync S $addr
+ }
+}
+
+## Modify configuration
+ # @parm Int addr - Source register
+ # @parm List key_list - List of keys for array controllers_conf
+ # @return void
+private method write_conf {addr key_list} {
+ set mask 256
+ foreach key $key_list {
+
+ set mask [expr {$mask >> 1}]
+ if {$key == {-}} {continue}
+
+ if {[expr {$sfr($addr) & $mask}] == 0} {
+ set controllers_conf($key) 0
+ } {
+ set controllers_conf($key) 1
+ }
+ }
+}
+
+## Increment program counter
+ # @parm Int val - Value to increment by
+ # @return void
+private method incr_pc {val} {
+ set pc [incr_16b $pc $val]
+}
+
+## Increment 16 bit value
+ # @parm Int val - Value to increment
+ # @parm Int byVal - Value to increment by
+ # @return Int - 16 bit result
+private method incr_16b {val byVal} {
+ incr val $byVal
+ if {$val > 65535} {
+ incr val -65536
+ } elseif {$val < 0} {
+ incr val 65536
+ }
+ return $val
+}
+
+## Increment 8 bit value
+ # @parm Char type - D == Direct addressing; I == Indirect addressing
+ # @parm Int addr - Register to increment
+ # @parm Int val - Value to increment by
+ # @return Bool - 0 == successful; 1 == failed
+private method incr_8b {type addr val} {
+ if {[check_address_validity $type $addr]} {return 1}
+
+ # Indirect addressing
+ if {$type == {I} || $addr < 128} {
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change I $addr
+ }
+
+ incr ram($addr) $val
+ if {$ram($addr) > 255} {
+ incr ram($addr) -256
+ } elseif {$ram($addr) < 0} {
+ incr ram($addr) 256
+ }
+ if {$sync_ena} {
+ $this Simulator_sync_reg $addr
+ }
+
+ # Direct addressing
+ } else {
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change S $addr
+ }
+
+ incr sfr($addr) $val
+ set val [read_sfr $addr]
+ if {$val > 255} {
+ incr sfr($addr) -256
+ } elseif {$val < 0} {
+ incr sfr($addr) 256
+ }
+ if {$sync_ena} {
+ $this Simulator_GUI_sync S $addr
+ }
+ }
+ return 0
+}
+
+## Pop value from stack
+ # @return Int - result
+private method stack_pop {} {
+ if {[check_address_validity I $sfr(129)]} {
+ set result [undefined_octet]
+ } {
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change I $sfr(129)
+ }
+ set result $ram($sfr(129)) ;# 129d == 0x81 == SP
+ }
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change S 129
+ }
+ incr sfr(129) -1
+ if {$sfr(129) < 0} {
+ set sfr(129) 255
+ if {!${::Simulator::ignore_stack_underflow}} {
+ $this simulator_stack_warning under $pc [lindex $Line($pc) 0]
+ internal_shutdown
+ }
+ }
+
+ evaluate_sfr 129
+ $this stack_monitor_pop
+
+ return $result
+}
+
+## Push value onto stack
+ # @parm Int - Value to push onto stack
+ # @return void
+public method stack_push {val} {
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change S 129
+ }
+ incr sfr(129) ;# 129d == 0x81 == SP
+ if {$sfr(129) > 255} {
+ set sfr(129) 0
+ if {!${::Simulator::ignore_stack_overflow}} {
+ $this simulator_stack_warning over $pc [lindex $Line($pc) 0]
+ internal_shutdown
+ }
+ }
+ if {[check_address_validity I $sfr(129)]} {
+ return
+ } {
+ if {${::Simulator::reverse_run_steps}} {
+ stepback_reg_change I $sfr(129)
+ }
+ set ram($sfr(129)) $val
+ if {$sync_ena} {
+ $this Simulator_sync_reg $sfr(129)
+ }
+ }
+
+ evaluate_sfr 129
+ $this stack_monitor_push $sfr(129) $val
+}