OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [Or1200MonitorSC.cpp] - Blame information for rev 51

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 julius
// ----------------------------------------------------------------------------
2
 
3
// SystemC OpenRISC 1200 Monitor: implementation
4
 
5
// Copyright (C) 2008  Embecosm Limited <info@embecosm.com>
6
 
7
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 44 julius
// Contributor Julius Baxter <jb@orsoc.se>
9 6 julius
 
10
// This file is part of the cycle accurate model of the OpenRISC 1000 based
11
// system-on-chip, ORPSoC, built using Verilator.
12
 
13
// This program is free software: you can redistribute it and/or modify it
14
// under the terms of the GNU Lesser General Public License as published by
15
// the Free Software Foundation, either version 3 of the License, or (at your
16
// option) any later version.
17
 
18
// This program is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
21
// License for more details.
22
 
23
// You should have received a copy of the GNU Lesser General Public License
24
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 
26
// ----------------------------------------------------------------------------
27
 
28
// $Id: Or1200MonitorSC.cpp 303 2009-02-16 11:20:17Z jeremy $
29
 
30
#include <iostream>
31
#include <iomanip>
32 44 julius
#include <fstream>
33 6 julius
 
34 44 julius
using namespace std;
35
 
36 6 julius
#include "Or1200MonitorSC.h"
37 44 julius
#include "OrpsocMain.h"
38 6 julius
 
39
 
40
SC_HAS_PROCESS( Or1200MonitorSC );
41
 
42
//! Constructor for the OpenRISC 1200 monitor
43
 
44
//! @param[in] name  Name of this module, passed to the parent constructor.
45
//! @param[in] accessor  Accessor class for this Verilated ORPSoC model
46
 
47
Or1200MonitorSC::Or1200MonitorSC (sc_core::sc_module_name   name,
48 49 julius
                                  OrpsocAccess             *_accessor,
49 51 julius
                                  MemoryLoad               *_memoryload,
50 49 julius
                                  int argc,
51
                                  char *argv[]) :
52 6 julius
  sc_module (name),
53 51 julius
  accessor (_accessor),
54
  memoryload(_memoryload)
55 6 julius
{
56 49 julius
 
57
  // If not -log option, then don't log
58
 
59
  string logfileDefault("vlt-executed.log");
60
  string logfileNameString;
61 51 julius
  int profiling_enabled = 0;
62
  string profileFileName(DEFAULT_PROF_FILE);
63
  insn_count=0;
64
  cycle_count=0;
65 49 julius
 
66
  exit_perf_summary_enabled = 1; // Simulation exit performance summary is 
67
                                 // on by default. Turn off with "-q" on the cmd line
68
 
69
  // Parse the command line options
70
  int cmdline_name_found=0;
71
  if (argc > 1)
72
    {
73
      // Search through the command line parameters for the "-log" option
74
      for(int i=1; i < argc; i++)
75
        {
76
          if ((strcmp(argv[i], "-l")==0) ||
77
              (strcmp(argv[i], "--log")==0))
78
            {
79
              logfileNameString = (argv[i+1]);
80
              cmdline_name_found=1;
81
            }
82 51 julius
          else if ((strcmp(argv[i], "-q")==0) ||
83
                   (strcmp(argv[i], "--quiet")==0))
84 49 julius
            {
85
              exit_perf_summary_enabled = 0;
86
            }
87 51 julius
          else if ((strcmp(argv[i], "-p")==0) ||
88
                   (strcmp(argv[i], "--profile")==0))
89
            {
90
              profiling_enabled = 1;
91
              // Check for !end of command line and it's not a command
92
              if ((i+1 < argc)){
93
                if(argv[i+1][0] != '-')
94
                  profileFileName = (argv[i+1]);
95
              }
96
            }
97 49 julius
        }
98
    }
99
 
100
 
101 51 julius
  if (profiling_enabled)
102
    {
103
      profileFile.open(profileFileName.c_str(), ios::out); // Open profiling log file
104
      if(profileFile.is_open())
105
        {
106
          // If the file was opened OK, then enabled logging and print a message.
107
          profiling_enabled = 1;
108
          cout << "* Execution profiling enabled. Logging to " << profileFileName << endl;
109
        }
110
 
111
      // Setup profiling function
112
      SC_METHOD (callLog);
113
      sensitive << clk.pos();
114
      dont_initialize();
115
      start = clock();
116
    }
117 49 julius
 
118 51 julius
 
119 49 julius
  if(cmdline_name_found==1) // No -log option specified so don't turn on logging
120
    {
121
 
122
      logging_enabled = 0; // Default is logging disabled      
123
      statusFile.open(logfileNameString.c_str(), ios::out ); // open file to write to it
124
 
125
      if(statusFile.is_open())
126
        {
127
          // If we could open the file then turn on logging
128
          logging_enabled = 1;
129
          cout << "* Processor execution logged to file: " << logfileNameString << endl;
130
        }
131
 
132
    }
133 51 julius
  if (logging_enabled)
134
    {
135
      SC_METHOD (displayState);
136
      sensitive << clk.pos();
137
      dont_initialize();
138
      start = clock();
139
    }
140 49 julius
 
141
 
142
 
143
  // checkInstruction monitors the bus for special NOP instructionsl
144
  SC_METHOD (checkInstruction);
145 44 julius
  sensitive << clk.pos();
146
  dont_initialize();
147 49 julius
 
148
 
149
 
150 6 julius
}       // Or1200MonitorSC ()
151
 
