Line 3... |
Line 3... |
// SystemC OpenRISC 1200 Monitor: implementation
|
// SystemC OpenRISC 1200 Monitor: implementation
|
|
|
// Copyright (C) 2008 Embecosm Limited <info@embecosm.com>
|
// Copyright (C) 2008 Embecosm Limited <info@embecosm.com>
|
|
|
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
// Contributor Julius Baxter <jb@orsoc.se>
|
|
|
// This file is part of the cycle accurate model of the OpenRISC 1000 based
|
// This file is part of the cycle accurate model of the OpenRISC 1000 based
|
// system-on-chip, ORPSoC, built using Verilator.
|
// system-on-chip, ORPSoC, built using Verilator.
|
|
|
// This program is free software: you can redistribute it and/or modify it
|
// This program is free software: you can redistribute it and/or modify it
|
Line 26... |
Line 27... |
|
|
// $Id: Or1200MonitorSC.cpp 303 2009-02-16 11:20:17Z jeremy $
|
// $Id: Or1200MonitorSC.cpp 303 2009-02-16 11:20:17Z jeremy $
|
|
|
#include <iostream>
|
#include <iostream>
|
#include <iomanip>
|
#include <iomanip>
|
|
#include <fstream>
|
|
|
|
using namespace std;
|
|
|
#include "Or1200MonitorSC.h"
|
#include "Or1200MonitorSC.h"
|
|
#include "OrpsocMain.h"
|
|
|
|
|
SC_HAS_PROCESS( Or1200MonitorSC );
|
SC_HAS_PROCESS( Or1200MonitorSC );
|
|
|
//! Constructor for the OpenRISC 1200 monitor
|
//! Constructor for the OpenRISC 1200 monitor
|
Line 46... |
Line 51... |
{
|
{
|
SC_METHOD (checkInstruction);
|
SC_METHOD (checkInstruction);
|
sensitive << clk.pos();
|
sensitive << clk.pos();
|
dont_initialize();
|
dont_initialize();
|
|
|
|
SC_METHOD (displayState);
|
|
logging_enabled = 0; // Default is logging disabled
|
|
exit_perf_summary_enabled = 1; // Simulation exit performance summary is on by default. Turn off with "-q" on the cmd line
|
|
sensitive << clk.pos();
|
|
dont_initialize();
|
|
|
|
start = clock();
|
|
|
} // Or1200MonitorSC ()
|
} // Or1200MonitorSC ()
|
|
|
|
|
//! Method to handle special instrutions
|
//! Method to handle special instrutions
|
|
|
Line 76... |
Line 89... |
case NOP_EXIT:
|
case NOP_EXIT:
|
r3 = accessor->getGpr (3);
|
r3 = accessor->getGpr (3);
|
ts = sc_time_stamp().to_seconds() * 1000000000.0;
|
ts = sc_time_stamp().to_seconds() * 1000000000.0;
|
std::cout << std::fixed << std::setprecision (2) << ts;
|
std::cout << std::fixed << std::setprecision (2) << ts;
|
std::cout << " ns: Exiting (" << r3 << ")" << std::endl;
|
std::cout << " ns: Exiting (" << r3 << ")" << std::endl;
|
|
if (exit_perf_summary_enabled) perfSummary();
|
|
if (logging_enabled != 0) statusFile.close();
|
sc_stop();
|
sc_stop();
|
break;
|
break;
|
|
|
case NOP_REPORT:
|
case NOP_REPORT:
|
ts = sc_time_stamp().to_seconds() * 1000000000.0;
|
ts = sc_time_stamp().to_seconds() * 1000000000.0;
|
Line 104... |
Line 119... |
}
|
}
|
}
|
}
|
|
|
} // checkInstruction()
|
} // checkInstruction()
|
|
|
|
//! Method to setup the files for outputting the state of the processor
|
|
|
|
//! This function will setup the output file, if enabled.
|
|
|
|
void
|
|
Or1200MonitorSC::init_displayState(int argc, char *argv[])
|
|
{
|
|
|
|
string logfileDefault("vlt-executed.log");
|
|
string logfileNameString;
|
|
|
|
// Parse the command line options
|
|
int cmdline_name_found=0;
|
|
if (argc > 1)
|
|
{
|
|
// Search through the command line parameters for the "-log" option
|
|
for(int i=1; i < argc; i++)
|
|
{
|
|
if (strcmp(argv[i], "-log")==0)
|
|
{
|
|
logfileNameString = (argv[i+1]);
|
|
cmdline_name_found=1;
|
|
break;
|
|
}
|
|
}
|
|
// Search through the command line parameters for the "-q","--no-perf-summary" option
|
|
for(int i=1; i < argc; i++)
|
|
{
|
|
if ((strcmp(argv[i], "-q")==0)||(strcmp(argv[i], "--no-perf-summary")==0))
|
|
{
|
|
exit_perf_summary_enabled = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if(cmdline_name_found==0) // No -log option specified so don't turn on logging
|
|
return;
|
|
|
|
statusFile.open(logfileNameString.c_str(), ios::out ); // open file to write to it
|
|
|
|
if(statusFile.is_open())
|
|
{
|
|
// If we could open the file then turn on logging
|
|
logging_enabled = 1;
|
|
cout << "Processor execution logged to file: " << logfileNameString << endl;
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//! Method to output the state 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.
|
|
|
|
void
|
|
Or1200MonitorSC::displayState()
|
|
{
|
|
uint32_t wbinsn;
|
|
|
|
// 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()))
|
|
// Increment instruction counter
|
|
insn_count++;
|
|
|
|
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
|
|
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
|
|
{
|
|
// 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;
|
|
|
|
// Print general purpose register contents
|
|
for (int i=0; i<32; i++)
|
|
{
|
|
if ((i%4 == 0)&&(i>0)) statusFile << endl;
|
|
statusFile << std::setfill('0');
|
|
statusFile << "GPR" << dec << std::setw(2) << i << ": " << hex << std::setw(8) << (uint32_t) accessor->getGpr(i) << " ";
|
|
}
|
|
statusFile << endl;
|
|
|
|
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) accessor->getSprSr() << " ";
|
|
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " ";
|
|
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " ";
|
|
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} // displayState()
|
|
|
|
//! Function to calculate the number of instructions performed and the time taken
|
|
void
|
|
Or1200MonitorSC::perfSummary()
|
|
{
|
|
double ts;
|
|
ts = sc_time_stamp().to_seconds() * 1000000000.0;
|
|
int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had
|
|
|
|
clock_t finish = clock();
|
|
double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC;
|
|
// It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second.
|
|
double ips = (insn_count/elapsed_time);
|
|
double mips = (insn_count/elapsed_time)/1000000;
|
|
std::cout << "Or1200Monitor: real time elapsed: " << elapsed_time << " seconds" << endl;
|
|
std::cout << "Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed " << insn_count << " instructions" << endl;
|
|
std::cout << "Or1200Monitor: simulated insn/sec = " << ips << ", simulator mips = " << mips << endl;
|
|
return;
|
|
} // calculateMips()
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|