Breakpoint on CPU cycles/instructions GUI setup dialog in work.

This commit is contained in:
mjbudd77 2021-07-24 15:03:13 -04:00
parent 08def74ceb
commit bcbd3218d2
4 changed files with 375 additions and 34 deletions

View File

@ -89,6 +89,10 @@ static void DeleteBreak(int sel);
static bool waitingAtBp = false;
static bool bpDebugEnable = true;
static int lastBpIdx = 0;
static bool breakOnCycleOneShot = 0;
static bool breakOnInstrOneShot = 0;
static int breakOnCycleMode = 0;
static int breakOnInstrMode = 0;
//----------------------------------------------------------------------------
ConsoleDebugger::ConsoleDebugger(QWidget *parent)
: QDialog( parent, Qt::Window )
@ -581,35 +585,59 @@ QMenuBar *ConsoleDebugger::buildMenuBar(void)
debugMenu->addSeparator();
// Debug -> Break on Bad Opcodes
act = new QAction(tr("Break on Bad &Opcodes"), this);
subMenu = debugMenu->addMenu(tr("&Break On..."));
// Debug -> Break on -> Bad Opcodes
act = new QAction(tr("Bad &Opcodes"), this);
//act->setShortcut(QKeySequence( tr("F7") ) );
act->setStatusTip(tr("Break on Bad Opcodes"));
act->setStatusTip(tr("Bad Opcodes"));
act->setCheckable(true);
act->setChecked( FCEUI_Debugger().badopbreak );
connect( act, SIGNAL(triggered(bool)), this, SLOT(breakOnBadOpcodeCB(bool)) );
debugMenu->addAction(act);
subMenu->addAction(act);
// Debug -> Break on Unlogged Code
act = new QAction(tr("Break on Unlogged &Code"), this);
// Debug -> Break on -> Unlogged Code
act = new QAction(tr("Unlogged &Code"), this);
//act->setShortcut(QKeySequence( tr("F7") ) );
act->setStatusTip(tr("Break on Unlogged Code"));
act->setStatusTip(tr("Unlogged Code"));
act->setCheckable(true);
act->setChecked( break_on_unlogged_code );
connect( act, SIGNAL(triggered(bool)), this, SLOT(breakOnNewCodeCB(bool)) );
debugMenu->addAction(act);
subMenu->addAction(act);
// Debug -> Break on Unlogged Data
act = new QAction(tr("Break on Unlogged &Data"), this);
// Debug -> Break on -> Unlogged Data
act = new QAction(tr("Unlogged &Data"), this);
//act->setShortcut(QKeySequence( tr("F7") ) );
act->setStatusTip(tr("Break on Unlogged Data"));
act->setStatusTip(tr("Unlogged Data"));
act->setCheckable(true);
act->setChecked( break_on_unlogged_data );
connect( act, SIGNAL(triggered(bool)), this, SLOT(breakOnNewDataCB(bool)) );
debugMenu->addAction(act);
subMenu->addAction(act);
// Debug -> Break on -> Cycle Count Exceeded
act = new QAction(tr("&Cycle Count Exceeded"), this);
//act->setShortcut(QKeySequence( tr("F7") ) );
act->setStatusTip(tr("CPU Cycle Count Exceeded"));
act->setCheckable(true);
act->setChecked( break_on_cycles );
connect( act, SIGNAL(triggered(bool)), this, SLOT(breakOnCyclesCB(bool)) );
subMenu->addAction(act);
// Debug -> Break on -> Instruction Count Exceeded
act = new QAction(tr("&Instruction Count Exceeded"), this);
//act->setShortcut(QKeySequence( tr("F7") ) );
act->setStatusTip(tr("CPU Instruction Count Exceeded"));
act->setCheckable(true);
act->setChecked( break_on_instructions );
connect( act, SIGNAL(triggered(bool)), this, SLOT(breakOnInstructionsCB(bool)) );
subMenu->addAction(act);
debugMenu->addSeparator();
// Debug -> Reset Counters
act = new QAction(tr("Reset &Counters"), this);
@ -2244,11 +2272,16 @@ void ConsoleDebugger::breakOnNewDataCB(bool value)
break_on_unlogged_data = value;
}
//----------------------------------------------------------------------------
void ConsoleDebugger::breakOnCyclesCB( int value )
void ConsoleDebugger::breakOnCyclesCB( bool value )
{
std::string s;
break_on_cycles = (value != Qt::Unchecked);
if ( value )
{
DebugBreakOnDialog *win = new DebugBreakOnDialog(0, this);
win->exec();
}
break_on_cycles = value;
//s = cpuCycExdVal->text().toStdString();
@ -2274,11 +2307,16 @@ void ConsoleDebugger::cpuCycleThresChanged(const QString &txt)
}
}
//----------------------------------------------------------------------------
void ConsoleDebugger::breakOnInstructionsCB( int value )
void ConsoleDebugger::breakOnInstructionsCB( bool value )
{
std::string s;
break_on_instructions = (value != Qt::Unchecked);
if ( value )
{
DebugBreakOnDialog *win = new DebugBreakOnDialog(1, this);
win->exec();
}
break_on_instructions = value;
//s = instrExdVal->text().toStdString();
@ -6909,3 +6947,266 @@ void DebuggerTabBar::contextMenuEvent(QContextMenuEvent *event)
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//--- Break On Count Setup Dialog
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
DebugBreakOnDialog::DebugBreakOnDialog(int type, QWidget *parent )
: QDialog(parent)
{
QVBoxLayout *mainLayout, *vbox;
QHBoxLayout *hbox;
QGroupBox *gbox;
QGridLayout *grid;
fceuDecIntValidtor *validator;
int refMode;
bool oneShotMode;
char stmp[128];
QPushButton *btn;
fceuWrapperLock();
prevPauseState = FCEUI_EmulationPaused();
if (prevPauseState == 0)
{
FCEUI_ToggleEmulationPause();
}
fceuWrapperUnLock();
currLbl = new QLabel();
this->type = type;
if ( type )
{
totalCount = total_instructions;
deltaCount = delta_instructions;
setWindowTitle( tr("Break on CPU Instruction Exceedance") );
oneShotMode = breakOnInstrOneShot;
refMode = breakOnInstrMode;
threshold = break_instructions_limit;
if (totalCount < 0) // sanity check
{
ResetDebugStatisticsCounters();
totalCount = 0;
}
if (deltaCount < 0) // sanity check
{
ResetDebugStatisticsCounters();
deltaCount = 0;
}
sprintf(stmp, "Current Instruction Count: %10llu (+%llu)", totalCount, deltaCount);
currLbl->setText( tr(stmp) );
}
else
{
totalCount = timestampbase + (uint64)timestamp - total_cycles_base;
deltaCount = timestampbase + (uint64)timestamp - delta_cycles_base;
setWindowTitle( tr("Break on CPU Cycle Exceedance") );
oneShotMode = breakOnCycleOneShot;
refMode = breakOnCycleMode;
threshold = break_cycles_limit;
sprintf(stmp, "Current Cycle Count: %10llu (+%llu)", totalCount, deltaCount);
currLbl->setText( tr(stmp) );
}
mainLayout = new QVBoxLayout();
hbox = new QHBoxLayout();
mainLayout->addLayout(hbox);
gbox = new QGroupBox( tr("Mode") );
vbox = new QVBoxLayout();
oneShotBtn = new QRadioButton( tr("One-Shot") );
contBtn = new QRadioButton( tr("Continuous") );
oneShotBtn->setChecked( oneShotMode );
contBtn->setChecked( !oneShotMode );
hbox->addWidget(gbox);
gbox->setLayout(vbox);
vbox->addWidget( oneShotBtn );
vbox->addWidget( contBtn );
gbox = new QGroupBox( tr("Reference") );
vbox = new QVBoxLayout();
absBtn = new QRadioButton( tr("Absolute") );
relBtn = new QRadioButton( tr("Relative") );
absBtn->setChecked( refMode == 0 );
relBtn->setChecked( refMode == 1 );
hbox->addWidget(gbox);
gbox->setLayout(vbox);
vbox->addWidget( absBtn );
vbox->addWidget( relBtn );
mainLayout->addWidget(currLbl);
hbox = new QHBoxLayout();
mainLayout->addLayout(hbox);
validator = new fceuDecIntValidtor( 0, 0x7FFFFFFFFFFFFFFFLL, this);
countEntryBox = new QLineEdit();
countEntryBox->setValidator( validator );
countEntryBox->setAlignment(Qt::AlignCenter);
hbox->addWidget( new QLabel( tr("Threshold:") ), 1 );
hbox->addWidget( countEntryBox, 100 );
grid = new QGridLayout();
mainLayout->addLayout( grid );
for (int row=0; row<2; row++)
{
int b = row == 0 ? 1 : -1;
for (int col=0; col<5; col++)
{
btn = new QPushButton();
grid->addWidget( btn, row, col );
sprintf( stmp, "%+i", b);
b = b * 10;
btn->setText( tr(stmp) );
}
}
descLbl = new QLabel();
mainLayout->addWidget( descLbl );
setLayout( mainLayout );
setThreshold( threshold );
connect( countEntryBox, SIGNAL(textChanged(const QString &)), this, SLOT(setThreshold(const QString &)) );
connect( absBtn, SIGNAL(clicked(bool)), this, SLOT(refModeChanged(bool)) );
connect( relBtn, SIGNAL(clicked(bool)), this, SLOT(refModeChanged(bool)) );
}
//----------------------------------------------------------------------------
DebugBreakOnDialog::~DebugBreakOnDialog(void)
{
FCEUI_SetEmulationPaused(prevPauseState);
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::closeEvent(QCloseEvent *event)
{
//printf("Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::setThreshold( unsigned long long int val )
{
char stmp[64];
threshold = val;
sprintf( stmp, "%llu", threshold );
countEntryBox->setText( tr(stmp) );
updateLabel();
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::setThreshold( const QString &text )
{
threshold = strtoull( text.toStdString().c_str(), NULL, 10 );
updateLabel();
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::refModeChanged(bool val)
{
updateLabel();
}
//----------------------------------------------------------------------------
void DebugBreakOnDialog::updateLabel(void)
{
long long delta;
char stmp[256];
stmp[0] = 0;
if ( type )
{
if ( absBtn->isChecked() )
{
delta = threshold - total_instructions;
if ( delta > 0 )
{
sprintf( stmp, "Will break in %lli CPU Instruction%s", delta, (delta > 1) ? "s":"" );
}
else
{
sprintf( stmp, "Will break immediately, CPU instruction count already exceeds value.");
}
}
else
{
delta = threshold - delta_instructions;
if ( delta > 0 )
{
sprintf( stmp, "Will break in %lli CPU Instruction%s", delta, (delta > 1) ? "s":"" );
}
else
{
sprintf( stmp, "Will break immediately, CPU instruction count already exceeds value.");
}
}
}
else
{
if ( absBtn->isChecked() )
{
delta = threshold - totalCount;
if ( delta > 0 )
{
sprintf( stmp, "Will break in %lli CPU cycle%s", delta, (delta > 1) ? "s":"" );
}
else
{
sprintf( stmp, "Will break immediately, CPU cycle count already exceeds value.");
}
}
else
{
delta = threshold - deltaCount;
if ( delta > 0 )
{
sprintf( stmp, "Will break in %lli CPU cycle%s", delta, (delta > 1) ? "s":"" );
}
else
{
sprintf( stmp, "Will break immediately, CPU cycle count already exceeds value.");
}
}
}
descLbl->setText( tr(stmp) );
}
//----------------------------------------------------------------------------

View File

@ -11,10 +11,12 @@
#include <QCheckBox>
#include <QGroupBox>
#include <QPushButton>
#include <QRadioButton>
#include <QFont>
#include <QLabel>
#include <QTimer>
#include <QFrame>
#include <QSpinBox>
#include <QGroupBox>
#include <QTreeView>
#include <QTreeWidget>
@ -369,6 +371,41 @@ class DebuggerTabWidget : public QTabWidget
int _col;
};
class DebugBreakOnDialog : public QDialog
{
Q_OBJECT
public:
DebugBreakOnDialog(int type, QWidget *parent = 0);
~DebugBreakOnDialog(void);
unsigned long long int getThreshold(void){ return threshold; }
protected:
void closeEvent(QCloseEvent *event) override;
void updateLabel(void);
int type;
QRadioButton *oneShotBtn;
QRadioButton *contBtn;
QRadioButton *absBtn;
QRadioButton *relBtn;
QLineEdit *countEntryBox;
QLabel *currLbl;
QLabel *descLbl;
int prevPauseState;
long long int totalCount;
long long int deltaCount;
unsigned long long int threshold;
public slots:
void closeWindow(void);
void setThreshold( unsigned long long int val );
void setThreshold( const QString &text );
void refModeChanged(bool);
};
class ConsoleDebugger : public QDialog
{
Q_OBJECT
@ -447,6 +484,9 @@ class ConsoleDebugger : public QDialog
QCheckBox *iGrn_cbox;
QCheckBox *iBlu_cbox;
QAction *brkOnCycleExcAct;
QAction *brkOnInstrExcAct;
DebuggerTabWidget *tabView[2][4];
QWidget *asmViewContainerWidget;
QWidget *bpTreeContainerWidget;
@ -535,8 +575,8 @@ class ConsoleDebugger : public QDialog
void breakOnBadOpcodeCB(bool value);
void breakOnNewCodeCB(bool value);
void breakOnNewDataCB(bool value);
void breakOnCyclesCB( int value );
void breakOnInstructionsCB( int value );
void breakOnCyclesCB( bool value );
void breakOnInstructionsCB( bool value );
void bpItemClicked( QTreeWidgetItem *item, int column);
void bmItemClicked( QTreeWidgetItem *item, int column);
void bmItemDoubleClicked( QTreeWidgetItem *item, int column);

View File

@ -508,14 +508,14 @@ void fceuCustomToolTip::mouseMoveEvent(QMouseEvent *event)
//---------------------------------------------------------------------------
// FCEU Data Entry Custom Validators
//---------------------------------------------------------------------------
fceuDecIntValidtor::fceuDecIntValidtor( int min, int max, QObject *parent)
fceuDecIntValidtor::fceuDecIntValidtor( long long int min, long long int max, QObject *parent)
: QValidator(parent)
{
this->min = min;
this->max = max;
}
//---------------------------------------------------------------------------
void fceuDecIntValidtor::setMinMax( int min, int max)
void fceuDecIntValidtor::setMinMax( long long int min, long long int max)
{
this->min = min;
this->max = max;
@ -523,7 +523,7 @@ void fceuDecIntValidtor::setMinMax( int min, int max)
//---------------------------------------------------------------------------
QValidator::State fceuDecIntValidtor::validate(QString &input, int &pos) const
{
int i, v;
long long int i, v;
//printf("Validate: %i '%s'\n", input.size(), input.toStdString().c_str() );
if ( input.size() == 0 )
@ -557,7 +557,7 @@ QValidator::State fceuDecIntValidtor::validate(QString &input, int &pos) const
if ( s[i] == 0 )
{
v = strtol( s.c_str(), NULL, 0 );
v = strtoll( s.c_str(), NULL, 0 );
if ( v < min )
{
@ -575,14 +575,14 @@ QValidator::State fceuDecIntValidtor::validate(QString &input, int &pos) const
//---------------------------------------------------------------------------
// FCEU Data Entry Custom Validators
//---------------------------------------------------------------------------
fceuHexIntValidtor::fceuHexIntValidtor( int min, int max, QObject *parent)
fceuHexIntValidtor::fceuHexIntValidtor( long long int min, long long int max, QObject *parent)
: QValidator(parent)
{
this->min = min;
this->max = max;
}
//---------------------------------------------------------------------------
void fceuHexIntValidtor::setMinMax( int min, int max)
void fceuHexIntValidtor::setMinMax( long long int min, long long int max)
{
this->min = min;
this->max = max;
@ -590,7 +590,7 @@ void fceuHexIntValidtor::setMinMax( int min, int max)
//---------------------------------------------------------------------------
QValidator::State fceuHexIntValidtor::validate(QString &input, int &pos) const
{
int i, v;
long long int i, v;
//printf("Validate: %i '%s'\n", input.size(), input.toStdString().c_str() );
if ( input.size() == 0 )
@ -625,7 +625,7 @@ QValidator::State fceuHexIntValidtor::validate(QString &input, int &pos) const
if ( s[i] == 0 )
{
v = strtol( s.c_str(), NULL, 16 );
v = strtoll( s.c_str(), NULL, 16 );
if ( v < min )
{

View File

@ -23,27 +23,27 @@ int fceuLoadConfigColor( const char *confName, QColor *color );
class fceuDecIntValidtor : public QValidator
{
public:
fceuDecIntValidtor( int min, int max, QObject *parent);
fceuDecIntValidtor( long long int min, long long int max, QObject *parent);
QValidator::State validate(QString &input, int &pos) const;
void setMinMax( int min, int max );
void setMinMax( long long int min, long long int max );
private:
int min;
int max;
long long int min;
long long int max;
};
class fceuHexIntValidtor : public QValidator
{
public:
fceuHexIntValidtor( int min, int max, QObject *parent);
fceuHexIntValidtor( long long int min, long long int max, QObject *parent);
QValidator::State validate(QString &input, int &pos) const;
void setMinMax( int min, int max );
void setMinMax( long long int min, long long int max );
private:
int min;
int max;
long long int min;
long long int max;
};
class fceuCustomToolTip : public QDialog