152 49 julius
//! Print command line switches for the options of this module
153
void
154
Or1200MonitorSC::printSwitches()
155
{
156 51 julius
  printf(" [-l <file>] [-q] [-p [<file>]]");
157 49 julius
}
158 6 julius
 
159 49 julius
//! Print usage for the options of this module
160
void
161
Or1200MonitorSC::printUsage()
162
{
163 51 julius
  printf("  -p, --profile\t\tEnable execution profiling output to file (default "DEFAULT_PROF_FILE")\n");
164 49 julius
  printf("  -l, --log\t\tLog processor execution to file\n");
165
  printf("  -q, --quiet\t\tDisable the performance summary at end of simulation\n");
166
}
167
 
168 6 julius
//! Method to handle special instrutions
169
 
170
//! These are l.nop instructions with constant values. At present the
171
//! following are implemented:
172
 
173
//! - l.nop 1  Terminate the program
174
//! - l.nop 2  Report the value in R3
175
//! - l.nop 3  Printf the string with the arguments in R3, etc
176
//! - l.nop 4  Print a character
177 49 julius
extern int SIM_RUNNING;
178 6 julius
void
179
Or1200MonitorSC::checkInstruction()
180
{
181
  uint32_t  r3;
182
  double    ts;
183 51 julius
 
184 6 julius
  // Check the instruction when the freeze signal is low.
185
  if (!accessor->getWbFreeze())
186
    {
187
      // Do something if we have l.nop
188
      switch (accessor->getWbInsn())
189
        {
190
        case NOP_EXIT:
191
          r3 = accessor->getGpr (3);
192
          ts = sc_time_stamp().to_seconds() * 1000000000.0;
193
          std::cout << std::fixed << std::setprecision (2) << ts;
194
          std::cout << " ns: Exiting (" << r3 << ")" << std::endl;
195 49 julius
          perfSummary();
196 44 julius
          if (logging_enabled != 0) statusFile.close();
197 49 julius
          SIM_RUNNING=0;
198 6 julius
          sc_stop();
199
          break;
200
 
201
        case NOP_REPORT:
202
          ts = sc_time_stamp().to_seconds() * 1000000000.0;
203
          r3 = accessor->getGpr (3);
204
          std::cout << std::fixed << std::setprecision (2) << ts;
205
          std::cout << " ns: report (" << hex << r3 << ")" << std::endl;
206
          break;
207
 
208
        case NOP_PRINTF:
209
          ts = sc_time_stamp().to_seconds() * 1000000000.0;
210
          std::cout << std::fixed << std::setprecision (2) << ts;
211
          std::cout << " ns: printf" << std::endl;
212
          break;
213
 
214
        case NOP_PUTC:
215
          r3 = accessor->getGpr (3);
216
          std::cout << (char)r3 << std::flush;
217
          break;
218
 
219
        default:
220
          break;
221
        }
222
    }
223
 
224
}       // checkInstruction()
225
 
226 44 julius
 
227 51 julius
//! Method to log execution in terms of calls and returns
228
 
229
void
230
Or1200MonitorSC::callLog()
231
{
232
  uint32_t  exinsn, delaypc;
233
  uint32_t o_a; // operand a
234
  uint32_t o_b; // operand b
235
  struct label_entry *tmp;
236
 
237
  cycle_count++;
238
  // Instructions should be valid when freeze is low and there are no exceptions
239
  //if (!accessor->getExFreeze())
240
  if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0))
