summaryrefslogtreecommitdiffstats
path: root/src/progs/gpsim
diff options
context:
space:
mode:
Diffstat (limited to 'src/progs/gpsim')
-rw-r--r--src/progs/gpsim/Makefile.am3
-rw-r--r--src/progs/gpsim/base/Makefile.am6
-rw-r--r--src/progs/gpsim/base/base.pro6
-rw-r--r--src/progs/gpsim/base/gpsim.cpp155
-rw-r--r--src/progs/gpsim/base/gpsim.h85
-rw-r--r--src/progs/gpsim/base/gpsim_debug.cpp282
-rw-r--r--src/progs/gpsim/base/gpsim_debug.h95
-rw-r--r--src/progs/gpsim/gpsim.pro2
-rw-r--r--src/progs/gpsim/gui/Makefile.am5
-rw-r--r--src/progs/gpsim/gui/gpsim_group_ui.cpp42
-rw-r--r--src/progs/gpsim/gui/gpsim_group_ui.h42
11 files changed, 723 insertions, 0 deletions
diff --git a/src/progs/gpsim/Makefile.am b/src/progs/gpsim/Makefile.am
new file mode 100644
index 0000000..490a53d
--- /dev/null
+++ b/src/progs/gpsim/Makefile.am
@@ -0,0 +1,3 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+SUBDIRS = base gui
diff --git a/src/progs/gpsim/base/Makefile.am b/src/progs/gpsim/base/Makefile.am
new file mode 100644
index 0000000..b008527
--- /dev/null
+++ b/src/progs/gpsim/base/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+libgpsim_la_LDFLAGS = $(all_libraries)
+noinst_LTLIBRARIES = libgpsim.la
+libgpsim_la_SOURCES = gpsim.cpp gpsim_debug.cpp
diff --git a/src/progs/gpsim/base/base.pro b/src/progs/gpsim/base/base.pro
new file mode 100644
index 0000000..4b05ac5
--- /dev/null
+++ b/src/progs/gpsim/base/base.pro
@@ -0,0 +1,6 @@
+STOPDIR = ../../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = gpsim
+HEADERS += gpsim.h gpsim_debug.h
+SOURCES += gpsim.cpp gpsim_debug.cpp
diff --git a/src/progs/gpsim/base/gpsim.cpp b/src/progs/gpsim/base/gpsim.cpp
new file mode 100644
index 0000000..e6c17bd
--- /dev/null
+++ b/src/progs/gpsim/base/gpsim.cpp
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "gpsim.h"
+
+#include <qregexp.h>
+#include "progs/base/generic_prog.h"
+#include "progs/base/generic_debug.h"
+
+//-----------------------------------------------------------------------------
+GPSim::Process::Process(Log::Base *base)
+ : ::Process::LineOutput(0, "gpsim_process"), Log::Base(base), _ready(false)
+{
+ connect(this, SIGNAL(stdoutDataReceived()), SLOT(stdoutDataReceivedSlot()));
+}
+
+void GPSim::Process::stdoutDataReceivedSlot()
+{
+ if ( _stdout.startsWith("**gpsim> ") || _ready ) {
+ log(Log::DebugLevel::Extra, "received console prompt", Log::Delayed);
+ _ready = true;
+ emit requestSynchronousStop();
+ }
+}
+
+void GPSim::Process::addStdoutLine(const QString &line)
+{
+ log(Log::DebugLevel::Extra, " " + line, Log::Delayed);
+ if ( line.startsWith("***ERROR:") ) {
+ log(Log::LineType::Error, line);
+ return;
+ }
+ QString s = line;
+ QString prompt = "**gpsim> ";
+ while ( s.startsWith(prompt) ) {
+ _ready = true;
+ s = s.mid(prompt.length());
+ }
+ s = s.stripWhiteSpace();
+ _stdoutLines += s;
+}
+
+//-----------------------------------------------------------------------------
+GPSim::ProcessManager::ProcessManager(Log::Base *base)
+ : Log::Base(base), _process(base)
+{}
+
+bool GPSim::ProcessManager::start()
+{
+ _process._ready = false;
+ _process.setup("gpsim", QStringList("-i"), false);
+ if ( !_process.start(0) ) {
+ log(Log::LineType::Error, i18n("Failed to start \"gpsim\"."));
+ return false;
+ }
+ return runSynchronously();
+}
+
+bool GPSim::ProcessManager::runSynchronously()
+{
+ ::Process::State state = ::Process::runSynchronously(_process, ::Process::NoRunAction, 5000);
+ if ( !_process.isRunning() ) {
+ log(Log::LineType::Error, i18n("\"gpsim\" unexpectedly exited."));
+ return false;
+ }
+ if ( state==::Process::Timedout ) {
+ log(Log::LineType::Error, i18n("Timeout waiting for \"gpsim\"."));
+ return false;
+ }
+ return true;
+}
+
+bool GPSim::ProcessManager::sendCommand(const QString &cmd, bool synchronous)
+{
+ _process._ready = false;
+ _process._stdoutLines.clear();
+ _process._stdout = QString::null;
+ _process.writeToStdin(cmd + '\n');
+ if (synchronous) return runSynchronously();
+ return true;
+}
+
+bool GPSim::ProcessManager::sendSignal(uint n, bool synchronous)
+{
+ _process._ready = false;
+ _process._stdoutLines.clear();
+ _process._stdout = QString::null;
+ if ( !_process.signal(n) ) {
+ log(Log::LineType::Error, i18n("Error send a signal to the subprocess."));
+ return false;
+ }
+ if (synchronous) return runSynchronously();
+ return true;
+}
+
+bool GPSim::ProcessManager::getVersion(VersionData &version)
+{
+ if ( !sendCommand("version", true) ) return false;
+ QRegExp reg("\\w*\\s*(\\d+\\.\\d+\\.\\d+).*");
+ if ( _process.sout().count()==0 || !reg.exactMatch(_process.sout()[0]) ) {
+ version = VersionData();
+ return true;
+ }
+ version = VersionData::fromString(reg.cap(1));
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+GPSim::Hardware::~Hardware()
+{
+ delete _manager;
+}
+
+bool GPSim::Hardware::internalConnectHardware()
+{
+ delete _manager;
+ _manager = new ProcessManager(this);
+ _manager->process().setWorkingDirectory(_base.debugger()->directory());
+ if ( !_manager->start() ) return false;
+ if ( !_manager->getVersion(_version) ) return false;
+ if ( !_version.isValid() ) {
+ log(Log::LineType::Error, i18n("Could not recognize gpsim version."));
+ return false;
+ }
+ return true;
+}
+
+void GPSim::Hardware::internalDisconnectHardware()
+{
+ delete _manager;
+ _manager = 0;
+}
+
+bool GPSim::Hardware::execute(const QString &command, bool synchronous, QStringList *output)
+{
+ log(Log::DebugLevel::Normal, QString("command: %1").arg(command));
+ if (output) output->clear();
+ if ( !_manager->sendCommand(command, synchronous) ) return false;
+ if (output) *output = _manager->process().sout();
+ return true;
+}
+
+bool GPSim::Hardware::signal(uint n, bool synchronous, QStringList *output)
+{
+ log(Log::DebugLevel::Normal, QString("signal: %1").arg(n));
+ if (output) output->clear();
+ if ( !_manager->sendSignal(n, synchronous) ) return false;
+ if (output) *output = _manager->process().sout();
+ return true;
+}
diff --git a/src/progs/gpsim/base/gpsim.h b/src/progs/gpsim/base/gpsim.h
new file mode 100644
index 0000000..ab004a3
--- /dev/null
+++ b/src/progs/gpsim/base/gpsim.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef GPSIM_H
+#define GPSIM_H
+
+#include "common/common/version_data.h"
+#include "progs/base/prog_specific.h"
+#include "common/global/process.h"
+#include "common/global/purl.h"
+
+namespace GPSim
+{
+//-----------------------------------------------------------------------------
+class Process : public ::Process::LineOutput, public Log::Base
+{
+Q_OBJECT
+public:
+ Process(Log::Base *base);
+
+private slots:
+ void stdoutDataReceivedSlot();
+
+private:
+ bool _ready;
+
+ virtual void addStdoutLine(const QString &line);
+
+ friend class ProcessManager;
+};
+
+//-----------------------------------------------------------------------------
+class ProcessManager : public Log::Base
+{
+public:
+ ProcessManager(Log::Base *base);
+ Process &process() { return _process; }
+ bool isReady() const { return _process._ready; }
+ bool start();
+ bool runSynchronously();
+ bool sendCommand(const QString &cmd, bool synchronous);
+ bool sendSignal(uint n, bool synchronous);
+ bool getVersion(VersionData &version);
+
+private:
+ Process _process;
+};
+
+//-----------------------------------------------------------------------------
+class Hardware : public Programmer::Hardware
+{
+public:
+ Hardware(::Programmer::Base &base) : Programmer::Hardware(base, 0, QString::null), _manager(0) {}
+ virtual ~Hardware();
+ bool isReady() const { return _manager->isReady(); }
+ bool execute(const QString &command, bool synchronous, QStringList *output = 0);
+ bool signal(uint n, bool synchronous, QStringList *output = 0);
+ const VersionData &version() const { return _version; }
+
+private:
+ ProcessManager *_manager;
+ VersionData _version;
+
+ virtual bool internalConnectHardware();
+ virtual void internalDisconnectHardware();
+};
+
+//-----------------------------------------------------------------------------
+class DeviceSpecific : public ::Programmer::DeviceSpecific
+{
+public:
+ DeviceSpecific(::Programmer::Base &base) : ::Programmer::DeviceSpecific(base) {}
+ virtual bool setPowerOff() { return false; }
+ virtual bool setPowerOn() { return false; }
+ virtual bool setTargetPowerOn(bool) { return true; }
+};
+
+} // namespace
+
+#endif
diff --git a/src/progs/gpsim/base/gpsim_debug.cpp b/src/progs/gpsim/base/gpsim_debug.cpp
new file mode 100644
index 0000000..b2bcec5
--- /dev/null
+++ b/src/progs/gpsim/base/gpsim_debug.cpp
@@ -0,0 +1,282 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "gpsim_debug.h"
+
+#include <signal.h>
+#include <qregexp.h>
+
+#include "devices/list/device_list.h"
+#include "devices/pic/base/pic_register.h"
+#include "coff/base/text_coff.h"
+#include "progs/manager/debug_manager.h"
+
+//----------------------------------------------------------------------------
+GPSim::Debugger::Debugger(Programmer &programmer)
+ : ::Debugger::PicBase(programmer), _nbBreakpoints(0)
+{}
+
+bool GPSim::Debugger::internalInit()
+{
+ if ( !hardware()->execute("processor pic" + device()->name().lower(), true) ) return false;
+ if ( _inputType==PURL::Cod ) return hardware()->execute("load s " + _filename, true);
+ Q_ASSERT( _inputType==PURL::Hex );
+ return hardware()->execute("load h " + _filename, true);
+}
+
+bool GPSim::Debugger::internalRun()
+{
+ return hardware()->execute("run", false);
+}
+
+bool GPSim::Debugger::hardHalt()
+{
+ log(Log::LineType::Warning, i18n("Failed to halt target: kill process."));
+ _programmer.disconnectHardware();
+ return true;
+}
+
+bool GPSim::Debugger::softHalt(bool &success)
+{
+ success = hardware()->signal(SIGINT, true);
+ return true;
+}
+
+bool GPSim::Debugger::internalStep()
+{
+ return hardware()->execute("step", true);
+}
+
+bool GPSim::Debugger::setBreakpoints(const QValueList<Address> &list)
+{
+ for (uint i=0; i<_nbBreakpoints; i++)
+ if ( !hardware()->execute("clear " + QString::number(i), true) ) return false;
+ for (uint i=0; i<uint(list.count()); i++)
+ if ( !hardware()->execute("break e 0x" + toHex(list[i], nbChars(list[i].toUInt())), true) ) return false;
+ _nbBreakpoints = list.count();
+ return true;
+}
+
+bool GPSim::Debugger::internalReset()
+{
+ if ( _programmer.state()==::Programmer::Running && !halt() ) return false;
+ return hardware()->execute("reset", true);
+}
+
+bool GPSim::Debugger::updateState()
+{
+ if ( hardware()->isReady() ) _programmer.setState(::Programmer::Halted);
+ else _programmer.setState(::Programmer::Running);
+ return true;
+}
+
+bool GPSim::Debugger::findRegExp(const QStringList &lines, const QString &pattern,
+ const QString &label, QString &value) const
+{
+ QRegExp rexp(pattern);
+ uint i = 0;
+ for (; i<uint(lines.count()); i++) {
+ int offset = 0;
+ for (;;) {
+ offset = rexp.search(lines[i], offset, QRegExp::CaretAtOffset);
+ if ( offset==-1 || rexp.cap(1)==label ) break;
+ offset += rexp.cap(0).length();
+ }
+ if ( offset!=-1 ) break;
+ }
+ if ( i==uint(lines.count()) ) return false;
+ value = rexp.cap(2);
+ return true;
+}
+
+bool GPSim::Debugger::readWreg(BitValue &value)
+{
+ // #### only known for version 4 and 11
+ if ( hardware()->version()<=VersionData(0, 21, 7) || hardware()->version()>=VersionData(0, 22, 0) )
+ return getRegister("W", value);
+ QStringList lines;
+ if ( !hardware()->execute("dump s", true, &lines) ) return false;
+ QString w = (_coff->symbol("_WREG") ? "_WREG" : "W");
+ QString s;
+ if ( !findRegExp(lines, "^\\s*[0-9A-Fa-f]+\\s+(\\w+)\\s*=\\s*([0-9A-Fa-f]+)", w, s) ) {
+ log(Log::LineType::Error, i18n("Error reading register \"%1\"").arg(w));
+ return false;
+ }
+ value = fromHex(s, 0);
+ return true;
+}
+
+bool GPSim::Debugger::getRegister(const QString &name, BitValue &value)
+{
+ QStringList lines;
+ QRegExp r;
+ if ( hardware()->version()<VersionData(0, 22, 0) ) {
+ if ( !hardware()->execute("x " + name, true, &lines) ) return false;
+ r.setPattern("\\w+\\s*[][\\w]+\\s*=\\s*(?:0x|)([0-9A-Fa-f]+)(?:\\W.*|)");
+ } else {
+ if ( !hardware()->execute(name, true, &lines) ) return false;
+ r.setPattern("[^=]*=\\s*(?:0x|\\$)([0-9A-Fa-f]+)(?:\\W.*|)");
+ }
+ uint i = 0;
+ for (; i<uint(lines.count()); i++)
+ if ( r.exactMatch(lines[i]) ) break;
+ if ( i==uint(lines.count()) ) {
+ log(Log::LineType::Error, i18n("Error reading register \"%1\"").arg(name));
+ return false;
+ }
+ value = fromHex(r.cap(1), 0);
+ return true;
+}
+
+bool GPSim::Debugger::getRegister(Address address, BitValue &value)
+{
+ const Pic::RegistersData &rdata = device()->registersData();
+ QString name = toHex(address, rdata.nbCharsAddress());
+ if ( hardware()->version()<VersionData(0, 22, 0) ) return getRegister("0x" + name, value);
+ return getRegister(QString("ramData[$%1]").arg(name), value);
+}
+
+bool GPSim::Debugger::readRegister(const Register::TypeData &data, BitValue &value)
+{
+ if ( data.type()==Register::Special ) {
+ if ( data.name()=="WREG" ) return readWreg(value);
+ if ( data.name()=="PC" ) return getRegister("pc", value);
+ Q_ASSERT(false);
+ return true;
+ }
+ QString name = device()->registersData().sfrNames[data.address()];
+ if ( name=="WREG" ) return readWreg(value);
+ if ( !name.isEmpty() ) return getRegister(name.lower(), value);
+ return getRegister(data.address(), value);
+}
+
+bool GPSim::Debugger::setRegister(const QString &name, BitValue value)
+{
+ if ( hardware()->version()<VersionData(0, 22, 0) ) {
+ log(Log::LineType::Warning, i18n("Writing registers is not supported by this version of gpsim"));
+ return true;
+ }
+ const Pic::RegistersData &rdata = device()->registersData();
+ QString s = QString("%1 = %2").arg(name).arg(toHexLabel(value, rdata.nbChars()));
+ return hardware()->execute(s, true);
+}
+
+bool GPSim::Debugger::setRegister(Address address, BitValue value)
+{
+ const Pic::RegistersData &rdata = device()->registersData();
+ QString s = QString("ramData[$%1]").arg(toHex(address, rdata.nbCharsAddress()));
+ return setRegister(s, value);
+}
+
+bool GPSim::Debugger::writeRegister(const Register::TypeData &data, BitValue value)
+{
+ if ( data.type()==Register::Special ) {
+ if ( data.name()=="WREG" ) return writeWreg(value);
+ if ( data.name()=="PC" ) {
+ log(Log::LineType::Warning, i18n("Writing PC is not supported by gpsim"));
+ return true;
+ }
+ Q_ASSERT(false);
+ return false;
+ }
+ const Pic::RegistersData &rdata = device()->registersData();
+ QString name = rdata.sfrNames[data.address()];
+ if ( !name.isEmpty() ) return setRegister(name.lower(), value);
+ return setRegister(data.address(), value);
+}
+
+bool GPSim::Debugger::writeWreg(BitValue value)
+{
+ return setRegister("W", value);
+}
+
+bool GPSim::Debugger::updatePortStatus(uint index, QMap<uint, Device::PortBitData> &bits)
+{
+ for (uint i=0; i<Device::MAX_NB_PORT_BITS; i++) {
+ if ( !device()->registersData().hasPortBit(index, i) ) continue;
+ QString name = device()->registersData().portName(index).lower() + QString::number(i);
+ QStringList lines;
+ if ( !hardware()->execute("symbol " + name, true, &lines) ) return false;
+ QString pattern = "^(\\w+)=([^\\s])+\\s*", value;
+ if ( !findRegExp(lines, pattern, "bitState", value) || value.length()!=1 ) {
+ log(Log::LineType::Error, i18n("Error reading state of IO bit: %1").arg(name));
+ return false;
+ }
+ switch (value[0].latin1()) {
+ case 'H':
+ case '1': bits[i].state = Device::High; break;
+ case 'L':
+ case '0': bits[i].state = Device::Low; break;
+ case 'W': bits[i].state = Device::WeakPullUp; break;
+ case 'w': bits[i].state = Device::WeakPullDown; break;
+ case 'Z': bits[i].state = Device::HighImpedance; break;
+ case 'X': bits[i].state = Device::Unknown; break;
+ default:
+ bits[i].state = Device::Unknown;
+ log(Log::LineType::Warning, i18n("Unknown state for IO bit: %1 (%2)").arg(name).arg(value));
+ break;
+ }
+ if ( !findRegExp(lines, pattern, "Driving", value) || value.length()!=1 ) {
+ log(Log::LineType::Error, i18n("Error reading driving state of IO bit: %1").arg(name));
+ return false;
+ }
+ bits[i].driving = ( value[0]=='1' );
+ if (bits[i].driving) {
+ if ( !findRegExp(lines, pattern, "drivingState", value) || value.length()!=1 ) {
+ log(Log::LineType::Error, i18n("Error reading driving state of IO bit: %1").arg(name));
+ return false;
+ }
+ bits[i].drivingState = (value[0]=='0' ? Device::IoLow : Device::IoHigh);
+ bits[i].drivenState = Device::IoUnknown;
+ } else {
+ if ( !findRegExp(lines, pattern, "drivenState", value) || value.length()!=1 ) {
+ log(Log::LineType::Error, i18n("Error reading driven state of IO bit: %1").arg(name));
+ return false;
+ }
+ bits[i].drivenState = (value[0]=='0' ? Device::IoLow : Device::IoHigh);
+ bits[i].drivingState = Device::IoUnknown;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+QString GPSim::Group::statusLabel() const
+{
+ return i18n("GPSim (4MHz)"); // #### FIXME: add config
+}
+
+void GPSim::Group::initSupported()
+{
+ ProcessManager manager(0);
+ if ( !manager.start() ) return;
+ VersionData version;
+ if ( !manager.getVersion(version) ) return;
+ bool oldGpsim = ( version<VersionData(0, 21, 11) );
+ if ( !manager.sendCommand("processor list", true) ) return;
+ QStringList devices = QStringList::split(" ", manager.process().sout().join(" "));
+ for (uint i=0; i<uint(devices.count()); i++) {
+ QString s = devices[i].upper();
+ if ( s.startsWith("PIC") ) s = s.mid(3);
+ const Pic::Data *data = static_cast<const Pic::Data *>(Device::lister().data(s));
+ if (data) {
+ if ( data->architecture()==Pic::Architecture::P18F && oldGpsim ) continue;
+ addDevice(data->name(), data, ::Group::Support::Tested);
+ }
+ }
+}
+
+Programmer::Hardware *GPSim::Group::createHardware(::Programmer::Base &base, const ::Programmer::HardwareDescription &) const
+{
+ return new Hardware(base);
+}
+
+Programmer::DeviceSpecific *GPSim::Group::createDeviceSpecific(::Programmer::Base &base) const
+{
+ return new DeviceSpecific(base);
+}
diff --git a/src/progs/gpsim/base/gpsim_debug.h b/src/progs/gpsim/base/gpsim_debug.h
new file mode 100644
index 0000000..ad838b2
--- /dev/null
+++ b/src/progs/gpsim/base/gpsim_debug.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef GPSIM_DEBUG_H
+#define GPSIM_DEBUG_H
+
+#include "gpsim.h"
+#include "devices/pic/prog/pic_prog.h"
+#include "devices/pic/prog/pic_debug.h"
+
+namespace GPSim
+{
+//-----------------------------------------------------------------------------
+class Programmer : public ::Programmer::PicBase
+{
+Q_OBJECT
+public:
+ Programmer(const ::Programmer::Group &group, const Pic::Data *data)
+ : Programmer::PicBase(group, data, "gpsim_programmer") {}
+
+private:
+ virtual VersionData minVersion() const { return VersionData(0, 21, 0); }
+ virtual bool verifyDeviceId() { return true; }
+ virtual bool checkErase() { return false; }
+ virtual bool internalErase(const Device::MemoryRange &) { return false; }
+ virtual bool checkRead() { return false; }
+ virtual bool internalRead(Device::Memory &, const Device::MemoryRange &) { return false; }
+ virtual bool checkProgram(const Device::Memory &) { return false; }
+ virtual bool internalProgram(const Device::Memory &, const Device::MemoryRange &) { return false; }
+ virtual bool checkVerify() { return false; }
+ virtual bool internalVerify(const Device::Memory &, const Device::MemoryRange &, ::Programmer::VerifyActions) { return false; }
+};
+
+//-----------------------------------------------------------------------------
+class Debugger : public ::Debugger::PicBase
+{
+public:
+ Debugger(Programmer &programmer);
+ virtual bool setBreakpoints(const QValueList<Address> &list);
+ virtual bool readRegister(const Register::TypeData &data, BitValue &value);
+ virtual bool writeRegister(const Register::TypeData &data, BitValue value);
+ virtual bool updatePortStatus(uint index, QMap<uint, Device::PortBitData> &bits);
+
+private:
+ uint _nbBreakpoints;
+
+ bool findRegExp(const QStringList &lines, const QString &pattern,
+ const QString &label, QString &value) const;
+ bool getRegister(const QString &name, BitValue &value);
+ bool setRegister(const QString &name, BitValue value);
+ bool getRegister(Address address, BitValue &value);
+ bool setRegister(Address address, BitValue value);
+ Hardware *hardware() { return static_cast<Hardware *>(_programmer.hardware()); }
+ const Pic::Data *device() const { return static_cast<const Pic::Data *>(_programmer.device()); }
+ virtual bool internalInit();
+ virtual bool updateState();
+ virtual bool internalRun();
+ virtual bool internalStep();
+ virtual bool softHalt(bool &success);
+ virtual bool hardHalt();
+ virtual bool internalReset();
+ bool readWreg(BitValue &value);
+ bool writeWreg(BitValue value);
+};
+
+//-----------------------------------------------------------------------------
+class Group : public ::Programmer::PicGroup
+{
+public:
+ virtual QString name() const { return "gpsim"; }
+ virtual QString label() const { return i18n("GPSim"); }
+ virtual QString statusLabel() const;
+ virtual ::Programmer::Properties properties() const { return ::Programmer::Debugger | ::Programmer::HasConnectedState; }
+ virtual ::Programmer::TargetPowerMode targetPowerMode() const { return ::Programmer::TargetSelfPowered; }
+ virtual bool isPortSupported(PortType) const { return false; }
+ virtual uint maxNbBreakpoints(const Device::Data *) const { return 100; }
+ virtual bool isInputFileTypeSupported(PURL::FileType type) const { return ( type==PURL::Cod || type==PURL::Hex ); }
+
+protected:
+ virtual void initSupported();
+ virtual ::Programmer::Base *createBase(const Device::Data *data) const { return new Programmer(*this, static_cast<const Pic::Data *>(data)); }
+ virtual ::Programmer::Hardware *createHardware(::Programmer::Base &base, const ::Programmer::HardwareDescription &hd) const;
+ virtual ::Programmer::DeviceSpecific *createDeviceSpecific(::Programmer::Base &base) const;
+ virtual ::Debugger::Base *createDebuggerBase(::Programmer::Base &base) const { return new Debugger(static_cast<Programmer &>(base)); }
+ virtual ::Debugger::Specific *createDebuggerSpecific(::Debugger::Base &) const { return 0; }
+};
+
+} // namespace
+
+#endif
diff --git a/src/progs/gpsim/gpsim.pro b/src/progs/gpsim/gpsim.pro
new file mode 100644
index 0000000..fe430fe
--- /dev/null
+++ b/src/progs/gpsim/gpsim.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = base
diff --git a/src/progs/gpsim/gui/Makefile.am b/src/progs/gpsim/gui/Makefile.am
new file mode 100644
index 0000000..d63f4a8
--- /dev/null
+++ b/src/progs/gpsim/gui/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+libgpsimui_la_LDFLAGS = $(all_libraries)
+noinst_LTLIBRARIES = libgpsimui.la
+libgpsimui_la_SOURCES = gpsim_group_ui.cpp
diff --git a/src/progs/gpsim/gui/gpsim_group_ui.cpp b/src/progs/gpsim/gui/gpsim_group_ui.cpp
new file mode 100644
index 0000000..3949b8e
--- /dev/null
+++ b/src/progs/gpsim/gui/gpsim_group_ui.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "gpsim_group_ui.h"
+
+#include <qtimer.h>
+
+#include "progs/base/prog_group.h"
+#include "progs/gpsim/base/gpsim.h"
+
+//----------------------------------------------------------------------------
+GPSim::ConfigWidget::ConfigWidget(const ::Programmer::Group &group, QWidget *parent)
+ : ::Programmer::ConfigWidget(group, parent)
+{
+ uint row = numRows();
+ QLabel *label = new QLabel(i18n("Status:"), this);
+ addWidget(label, row,row, 0,0);
+ _status = new QLabel(this);
+ addWidget(_status, row,row, 1,1);
+
+ QTimer::singleShot(0, this, SLOT(updateStatus()));
+}
+
+void GPSim::ConfigWidget::updateStatus()
+{
+ VersionData version;
+ ProcessManager manager(0);
+ if ( !manager.start() ) _status->setText(i18n("Could not start \"gpsim\""));
+ else if ( !manager.getVersion(version) || !version.isValid() ) _status->setText(i18n("Could not detect \"gpsim\" version"));
+ else _status->setText(i18n("Found version \"%1\"").arg(version.pretty()));
+}
+
+//----------------------------------------------------------------------------
+::Programmer::ConfigWidget *GPSim::GroupUI::createConfigWidget(QWidget *parent) const
+{
+ return new ConfigWidget(static_cast<const ::Programmer::Group &>(group()), parent);
+}
diff --git a/src/progs/gpsim/gui/gpsim_group_ui.h b/src/progs/gpsim/gui/gpsim_group_ui.h
new file mode 100644
index 0000000..485aa69
--- /dev/null
+++ b/src/progs/gpsim/gui/gpsim_group_ui.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef GPSIM_GROUP_UI_H
+#define GPSIM_GROUP_UI_H
+
+#include "progs/gui/prog_group_ui.h"
+#include "progs/gui/prog_config_widget.h"
+
+namespace GPSim
+{
+//----------------------------------------------------------------------------
+class ConfigWidget : public ::Programmer::ConfigWidget
+{
+Q_OBJECT
+public:
+ ConfigWidget(const ::Programmer::Group &group, QWidget *parent);
+
+private slots:
+ void updateStatus();
+
+private:
+ QLabel *_status;
+};
+
+//----------------------------------------------------------------------------
+class GroupUI : public ::Programmer::GroupUI
+{
+public:
+ virtual ::Programmer::ConfigWidget *createConfigWidget(QWidget *parent) const;
+ virtual bool hasAdvancedDialog() const { return false; }
+ virtual ::Programmer::AdvancedDialog *createAdvancedDialog(::Programmer::Base &, QWidget *) const { return 0; }
+};
+
+} // namespace
+
+#endif