Line 23... |
Line 23... |
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
|
|
// $Id: Or1200MonitorSC.cpp 303 2009-02-16 11:20:17Z jeremy $
|
// $Id$
|
|
|
#include <iostream>
|
#include <iostream>
|
#include <iomanip>
|
#include <iomanip>
|
#include <fstream>
|
#include <fstream>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
Line 140... |
Line 140... |
}
|
}
|
}
|
}
|
|
|
|
|
|
|
|
// checkInstruction monitors the bus for special NOP instructionsl
|
|
SC_METHOD (checkInstruction);
|
|
sensitive << clk.pos();
|
|
dont_initialize();
|
|
|
|
|
if (profiling_enabled)
|
if (profiling_enabled)
|
{
|
{
|
profileFile.open(profileFileName.c_str(), ios::out); // Open profiling log file
|
profileFile.open(profileFileName.c_str(), ios::out); // Open profiling log file
|
if(profileFile.is_open())
|
if(profileFile.is_open())
|
{
|
{
|
Line 215... |
Line 221... |
|
|
memdump_start_addr = memdump_start;
|
memdump_start_addr = memdump_start;
|
memdump_end_addr = memdump_end;
|
memdump_end_addr = memdump_end;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
// checkInstruction monitors the bus for special NOP instructionsl
|
|
SC_METHOD (checkInstruction);
|
|
sensitive << clk.pos();
|
|
dont_initialize();
|
|
|
|
|
|
|
|
} // Or1200MonitorSC ()
|
} // Or1200MonitorSC ()
|
|
|
//! Print command line switches for the options of this module
|
//! Print command line switches for the options of this module
|
void
|
void
|
Or1200MonitorSC::printSwitches()
|
Or1200MonitorSC::printSwitches()
|
Line 254... |
Line 249... |
|
|
//! - l.nop 1 Terminate the program
|
//! - l.nop 1 Terminate the program
|
//! - l.nop 2 Report the value in R3
|
//! - l.nop 2 Report the value in R3
|
//! - l.nop 3 Printf the string with the arguments in R3, etc
|
//! - l.nop 3 Printf the string with the arguments in R3, etc
|
//! - l.nop 4 Print a character
|
//! - l.nop 4 Print a character
|
|
|
|
//#define OR1200_OR32_NOP_BITS_31_TO_26 6'b000101
|
|
#define OR1200_OR32_NOP 0x14000000
|
|
|
extern int SIM_RUNNING;
|
extern int SIM_RUNNING;
|
void
|
void
|
Or1200MonitorSC::checkInstruction()
|
Or1200MonitorSC::checkInstruction()
|
{
|
{
|
uint32_t r3;
|
uint32_t r3;
|
double ts;
|
double ts;
|
|
|
cycle_count++;
|
cycle_count++;
|
|
|
|
/* Check if this counts as an "executed" instruction */
|
|
if (!accessor->getWbFreeze())
|
|
if ((((accessor->getWbInsn() & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(accessor->getWbInsn() & (1<<16))) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
|
|
insn_count++;
|
|
else
|
|
// Exception version
|
|
if (accessor->getExceptFlushpipe())
|
|
insn_count++;
|
|
|
// Check the instruction when the freeze signal is low.
|
// Check the instruction when the freeze signal is low.
|
//if (!accessor->getWbFreeze())
|
//if (!accessor->getWbFreeze())
|
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0))
|
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0))
|
{
|
{
|
|
|
// Increment instruction counter
|
|
insn_count++;
|
|
|
|
// Do something if we have l.nop
|
// Do something if we have l.nop
|
switch (accessor->getWbInsn())
|
switch (accessor->getWbInsn())
|
{
|
{
|
case NOP_EXIT:
|
case NOP_EXIT:
|
r3 = accessor->getGpr (3);
|
r3 = accessor->getGpr (3);
|
Line 373... |
Line 378... |
|
|
break;
|
break;
|
|
|
}
|
}
|
}
|
}
|
} // checkInstruction()
|
} // callLog()
|
|
|
|
|
//! Method to output the state of the processor
|
//! Method to output the state of the processor
|
|
|
//! This function will output to a file, if enabled, the status of the processor
|
//! This function will output to a file, if enabled, the status of the processor
|
//! For now, it's just the PPC and instruction.
|
//! This copies what the verilog testbench module, or1200_monitor does in it its
|
|
//! process which calls the display_arch_state tasks. This is designed to be
|
|
//! identical to that process, so the output is identical
|
#define PRINT_REGS 1
|
#define PRINT_REGS 1
|
void
|
void
|
Or1200MonitorSC::displayState()
|
Or1200MonitorSC::displayState()
|
{
|
{
|
uint32_t wbinsn;
|
bool printregs = false;
|
|
|
// Calculate how many instructions we've actually calculated by ignoring cycles where we're frozen, delay slots and flushpipe cycles
|
|
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
|
|
|
|
if (logging_enabled == 0)
|
|
return; // If we didn't inialise a file, then just return.
|
|
|
|
// Output the state if we're not frozen and not flushing during a delay slot
|
// Output the state if we're not frozen and not flushing during a delay slot
|
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
|
if (!accessor->getWbFreeze())
|
|
{
|
|
if ((((accessor->getWbInsn() & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(accessor->getWbInsn() & (1<<16))) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
|
{
|
{
|
// Print PC, instruction
|
// Print PC, instruction
|
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() << endl;
|
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << std::setw(8) << accessor->getWbInsn() << endl;
|
#if PRINT_REGS
|
#if PRINT_REGS
|
|
printregs = true;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// Exception version
|
|
if (accessor->getExceptFlushpipe())
|
|
{
|
|
// Print PC, instruction, indicate it caused an exception
|
|
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getExPC() << ": " << hex << std::setw(8) << accessor->getExInsn() << " (exception)" << endl;
|
|
#if PRINT_REGS
|
|
printregs = true;
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
if (printregs)
|
|
{
|
// Print general purpose register contents
|
// Print general purpose register contents
|
for (int i=0; i<32; i++)
|
for (int i=0; i<32; i++)
|
{
|
{
|
if ((i%4 == 0)&&(i>0)) statusFile << endl;
|
if ((i%4 == 0)&&(i>0)) statusFile << endl;
|
statusFile << std::setfill('0');
|
statusFile << std::setfill('0');
|
Line 411... |
Line 432... |
|
|
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) accessor->getSprSr() << " ";
|
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) accessor->getSprSr() << " ";
|
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " ";
|
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " ";
|
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " ";
|
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " ";
|
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl;
|
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl;
|
#endif
|
|
|
|
}
|
}
|
|
}
|
|
|
return;
|
return;
|
|
|
} // displayState()
|
} // displayState()
|
|
|