241
    {
242
      // Increment instruction counter
243
      insn_count++;
244
 
245
      //exinsn = accessor->getExInsn();// & 0x3ffffff;
246
      exinsn = accessor->getWbInsn();
247
      // Check the instruction
248
      switch((exinsn >> 26) & 0x3f) { // Check Opcode - top 6 bits
249
      case 0x1:
250
        /* Instruction: l.jal */
251
        o_a = (exinsn >> 0) & 0x3ffffff;
252
        if(o_a & 0x02000000) o_a |= 0xfe000000;
253
 
254
        //delaypc = accessor->getExPC() + (o_a * 4); // PC we're jumping to
255
        delaypc = accessor->getWbPC() + (o_a * 4); // PC we're jumping to
256
        // Now we have info about where we're jumping to. Output the info, with label if possible
257
        // We print the PC we're jumping from + 8 which is the return address
258
        if ( tmp = memoryload->get_label (delaypc) )
259
          profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl;
260
        else
261
          profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl;
262
 
263
        break;
264
      case 0x11:
265
        /* Instruction: l.jr */
266
        // Bits 15-11 contain register number
267
        o_b = (exinsn >> 11) & 0x1f;
268
        if (o_b == 9) // l.jr r9 is typical return
269
          {
270
            // Now get the value in this register
271
            delaypc = accessor->getGpr(o_b);
272
            // Output this jump
273
            profileFile << "-" << std::setfill('0') << hex << std::setw(8) << cycle_count << " "  << hex << std::setw(8) << delaypc << endl;
274
          }
275
        break;
276
      case 0x12:
277
        /* Instruction: l.jalr */
278
        o_b = (exinsn >> 11) & 0x1f;
279
        // Now get the value in this register
280
        delaypc = accessor->getGpr(o_b);
281
        // Now we have info about where we're jumping to. Output the info, with label if possible
282
        // We print the PC we're jumping from + 8 which is the return address
283
        if ( tmp = memoryload->get_label (delaypc) )
284
          profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl;
285
        else
286
          profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl;
287
 
288
        break;
289
 
290
      }
291
    }
292
}       // checkInstruction()
293
 
294
 
295 44 julius
//! Method to output the state of the processor
296
 
297
//! This function will output to a file, if enabled, the status of the processor
298
//! For now, it's just the PPC and instruction.
299 51 julius
#define PRINT_REGS 1
300 44 julius
void
301
Or1200MonitorSC::displayState()
302
{
303
  uint32_t  wbinsn;
304
 
305
  // Calculate how many instructions we've actually calculated by ignoring cycles where we're frozen, delay slots and flushpipe cycles
306
  if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
307
 
308
  if (logging_enabled == 0)
309
        return; // If we didn't inialise a file, then just return.
310
 
311
  // Output the state if we're not frozen and not flushing during a delay slot
312
  if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
313
    {
314 51 julius
      // Print PC, instruction
315
      statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() <<  endl;
316 49 julius
#if PRINT_REGS
317 44 julius
        // Print general purpose register contents
318
        for (int i=0; i<32; i++)
319 49 julius
          {
320 44 julius
                if ((i%4 == 0)&&(i>0)) statusFile << endl;
321
                statusFile << std::setfill('0');
322
                statusFile << "GPR" << dec << std::setw(2) << i << ": " <<  hex << std::setw(8) << (uint32_t) accessor->getGpr(i) << "  ";
323
        }
324
        statusFile << endl;
325
 
326
        statusFile << "SR   : " <<  hex << std::setw(8) << (uint32_t) accessor->getSprSr() << "  ";
327
        statusFile << "EPCR0: " <<  hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << "  ";
328
        statusFile << "EEAR0: " <<  hex << std::setw(8) << (uint32_t) accessor->getSprEear() << "  ";
329
        statusFile << "ESR0 : " <<  hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl;
330 49 julius
#endif
331 44 julius
 
332
    }
333
 
334
  return;
335
 
336
}       // displayState()
337
 
338
//! Function to calculate the number of instructions performed and the time taken
339
void
340
Or1200MonitorSC::perfSummary()
341
{
342 49 julius
  if (exit_perf_summary_enabled)
343
    {
344
      double ts;
345
      ts = sc_time_stamp().to_seconds() * 1000000000.0;
346
      int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had
347
 
348
      clock_t finish = clock();
349
      double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC;
350
      // It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second.
351
      double ips = (insn_count/elapsed_time);
352
      double mips = (insn_count/elapsed_time)/1000000;
353
      int hertz = (int) ((cycles/elapsed_time)/1000);
354
      std::cout << "* Or1200Monitor: simulated " << sc_time_stamp() << ",time elapsed: " << elapsed_time << " seconds" << endl;
355
      std::cout << "* Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed at approx " << hertz << "kHz" << endl;
356
      std::cout << "* Or1200Monitor: simulated " << insn_count << " instructions, insn/sec. = " << ips << ", mips = " << mips << endl;
357
    }
358
  return;
359
}       // perfSummary
360 44 julius
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.