com.github.croesch.micro_debug.console.TraceManager Maven / Gradle / Ivy
/*
* Copyright (C) 2011-2012 Christian Roesch
*
* This file is part of micro-debug.
*
* micro-debug 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 3 of the License, or
* (at your option) any later version.
*
* micro-debug 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 micro-debug. If not, see .
*/
package com.github.croesch.micro_debug.console;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import com.github.croesch.micro_debug.annotation.NotNull;
import com.github.croesch.micro_debug.commons.Printer;
import com.github.croesch.micro_debug.commons.Utils;
import com.github.croesch.micro_debug.i18n.Text;
import com.github.croesch.micro_debug.mic1.api.IReadableMemory;
import com.github.croesch.micro_debug.mic1.controlstore.MicroInstruction;
import com.github.croesch.micro_debug.mic1.controlstore.MicroInstructionDecoder;
import com.github.croesch.micro_debug.mic1.register.Register;
import com.github.croesch.micro_debug.settings.Settings;
/**
* Console view for the {@link com.github.croesch.micro_debug.mic1.Mic1}.
*
* @author croesch
* @since Date: Jan 15, 2012
*/
public final class TraceManager {
/** contains which registers are traced and which aren't */
@NotNull
private final Map tracingRegisters = new EnumMap(Register.class);
/** contains the old/current values of the registers */
@NotNull
private final Map tracingRegistersValues = new EnumMap(Register.class);
/** contains the variables that are currently traced */
@NotNull
private final List tracingVariables = new ArrayList();
/** determines whether the micro code is currently traced */
private boolean microTracing = false;
/** determines whether the macro code is currently traced */
private boolean macroTracing = false;
/** the main memory of the processor being traced */
@NotNull
private final IReadableMemory memory;
/**
* A manager that is able to trace some things of the processors current state.
*
* @since Date: Feb 8, 2012
* @param mem the main memory of the processor, mustn't be null
*/
public TraceManager(final IReadableMemory mem) {
if (mem == null) {
throw new IllegalArgumentException();
}
this.memory = mem;
}
/**
* Lists the values of all {@link Register}s.
*
* @since Date: Jan 15, 2012
*/
public void listAllRegisters() {
for (final Register r : Register.values()) {
listRegister(r);
}
}
/**
* Lists the value of a single {@link Register}.
*
* @since Date: Jan 15, 2012
* @param r the {@link Register} to print with its value.
*/
public void listRegister(final Register r) {
if (r != null) {
Printer.println(Text.REGISTER_VALUE.text(String.format("%-4s", r), Utils.toHexString(r.getValue())));
}
}
/**
* Performs to trace all {@link Register}s.
*
* @since Date: Jan 15, 2012
*/
public void traceRegister() {
for (final Register r : Register.values()) {
traceRegister(r);
}
}
/**
* Performs to trace the given {@link Register}.
*
* @since Date: Jan 15, 2012
* @param r the {@link Register} to trace.
*/
public void traceRegister(final Register r) {
if (r != null) {
this.tracingRegisters.put(r, Boolean.TRUE);
this.tracingRegistersValues.put(r, Integer.valueOf(r.getValue()));
}
}
/**
* Performs to not trace any {@link Register}.
*
* @since Date: Jan 15, 2012
*/
public void untraceRegister() {
for (final Register r : Register.values()) {
untraceRegister(r);
}
}
/**
* Performs to not trace the given {@link Register} anymore.
*
* @since Date: Jan 15, 2012
* @param r the {@link Register} not being traced anymore.
*/
public void untraceRegister(final Register r) {
if (r != null) {
this.tracingRegisters.put(r, Boolean.FALSE);
}
}
/**
* Returns whether the given {@link Register} is currently traced.
*
* @since Date: Jan 15, 2012
* @param r the {@link Register} to check, if it's traced
* @return true
, if the {@link Register} is currently traced
* false
otherwise.
*/
public boolean isTracing(final Register r) {
return this.tracingRegisters.containsKey(r) && this.tracingRegisters.get(r);
}
/**
* Performs to trace the micro code.
*
* @since Date: Jan 21, 2012
*/
public void traceMicro() {
this.microTracing = true;
}
/**
* Performs to not trace the micro code anymore.
*
* @since Date: Jan 21, 2012
*/
public void untraceMicro() {
this.microTracing = false;
}
/**
* Performs to trace the micro code.
*
* @since Date: Jan 21, 2012
*/
public void traceMacro() {
this.macroTracing = true;
}
/**
* Performs to not trace the macro code anymore.
*
* @since Date: Feb 3, 2012
*/
public void untraceMacro() {
this.macroTracing = false;
}
/**
* Returns whether the micro code is currently traced.
*
* @since Date: Jan 21, 2012
* @return true
, if the micro code is currently traced
* false
otherwise.
*/
public boolean isTracingMicro() {
return this.microTracing;
}
/**
* Returns whether the macro code is currently traced.
*
* @since Date: Feb 3, 2012
* @return true
, if the macro code is currently traced
* false
otherwise.
*/
public boolean isTracingMacro() {
return this.macroTracing;
}
/**
* Tells the view to update itself.
*
* @since Date: Jan 15, 2012
* @param currentInstruction the instruction that is now executed
* @param macroCodeLine the formatted macro code line being executed, or null
if no new macro code line
* has been reached
*/
public void update(final MicroInstruction currentInstruction, final String macroCodeLine) {
// trace macro code
if (macroCodeLine != null && isTracingMacro()) {
Printer.println(Text.EXECUTED_CODE.text(macroCodeLine));
}
// trace micro code
if (isTracingMicro()) {
Printer.println(Text.EXECUTED_CODE.text(MicroInstructionDecoder.decode(currentInstruction)));
}
// trace register
for (final Register r : Register.values()) {
if (isTracing(r) && r.getValue() != this.tracingRegistersValues.get(r).intValue()) {
this.tracingRegistersValues.put(r, Integer.valueOf(r.getValue()));
listRegister(r);
}
}
//trace local variables
for (final MacroVariable var : this.tracingVariables) {
final int addr = getAddressOfLocalVariable(var.getNumber());
if (addr == var.getAddress()) {
final int newVal = this.memory.getWord(addr);
if (var.getValue() != newVal) {
var.setValue(newVal);
Printer.println(Text.LOCAL_VARIABLE_VALUE.text(var.getNumber(), var.getValue()));
}
}
}
}
/**
* Start tracing the value of the local variable with the given number. This will create a variable based on the
* current LV value so that we can differentiate the variable if we return from this method.
*
* @since Date: Feb 8, 2012
* @param varNum the local number of this variable as an offset to the LV.
*/
public void traceLocalVariable(final int varNum) {
if (canTraceLocalVariable(varNum) && !isTracingLocalVariable(varNum)) {
final int addr = getAddressOfLocalVariable(varNum);
this.tracingVariables.add(new MacroVariable(varNum, addr, this.memory.getWord(addr)));
}
}
/**
* Ends tracing the value of the local variable with the given number. This will remove the variable based on the
* current LV value so that we don't stop tracing a variable that is traced outside the current method.
*
* @since Date: Feb 8, 2012
* @param varNum the local number of this variable as an offset to the LV.
*/
public void untraceLocalVariable(final int varNum) {
if (canTraceLocalVariable(varNum)) {
final int addr = getAddressOfLocalVariable(varNum);
this.tracingVariables.remove(new MacroVariable(varNum, addr, 0));
}
}
/**
* Returns whether it should be possible to trace a local variable with the given number.
*
* @since Date: Feb 9, 2012
* @param varNum the number of the local variable to check
* @return true
, if there is a local variable with the given number that can be traced,
* false
otherwise
*/
private boolean canTraceLocalVariable(final int varNum) {
return isRegularLocalVariable(varNum) || isLocalVariableInMainFunction(varNum);
}
/**
* Returns whether we are currently in main function and if the given number is a valid variable in main function.
*
* @since Date: Feb 9, 2012
* @param varNum the number of the local variable
* @return true
if we are in the main function of macro code and if the given number could refer to a
* local variable in main function,
* false
otherwise
*/
private boolean isLocalVariableInMainFunction(final int varNum) {
return Register.LV.getValue() == Settings.MIC1_REGISTER_LV_DEFVAL.getValue()
&& varNum >= 0
&& varNum < Utils.getNextHigherValue(Settings.MIC1_REGISTER_LV_DEFVAL.getValue(), this.memory.getSize(),
Settings.MIC1_REGISTER_CPP_DEFVAL.getValue(),
Settings.MIC1_REGISTER_SP_DEFVAL.getValue(),
Settings.MIC1_REGISTER_PC_DEFVAL.getValue());
}
/**
* Returns whether the given number is a valid local variable, assuming to be not in the main function of the macro
* code.
*
* @since Date: Feb 9, 2012
* @param varNum the number of the local variable
* @return true
, if the given number could refer to a local variable in the current function,
* false
otherwise
*/
private boolean isRegularLocalVariable(final int varNum) {
return varNum > 0 && varNum <= getNumberOfLocalVariables();
}
/**
* Returns whether we are tracing the value of the local variable with the given number. This will also check the
* value of the LV, so that we are sure we are really tracing this variable and not a variable in a different method
* with the same local number.
*
* @since Date: Feb 8, 2012
* @param varNum the local number of this variable as an offset to the LV.
* @return true
if we are tracing the local variable with the given number in the current macro code
* method,
* false
otherwise
*/
public boolean isTracingLocalVariable(final int varNum) {
if (canTraceLocalVariable(varNum)) {
final int addr = getAddressOfLocalVariable(varNum);
return this.tracingVariables.contains(new MacroVariable(varNum, addr, 0));
}
return false;
}
/**
* Returns the number of local variables in the current method, based on the value of the LV.
*
* @since Date: Feb 8, 2012
* @return the number of local variables in the current method. Means number of parameters plus the number of local
* variables, of this method.
*/
private int getNumberOfLocalVariables() {
return this.memory.getWord(Register.LV.getValue()) - Register.LV.getValue() - 1;
}
/**
* Returns the physical address in the main memory of the local variable with the given number (in the current macro
* code method).
*
* @since Date: Feb 8, 2012
* @param varNum the number of the local variable to fetch the address of
* @return the address of the local variable in the main memory
*/
private int getAddressOfLocalVariable(final int varNum) {
return Register.LV.getValue() + varNum;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy