summaryrefslogtreecommitdiffstats
path: root/src/electronics/gpsimprocessor.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/electronics/gpsimprocessor.h')
-rw-r--r--src/electronics/gpsimprocessor.h393
1 files changed, 393 insertions, 0 deletions
diff --git a/src/electronics/gpsimprocessor.h b/src/electronics/gpsimprocessor.h
new file mode 100644
index 0000000..0650fd9
--- /dev/null
+++ b/src/electronics/gpsimprocessor.h
@@ -0,0 +1,393 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#include "config.h"
+#ifndef NO_GPSIM
+
+#ifndef GPSIMPROCESSOR_H
+#define GPSIMPROCESSOR_H
+
+#include "sourceline.h"
+
+#include <qmap.h>
+#include <qvaluevector.h>
+#include <qobject.h>
+#include <qvaluelist.h>
+
+class DebugLine;
+class GpsimProcessor;
+class MicroInfo;
+class pic_processor; // from gpsim
+class Register;
+class RegisterMemoryAccess;
+
+typedef QMap<SourceLine, SourceLine> SourceLineMap;
+typedef QMap<int, QString> QStringMap;
+typedef QValueList<int> IntList;
+
+
+class DebugLine : public SourceLine
+{
+ public:
+ DebugLine();
+ DebugLine( const QString & fileName, int line );
+ /**
+ * Whether or not to break when we reach this line.
+ */
+ bool isBreakpoint() const { return m_bIsBreakpoint; }
+ /**
+ * Set whether or not to break when we reach this line.
+ */
+ void setBreakpoint( bool breakpoint ) { m_bIsBreakpoint = breakpoint; }
+ /**
+ * Used for efficiency purposes by GpsimProcessor. Sets a flag.
+ */
+ void markAsDeleted() { m_bMarkedAsDeleted = true; }
+ /**
+ * Used for efficiency purposes by GpsimProcessor.
+ */
+ bool markedAsDeleted() const { return m_bMarkedAsDeleted; }
+
+ protected:
+ bool m_bIsBreakpoint;
+ bool m_bMarkedAsDeleted;
+
+ private:
+ DebugLine( const DebugLine & dl );
+ DebugLine & operator = ( const DebugLine & dl );
+};
+
+
+/**
+@short Stores info from gpsim register, used to hide gpsim interface
+@author David Saxton
+*/
+class RegisterInfo : public QObject
+{
+ Q_OBJECT
+ public:
+ RegisterInfo( Register * reg );
+
+ enum RegisterType
+ {
+ Invalid,
+ Generic,
+ File,
+ SFR,
+ Breakpoint
+ };
+
+ RegisterType type() const { return m_type; }
+ QString name() const { return m_name; }
+ unsigned value() const;
+ static QString toString( RegisterType type );
+
+ /**
+ * Checks to see if the value has changed; if so, emit new value.
+ */
+ void update();
+
+ signals:
+ void valueChanged( unsigned newValue );
+
+ protected:
+ QString m_name;
+ RegisterType m_type;
+ Register * m_pRegister;
+ unsigned m_prevEmitValue;
+};
+
+
+/**
+@short Stores information about a set of registers, used to hide gpsim interface.
+@author David Saxton
+*/
+class RegisterSet
+{
+ public:
+ RegisterSet( pic_processor * picProcessor );
+ ~RegisterSet();
+
+ /**
+ * Calls update for each RegisterInfo in this set.
+ */
+ void update();
+ /**
+ * Returns the number of registers.
+ */
+ unsigned size() const { return m_registers.size(); }
+
+ RegisterInfo * fromAddress( unsigned address );
+ RegisterInfo * fromName( const QString & name );
+
+ protected:
+ typedef QMap< QString, RegisterInfo * > RegisterInfoMap;
+ RegisterInfoMap m_nameToRegisterMap;
+ QValueVector< RegisterInfo * > m_registers;
+};
+
+
+/**
+@author David Saxton
+*/
+class GpsimDebugger : public QObject
+{
+ friend class GpsimProcessor;
+ Q_OBJECT
+
+ public:
+ enum Type
+ {
+ AsmDebugger = 0,
+ HLLDebugger = 1
+ };
+
+ GpsimDebugger( Type type, GpsimProcessor * gpsim );
+ ~GpsimDebugger();
+
+ GpsimProcessor * gpsim() const { return m_pGpsim; }
+
+ /**
+ * When an assembly file was generated by a high level language compiler
+ * like SDCC, it will insert markers like ";#CSRC" that show which line
+ * of source-code generated the given set of assembly instructions. This
+ * matches up the assembly file lines with the associated source file
+ * lines.
+ */
+ void associateLine( const QString & sourceFile, int sourceLine, const QString & assemblyFile, int assemblyLine );
+ /**
+ * Check to see if we've hit a breakpoint or similar; if so, this
+ * function will stop the execution of the PIC program.
+ */
+ void checkForBreak();
+ /**
+ * Sets the breakpoints used for the given file to exactly those that
+ * are contained in this list. Breakpoints for other files are not
+ * affected.
+ * @param path the location of the file (which gpsim must recognise).
+ */
+ void setBreakpoints( const QString & path, const IntList & lines );
+ /**
+ * Sets / removes the breakpoint at the given line
+ */
+ void setBreakpoint( const QString & path, int line, bool isBreakpoint );
+ /**
+ * Returns the current source line that gpsim is at. By default, this
+ * will be the corresponding assembly line. That can be overwritten
+ * using mapAddressBlockToLine.
+ */
+ SourceLine currentLine();
+ /**
+ * Returns a pointer to the debug info for the current line.
+ */
+ DebugLine * currentDebugLine();
+ /**
+ * @return the program address for the given line (or -1 if no such
+ * line).
+ */
+ int programAddress( const QString & path, int line );
+ /**
+ * Step into the next program line.
+ */
+ void stepInto();
+ /**
+ * Step over the next program instruction. If we are currently running,
+ * this function will do nothing. Otherwise, it will record the current
+ * stack level, step, and if the new stack level is <= the initial level
+ * then return - otherwise, this processor will set a breakpoint for
+ * stack levels <= initial, and go to running mode.
+ */
+ void stepOver();
+ /**
+ * Similar to stepOver, except we break when the stack level becomes <
+ * the initial stack level (instead of <= initial).
+ */
+ void stepOut();
+
+ signals:
+ /**
+ * Emitted when a line is reached. By default, this is the line of the
+ * input assembly file; however, the line associated with an address in
+ * the PIC memory can be changed with mapAddressBlockToLine.
+ */
+ void lineReached( const SourceLine & sourceLine );
+
+ protected slots:
+ void gpsimRunningStatusChanged( bool isRunning );
+
+ protected:
+ void initAddressToLineMap();
+ void stackStep( int dl );
+ void emitLineReached();
+
+ int m_stackLevelLowerBreak; // Set by step-over, for when the stack level decreases to the one given
+ SourceLine m_previousAtLineEmit; // Used for working out whether we should emit a new line reached signal
+ DebugLine ** m_addressToLineMap;
+ DebugLine * m_pBreakFromOldLine;
+ GpsimProcessor * m_pGpsim;
+ Type m_type;
+ unsigned m_addressSize;
+ SourceLineMap m_sourceLineMap; // assembly <--> High level language
+};
+
+
+/**
+@author David Saxton
+*/
+class GpsimProcessor : public QObject
+{
+ friend class GpsimDebugger;
+ Q_OBJECT
+
+ public:
+ /**
+ * Create a new gpsim processor. After calling this constructor, you
+ * should always call codLoadStatus() to ensure that the cod file was
+ * loaded successfully.
+ */
+ GpsimProcessor( QString symbolFile, QObject *parent = 0 );
+ ~GpsimProcessor();
+
+ void setDebugMode( GpsimDebugger::Type mode ) { m_debugMode = mode; }
+ GpsimDebugger * currentDebugger() const { return m_pDebugger[m_debugMode]; }
+
+ enum CodLoadStatus
+ {
+ CodSuccess,
+ CodFileNotFound,
+ CodUnrecognizedProcessor,
+ CodFileNameTooLong,
+ CodLstNotFound,
+ CodBadFile,
+ CodFileUnreadable,
+ CodFailure,
+ CodUnknown // Should never be this, but just in case load_symbol_file returns something funny
+ };
+
+ enum InstructionType
+ {
+ LiteralOp,
+ BitOp,
+ RegisterOp,
+ UnknownOp,
+ };
+
+ /**
+ * @return status of opening the COD file
+ * @see displayCodLoadStatus
+ */
+ CodLoadStatus codLoadStatus() const { return m_codLoadStatus; }
+ /**
+ * Popups a messagebox to the user according to the CodLoadStatus. Will
+ * only popup a messagebox if the CodLoadStatus wasn't CodSuccess.
+ */
+ void displayCodLoadStatus();
+ /**
+ * Returns a list of source files for the currently running program.
+ */
+ QStringList sourceFileList();
+ /**
+ * Set whether or not to run gpsim. (i.e. whether or not the step
+ * function should do anything when called with force=false).
+ */
+ void setRunning( bool run );
+ /**
+ * Returns true if running (currently simulating), else gpsim is paused.
+ */
+ bool isRunning() const { return m_bIsRunning; }
+ /**
+ * Execute the next program instruction. If we are not in a running
+ * mode, then this function will do nothing.
+ */
+ void executeNext();
+ /**
+ * Reset all parts of the simulation. Gpsim will not run until
+ * setRunning(true) is called. Breakpoints are not affected.
+ */
+ void reset();
+ /**
+ * Returns the microinfo describing this processor.
+ */
+ MicroInfo * microInfo() const;
+
+ pic_processor * picProcessor() const { return m_pPicProcessor; }
+ unsigned programMemorySize() const;
+ RegisterSet * registerMemory() const { return m_pRegisterMemory; }
+ /**
+ * @return the instruction type at the given address.
+ */
+ InstructionType instructionType( unsigned address );
+ /**
+ * @return the address of the operand's register at address if the
+ * instruction at address is a register operation, and -1 otherwise.
+ */
+ int operandRegister( unsigned address );
+ /**
+ * @return the literal if the instruction at address is a literal
+ * operation, and -1 otherwise.
+ */
+ int operandLiteral( unsigned address );
+
+ //BEGIN Convenience functions for PIC files
+ enum ProgramFileValidity { DoesntExist, IncorrectType, Valid };
+ /**
+ * @return information on the validity of the given program file (either
+ * DoesntExist, IncorrectType, or Valid).
+ * @see static QString generateSymbolFile
+ */
+ static ProgramFileValidity isValidProgramFile( const QString & programFile );
+ /**
+ * Converts the file at programFile to a Symbol file for emulation,
+ * and returns that symbol file's path
+ * @param programFile The full url to the file
+ * @param assembled The slot to connect the assembled signal to
+ * @see static bool isValidProgramFile( const QString &programFile )
+ */
+ static QString generateSymbolFile( const QString &fileName, QObject *receiver, const char *successMember, const char * failMember = 0l );
+ /**
+ *Compile microbe to output to the given filename
+ */
+ static void compileMicrobe( const QString &filename, QObject *receiver, const char * successMember, const char * failMember = 0l );
+ //END convenience functions for PIC files
+
+ signals:
+ /**
+ * Emitted when the running status of gpsim changes.
+ */
+ void runningStatusChanged( bool isRunning );
+
+ protected:
+ /**
+ * Calls emitLineReached for each debugger.
+ */
+ void emitLineReached();
+
+ pic_processor * m_pPicProcessor;
+ CodLoadStatus m_codLoadStatus;
+ const QString m_symbolFile;
+ RegisterSet * m_pRegisterMemory;
+ GpsimDebugger::Type m_debugMode;
+ GpsimDebugger * m_pDebugger[2]; // Asm, HLL
+
+ /**
+ * We are called effectively for each cycle of the cycle of the
+ * processor. This value is used as some instructions (e.g. goto) take
+ * two cycles to execute, and so we must ignore one cycle to ensure
+ * realtime simulation.
+ */
+ bool m_bCanExecuteNextCycle;
+
+ private:
+ bool m_bIsRunning;
+};
+
+#endif
+
+#endif // !NO_GPSIM