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

Subversion Repositories openrisc

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

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 57 julius
// $Id$
29 6 julius
 
30
#include <iostream>
31
#include <iomanip>
32 44 julius
#include <fstream>
33 861 stekern
#include <unistd.h>
34 52 julius
#include <sys/types.h>
35
#include <netinet/in.h>
36 44 julius
using namespace std;
37
 
38 6 julius
#include "Or1200MonitorSC.h"
39 44 julius
#include "OrpsocMain.h"
40 6 julius
 
41 63 julius
#include <errno.h>
42 462 julius
int monitor_to_gdb_pipe[2][2];  // [0][] - monitor to gdb, [1][] - gdb to 
43
                                // monitor, [][0] - read, [][1] - write
44 6 julius
 
45 462 julius
SC_HAS_PROCESS(Or1200MonitorSC);
46 6 julius
 
47
//! Constructor for the OpenRISC 1200 monitor
48
 
49
//! @param[in] name  Name of this module, passed to the parent constructor.
50
//! @param[in] accessor  Accessor class for this Verilated ORPSoC model
51
 
52 462 julius
Or1200MonitorSC::Or1200MonitorSC(sc_core::sc_module_name name,
53
                                 OrpsocAccess * _accessor,
54
                                 MemoryLoad * _memoryload,
55
                                 int argc,
56
                                 char *argv[]):sc_module(name),
57
accessor(_accessor), memoryload(_memoryload)
58 6 julius
{
59 52 julius
 
60 462 julius
        /* Assign defaults */
61
        string logfileDefault(DEFAULT_EXEC_LOG_FILE);
62
        string logfileNameString;
63
        trace_enabled = false;
64
        logging_enabled = false;
65
        logfile_name_provided = false;
66
        profiling_enabled = false;
67
        string profileFileName(DEFAULT_PROF_FILE);
68
        memdumpFileName = (DEFAULT_MEMDUMP_FILE);
69
        int memdump_start = -1;
70
        int memdump_end = -1;
71
        do_memdump = false;     // Default is not to do a dump of RAM at finish
72
        logging_regs = true;    // Execution log has GPR values by default
73
        bool rsp_server_enabled = false;
74
        wait_for_stall_cmd_response = false;    // Default
75
        insn_count = insn_count_rst = 0;
76
        cycle_count = cycle_count_rst = 0;
77 49 julius
 
78 462 julius
        perf_summary = false;
79
        monitor_for_crash = false;
80
        lookslikewevecrashed_count = crash_monitor_buffer_head = 0;
81 49 julius
 
82 462 julius
        bus_trans_log_enabled = bus_trans_log_name_provided = bus_trans_log_start_delay_enable = false; // Default
83
        string bus_trans_default_log_name(DEFAULT_BUS_LOG_FILE);
84
        string bus_trans_log_file;
85 63 julius
 
86 462 julius
        // Parse the command line options
87
        bool cmdline_name_found = false;
88
 
89
        /*  Search through the command line parameters for the "-log" option */
90
        for (int i = 1; i < argc && argc > 1; i++) {
91
                if ((strcmp(argv[i], "-l") == 0) ||
92
                    (strcmp(argv[i], "--log") == 0)) {
93
                        logging_enabled = true;
94
                        binary_log_format = false;
95
                        if (i + 1 < argc)
96
                                if (argv[i + 1][0] != '-') {
97
                                        logfileNameString = (argv[i + 1]);
98
                                        logfile_name_provided = true;
99
                                }
100
                        if (!logfile_name_provided)
101
                                logfileNameString = logfileDefault;
102
                } else if ((strcmp(argv[i], "--log-noregs") == 0)) {
103
                        logging_regs = false;
104
                } else if ((strcmp(argv[i], "--trace") == 0)) {
105
                        trace_enabled = true;
106
 
107
                } else if ((strcmp(argv[i], "-b") == 0) ||
108
                           (strcmp(argv[i], "--binlog") == 0)) {
109
                        logging_enabled = true;
110
                        binary_log_format = true;
111
                        if (i + 1 < argc)
112
                                if (argv[i + 1][0] != '-') {
113
                                        logfileNameString = (argv[i + 1]);
114
                                        logfile_name_provided = true;
115
                                }
116
                        if (!logfile_name_provided)
117
                                logfileNameString = logfileDefault;
118
 
119
                } else if ((strcmp(argv[i], "-c") == 0) ||
120
                           (strcmp(argv[i], "--crash-monitor") == 0)) {
121
                        monitor_for_crash = true;
122
                } else if ((strcmp(argv[i], "-u") == 0) ||
123
                           (strcmp(argv[i], "--summary") == 0)) {
124
                        perf_summary = true;
125
                } else if ((strcmp(argv[i], "-p") == 0) ||
126
                           (strcmp(argv[i], "--profile") == 0)) {
127
                        profiling_enabled = true;
128
                        // Check for !end of command line and that 
129
                        // next thing is not a command
130
                        if ((i + 1 < argc)) {
131
                                if (argv[i + 1][0] != '-')
132
                                        profileFileName = (argv[i + 1]);
133
                        }
134
                } else if ((strcmp(argv[i], "-r") == 0) ||
135
                           (strcmp(argv[i], "--rsp") == 0)) {
136
                        // We need to detect this here too
137
                        rsp_server_enabled = true;
138 52 julius
                }
139 462 julius
 
140
                else if ((strcmp(argv[i], "-m") == 0) ||
141
                         (strcmp(argv[i], "--memdump") == 0)) {
142
                        do_memdump = true;
143
                        /* Check for !end of command line and that next thing
144
                           is not a  command or a memory address.
145
                         */
146
                        if (i + 1 < argc) {
147
                                if ((argv[i + 1][0] != '-')
148
                                    && (strncmp("0x", argv[i + 1], 2) != 0)) {
149
                                        /* Hopefully this is the filename we
150
                                           want to use. All addresses should
151
                                           have preceeding hex identifier 0x
152
                                         */
153
                                        memdumpFileName = argv[i + 1];
154
                                        /* We've used this next index, can
155
                                           safely increment i
156
                                         */
157
                                        i++;
158
                                }
159
                        }
160
                        if (i + 1 < argc) {
161
                                if ((argv[i + 1][0] != '-')
162
                                    && (strncmp("0x", argv[i + 1], 2) == 0)) {
163
                                        sscanf(argv[i + 1], "0x%x",
164
                                               &memdump_start);
165
                                        i++;
166
                                }
167
                        }
168
                        if (i + 1 < argc) {
169
                                if ((argv[i + 1][0] != '-')
170
                                    && (strncmp("0x", argv[i + 1], 2) == 0)) {
171
                                        sscanf(argv[i + 1], "0x%x",
172
                                               &memdump_end);
173
                                        i++;
174
                                }
175
                        }
176 52 julius
                }
177 462 julius
#if 0
178
                else if ((strcmp(argv[i], "-u") == 0) ||
179
                         (strcmp(argv[i], "--bus-log") == 0)) {
180
                        bus_trans_log_enabled = true;
181
                        if (i + 1 < argc)
182
                                if (argv[i + 1][0] != '-') {
183
                                        bus_trans_log_file = (argv[i + 1]);
184
                                        bus_trans_log_name_provided = true;
185
                                }
186 63 julius
 
187 462 julius
                        if (!bus_trans_log_name_provided)
188
                                bus_trans_log_file = bus_trans_default_log_name;
189 63 julius
 
190 462 julius
                        /* check for a log start delay */
191
                        if (i + 2 < argc)
192
                                if (argv[i + 2][0] != '-') {
193
                                        /* We have a bus transaction log start
194
                                           delay */
195
                                        bus_trans_log_start_delay_enable = true;
196
                                        int time_val = atoi(argv[i + 2]);
197
                                        sc_time log_start_time(time_val, SC_NS);
198
                                        bus_trans_log_start_delay =
199
                                            log_start_time;
200
                                }
201
                }
202
#endif
203 57 julius
 
204 51 julius
        }
205 49 julius
 
206 462 julius
        if (!rsp_server_enabled) {
207
                monitor_to_gdb_pipe[0][0] = monitor_to_gdb_pipe[0][1] = NULL;
208
                monitor_to_gdb_pipe[1][0] = monitor_to_gdb_pipe[1][1] = NULL;
209 49 julius
        }
210 462 julius
        /* checkInstruction monitors the bus for special NOP instructionsl */
211
        SC_METHOD(checkInstruction);
212
        sensitive << clk.pos();
213
        dont_initialize();
214
 
215
        if (profiling_enabled) {
216
                // Open profiling log file
217
                profileFile.open(profileFileName.c_str(), ios::out);
218
                if (profileFile.is_open()) {
219
                        /* If the file was opened OK, then enabled logging and
220
                           print a message.
221
                        */
222
                        profiling_enabled = true;
223
                        cout << "* Execution profiling enabled. Logging to " <<
224
                            profileFileName << endl;
225
                }
226
                // Setup profiling function
227
                SC_METHOD(callLog);
228
                sensitive << clk.pos();
229
                dont_initialize();
230 63 julius
        }
231 462 julius
 
232
        if (logging_enabled) {
233
 
234
                /* Now open the file */
235
                if (binary_log_format)
236
                        statusFile.open(logfileNameString.c_str(),
237
                                        ios::out | ios::binary);
238
                else
239
                        statusFile.open(logfileNameString.c_str(), ios::out);
240
 
241
                /* Check the open() */
242
                if (statusFile.is_open() && binary_log_format) {
243
                        cout <<
244
                            "* Processor execution logged in binary format to file: "
245
                            << logfileNameString << endl;
246
                        /* Write out a byte indicating whether there's register
247
                           values too
248
                        */
249
                        statusFile.write((char *)&logging_regs, 1);
250
 
251
                } else if (statusFile.is_open() && !binary_log_format)
252
                        cout << "* Processor execution logged to file: " <<
253
                            logfileNameString << endl;
254
                else
255
                        /* Couldn't open */
256
                        logging_enabled = false;
257
 
258 63 julius
        }
259 49 julius
 
260 462 julius
        if (logging_enabled) {
261
                if (binary_log_format) {
262
                        SC_METHOD(displayStateBinary);
263
                } else {
264
                        SC_METHOD(displayState);
265
                }
266
                sensitive << clk.pos();
267
                dont_initialize();
268
                start = clock();
269 63 julius
 
270 52 julius
        }
271
 
272 462 julius
        if (monitor_for_crash) {
273
                cout << "* Crash monitor enabled" << endl;
274 52 julius
        }
275
 
276 462 julius
        if (do_memdump) {
277
                // Were we given dump addresses? If not, we dump all of the 
278
                // memory. Size of memory isn't clearly defined in any one 
279
                // place. This could lead to big problems when changing size of
280
                // the RAM in simulation.
281
 
282
                /* No memory dump beginning specified. Set to zero. */
283
                if (memdump_start == -1)
284
                        memdump_start = 0;
285
 
286
                /* No dump end specified, assign some token amount, probably
287
                   useless, but then the user should have specified more. */
288
                if (memdump_end == -1)
289
                        memdump_end = memdump_start + 0x2000;
290 63 julius
 
291 462 julius
                if (memdump_start & 0x3)
292
                        memdump_start &= ~0x3;  // word-align the start address      
293
                if (memdump_end & 0x3)
294
                        memdump_end = (memdump_end + 4) & ~0x3; // word-align the start address
295
 
296
                memdump_start_addr = memdump_start;
297
                memdump_end_addr = memdump_end;
298 63 julius
        }
299 462 julius
#if 0
300
        if (bus_trans_log_enabled) {
301
                // Setup log file and register the bus monitoring function
302
                busTransLog.open(bus_trans_log_file.c_str(), ios::out);
303 63 julius
 
304 462 julius
                if (busTransLog.is_open()) {
305
                        cout << "* System bus transactions logged to file: " <<
306
                            bus_trans_log_file;
307 353 julius
 
308 462 julius
                        if (bus_trans_log_start_delay_enable)
309
                                cout << ", on at " <<
310
                                    bus_trans_log_start_delay.to_string();
311
                        cout << endl;
312
                } else
313
                        // Couldn't open
314
                        bus_trans_log_enabled = false;
315
        }
316 6 julius
 
317 462 julius
        if (bus_trans_log_enabled) {
318
                // Setup profiling function
319
                SC_METHOD(busMonitor);
320
                sensitive << clk.pos();
321
                dont_initialize();
322
        }
323
#endif
324
 
325
        // Record roughly when we begin execution
326
        start = clock();
327
 
328
}                               // Or1200MonitorSC ()
329
 
330 49 julius
//! Print usage for the options of this module
331 462 julius
void
332
 Or1200MonitorSC::printUsage()
333 49 julius
{
334 462 julius
        printf("\nLogging and diagnostic options:\n");
335
        printf("      --trace\t\tEnable an execution trace to stdout during simulation\n");
336
        printf("  -u, --summary\t\tEnable summary on exit\n");
337
        printf
338
            ("  -p, --profile [<file>]\n\t\t\tEnable execution profiling output to <file> (default is\n\t\t\t"
339
             DEFAULT_PROF_FILE ")\n");
340
        printf("  -l, --log <file>\tLog processor execution to <file>\n");
341
        printf("      --log-noregs\tLog excludes register contents\n");
342 63 julius
 
343 462 julius
        printf
344
            ("  -b, --binlog <file>\tGenerate binary format execution log (faster, smaller)\n");
345 63 julius
 
346 462 julius
        printf
347
            ("  -m, --memdump <file> <0xstartaddr> <0xendaddr>\n\t\t\tDump data between <0xstartaddr> and <0xendaddr> from\n\t\t\tthe system's RAM to <file> in binary format on exit\n");
348
        printf
349
            ("  -c, --crash-monitor\tDetect when the processor has crashed and exit\n");
350 354 julius
/*
351 63 julius
  printf("  -u, --bus-log <file> <val>\n\t\t\tLog the wishbone bus transactions to <file>, opt. start\n\t\t\tafter <val> ns\n\n");
352 354 julius
*/
353 63 julius
 
354 49 julius
}
355
 
356 6 julius
//! Method to handle special instrutions
357
 
358
//! These are l.nop instructions with constant values. At present the
359
//! following are implemented:
360
 
361
//! - l.nop 1  Terminate the program
362
//! - l.nop 2  Report the value in R3
363
//! - l.nop 3  Printf the string with the arguments in R3, etc
364
//! - l.nop 4  Print a character
365 57 julius
 
366 462 julius
#define OR1200_OR32_NOP_INSN_TOP_BYTE 0x15
367
#define OR1200_OR32_NOP 0x14000000
368 57 julius
 
369 462 julius
 
370
void
371 6 julius
Or1200MonitorSC::checkInstruction()
372
{
373 462 julius
        uint32_t r3;
374
        double ts;
375
        uint32_t currentWbInsn, currentWbPC;
376
        clock_t now;
377
        double elapsedTime;
378
        int hertz, khertz;
379
        unsigned long long int psPeriod;
380
        char insnMSByte;
381
        uint32_t insnImm;
382 57 julius
 
383 462 julius
        cycle_count++;
384 6 julius
 
385 462 julius
        /* Check if this counts as an "executed" instruction */
386
        if (!accessor->getWbFreeze()) {
387
                // Memory writeback stage instruction
388
                currentWbInsn = accessor->getWbInsn();
389 6 julius
 
390 462 julius
                if (((((currentWbInsn & 0xfc000000) !=
391
                      (uint32_t) OR1200_OR32_NOP)
392
                     || !(currentWbInsn & (1 << 16)))
393
                    && !(accessor->getExceptFlushpipe()
394
                         && accessor->getExDslot())) ||
395
                    // Exception version
396
                    accessor->getExceptFlushpipe())
397
                {
398
 
399
                        insn_count++;
400
                        if (trace_enabled)
401
                                printTrace();
402
                }
403 6 julius
 
404 462 julius
        }
405
        // Check the instruction when the freeze signal is low.
406
        if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) {
407
                // Extract MSB of instruction
408
                insnMSByte = (currentWbInsn >> 24) & 0xff;
409
 
410
                if (insnMSByte == OR1200_OR32_NOP_INSN_TOP_BYTE)
411
                {
412
                        insnImm = currentWbInsn & 0xffff;
413 435 julius
 
414 462 julius
                // Do something if we have l.nop
415
                switch (insnImm) {
416
 
417
                case NOP_EXIT:
418
                        r3 = accessor->getGpr(3);
419
                        /* No timestamp with reports, so exit report is
420
                           same format as from or1ksim */
421
                        /*
422
                          ts = sc_time_stamp().to_seconds() *
423
                          1000000000.0;
424
                          std::cout << std::fixed << std::
425
                          setprecision(2) << ts;
426
                        */
427
                        std::
428
                                cout << "exit(" << r3 << ")" <<
429
                                std::endl;
430
                        if (perf_summary)
431
                                perfSummary();
432
 
433
                        if (logging_enabled)
434
                                statusFile.close();
435
                        if (profiling_enabled)
436
                                profileFile.close();
437
                        if (bus_trans_log_enabled)
438
                                busTransLog.close();
439
                        memdump();
440
                        gSimRunning = 0;
441
                        sc_stop();
442
                        break;
443
 
444
                case NOP_REPORT:
445
                        /* No timestamp with reports, so reports are
446
                           same format as from or1ksim */
447
                        /*
448
                          ts = sc_time_stamp().to_seconds() *
449
                          1000000000.0;
450
 
451
                          std::cout << std::fixed << std::
452
                          setprecision(2) << ts;
453
                        */
454
                        r3 = accessor->getGpr(3);
455
                        std::cout << "report(0x" <<
456
                                std::setfill('0') << hex <<
457
                                std::setw(8) << r3 << ");" << std::endl;
458
                        break;
459
 
460
                case NOP_PRINTF:
461
                        /*
462
                        ts = sc_time_stamp().to_seconds() * 1000000000.0;
463
                        std::cout << std::fixed << std::setprecision(2) << ts;
464
                        */
465
                        std::cout << "printf: ";
466
                        simPrintf(accessor->getGpr(4), accessor->getGpr(3));
467
                        break;
468
 
469
                case NOP_PUTC:
470
                        r3 = accessor->getGpr(3);
471
                        std::cout << (char)r3 << std::flush;
472
                        break;
473
 
474
                case NOP_GET_TICKS:
475
                        // Put number of cycles so far into r11 and r12
476
                        accessor->setGpr(11, (uint32_t) cycle_count&0xffffffff);
477
                        accessor->setGpr(12, (uint32_t) (cycle_count >> 32) &
478
                                         0xffffffff);
479
                        /*
480
                        std::cout << "NOP_GET_TICKS: " << dec << cycle_count <<
481
                                " r11:" << dec << accessor->getGpr(11) <<
482
                                " r12:" << dec << accessor->getGpr(12) <<
483
                                std::endl;
484
                        */
485
                        break;
486
                case NOP_GET_PS:
487
                        // Put PS/cycle into r11
488
                        now = clock();
489
                        elapsedTime =
490
                                (double (now) - double (start))/CLOCKS_PER_SEC;
491
 
492
                        // Calculate execution rate so far
493
                        khertz = (int)((cycle_count / elapsedTime) / 1000);
494
 
495
                        psPeriod
496
                                = (((unsigned long long int) 1000000000) /
497
                                   (unsigned long long int ) khertz);
498
 
499
                        accessor->setGpr(11, (uint32_t) psPeriod);
500
 
501
                        /*
502
                        std::cout << "NOP_GET_PS: khertz: " << dec << khertz <<
503
                                " r11:" << dec << accessor->getGpr(11) <<
504
                                endl;
505
                        */
506
                        break;
507
 
508
                case NOP_CNT_RESET:
509
                        if (!gQuiet) {
510
                                std::cout <<
511
                                    "****************** counters reset ******************"
512
                                    << endl;
513
                                std::cout << "since last reset: cycles " <<
514
                                    cycle_count -
515
                                    cycle_count_rst << ", insn #" << insn_count
516
                                    - insn_count_rst << endl;
517
                                std::cout <<
518
                                    "****************** counters reset ******************"
519
                                    << endl;
520
                                cycle_count_rst = cycle_count;
521
                                insn_count_rst = insn_count;
522
                                /* 3 separate counters we'll use for various things */
523
                        }
524
                case NOP_CNT_RESET1:
525
                        if (!gQuiet) {
526
                                std::cout << "**** counter1 cycles: " <<
527
                                    std::setfill('0') << std::setw(10) <<
528
                                    cycle_count -
529
                                    cycles_1 << " resetting ********" << endl;
530
                                cycles_1 = cycle_count;
531
                        }
532
                        break;
533
                case NOP_CNT_RESET2:
534
                        if (!gQuiet) {
535
                                std::cout << "**** counter2 cycles: " <<
536
                                    std::setfill('0') << std::setw(10) <<
537
                                    cycle_count -
538
                                    cycles_2 << " resetting ********" << endl;
539
                                cycles_2 = cycle_count;
540
                        }
541
                        break;
542
                case NOP_CNT_RESET3:
543
                        if (!gQuiet) {
544
                                std::cout << "**** counter3 cycles: " <<
545
                                    std::setfill('0') << std::setw(10) <<
546
                                    cycle_count -
547
                                    cycles_3 << " resetting ********" << endl;
548
                                cycles_3 = cycle_count;
549
                        }
550
                        break;
551
                default:
552
                        break;
553
                }
554
 
555
                }
556
 
557
                if (monitor_for_crash) {
558
                        currentWbPC = accessor->getWbPC();
559
                        // Look at current instruction
560
                        if (currentWbInsn == 0x00000000) {
561
                                // Looks like we've jumped somewhere incorrectly
562
                                lookslikewevecrashed_count++;
563
                        }
564
#define CRASH_MONITOR_LOG_BAD_INSNS 0
565 63 julius
#if CRASH_MONITOR_LOG_BAD_INSNS
566
 
567 462 julius
                        /* Log so-called "bad" instructions, or at least instructions we
568
                           executed, no matter if they caused us to increment
569
                           lookslikewevecrashed_count, this way we get them in our list too */
570
                        if ((insnMSByte != OR1200_OR32_NOP_INSN_TOP_BYTE)
571
                            || !(currentWbInsn & (1 << 16))) {
572
                                crash_monitor_buffer[crash_monitor_buffer_head]
573
                                    [0] = currentWbPC;
574
                                crash_monitor_buffer[crash_monitor_buffer_head]
575
                                    [1] = currentWbInsn;
576
                                /* Circular buffer */
577
                                if (crash_monitor_buffer_head <
578
                                    CRASH_MONITOR_BUFFER_SIZE - 1)
579
                                        crash_monitor_buffer_head++;
580
                                else
581
                                        crash_monitor_buffer_head = 0;
582
 
583
                        }
584 63 julius
#else
585 462 julius
                        else if (((insnMSByte != OR1200_OR32_NOP_INSN_TOP_BYTE))
586
                                 || !(currentWbInsn & (1 << 16))) {
587 63 julius
 
588 462 julius
                                crash_monitor_buffer[crash_monitor_buffer_head]
589
                                    [0] = currentWbPC;
590
                                crash_monitor_buffer[crash_monitor_buffer_head]
591
                                    [1] = currentWbInsn;
592
                                /* Circular buffer */
593
                                if (crash_monitor_buffer_head <
594
                                    CRASH_MONITOR_BUFFER_SIZE - 1)
595
                                        crash_monitor_buffer_head++;
596
                                else
597
                                        crash_monitor_buffer_head = 0;
598
 
599
                                /* Reset this */
600
                                lookslikewevecrashed_count = 0;
601
                        }
602
#endif
603
                        if (wait_for_stall_cmd_response) {
604
                                // We've already crashed, and we're issued a command to stall the
605
                                // processor to the system C debug unit interface, and we're
606
                                // waiting for this debug unit to send back the message that we've
607
                                // stalled.
608
                                char readChar;
609
                                int n =
610
                                    read(monitor_to_gdb_pipe[1][0], &readChar,
611
                                         sizeof(char));
612
                                if (!(((n < 0) && (errno == EAGAIN))
613
                                      || (n == 0)))
614
                                        wait_for_stall_cmd_response = false;    // We got response
615
                                lookslikewevecrashed_count = 0;
616
 
617
                        } else if (lookslikewevecrashed_count > 0) {
618
 
619
                                if (lookslikewevecrashed_count >=
620
                                    CRASH_MONITOR_BUFFER_SIZE / 4) {
621
                                        /* Probably crashed. Bail out, print out buffer */
622
                                        std::cout <<
623
                                            "********************************************************************************"
624
                                            << endl;
625
                                        std::cout <<
626
                                            "* Looks like processor crashed. Printing last "
627
                                            << CRASH_MONITOR_BUFFER_SIZE <<
628
                                            " instructions executed:" << endl;
629
 
630
                                        int crash_monitor_buffer_head_end =
631
                                            (crash_monitor_buffer_head >
632
                                             0) ? crash_monitor_buffer_head -
633
                                            1 : CRASH_MONITOR_BUFFER_SIZE - 1;
634
                                        while (crash_monitor_buffer_head !=
635
                                               crash_monitor_buffer_head_end) {
636
                                                std::cout << "* PC: " <<
637
                                                    std::setfill('0') << hex <<
638
                                                    std::setw(8) <<
639
                                                    crash_monitor_buffer
640
                                                    [crash_monitor_buffer_head]
641
                                                    [0] << "  INSN: " <<
642
                                                    std::setfill('0') << hex <<
643
                                                    std::setw(8) <<
644
                                                    crash_monitor_buffer
645
                                                    [crash_monitor_buffer_head]
646
                                                    [1] << endl;
647
 
648
                                                if (crash_monitor_buffer_head <
649
                                                    CRASH_MONITOR_BUFFER_SIZE -
650
                                                    1)
651
                                                        crash_monitor_buffer_head++;
652
                                                else
653
                                                        crash_monitor_buffer_head
654
                                                            = 0;
655
                                        }
656
                                        std::cout <<
657
                                            "********************************************************************************"
658
                                            << endl;
659
 
660
                                        if ((monitor_to_gdb_pipe[0][0] != NULL)) {
661
                                                // If GDB server is running, we'll pass control back to
662
                                                // the debugger instead of just quitting.
663
                                                char interrupt = 0x3;   // Arbitrary
664
                                                write(monitor_to_gdb_pipe[0][1],
665
                                                      &interrupt, sizeof(char));
666
                                                wait_for_stall_cmd_response =
667
                                                    true;
668
                                                lookslikewevecrashed_count = 0;
669
                                                std::cout <<
670
                                                    "* Stalling processor and returning control to GDB"
671
                                                    << endl;
672
                                                // Problem: the debug unit interface's stalling the processor over the simulated JTAG bus takes a while, in the meantime this monitor will continue running and keep triggering the crash detection code. We must somehow wait until the processor is stalled, or circumvent this crash detection output until we detect that the processor is stalled.
673
                                                // Solution: Added another pipe, when we want to wait for preocssor to stall, we set wait_for_stall_cmd_response=true, then each time we get back to this monitor function we simply poll the pipe until we're stalled. (A blocking read didn't work - this function never yielded and the RSP server handling function never got called).
674
                                                wait_for_stall_cmd_response =
675
                                                    true;
676
 
677
                                        } else {
678
                                                // Close down sim end exit
679
                                                ts = sc_time_stamp().to_seconds
680
                                                    () * 1000000000.0;
681
                                                std::cout << std::fixed <<
682
                                                    std::setprecision(2) << ts;
683
                                                std::cout << " ns: Exiting (" <<
684
                                                    r3 << ")" << std::endl;
685
                                                if (perf_summary)
686
                                                        perfSummary();
687
                                                if (logging_enabled)
688
                                                        statusFile.close();
689
                                                if (profiling_enabled)
690
                                                        profileFile.close();
691
                                                if (bus_trans_log_enabled)
692
                                                        busTransLog.close();
693
                                                memdump();
694
                                                gSimRunning = 0;
695
                                                sc_stop();
696
                                        }
697
                                }
698
                        }
699 63 julius
                }
700 462 julius
        }
701
}                               // checkInstruction()
702 6 julius
 
703 51 julius
//! Method to log execution in terms of calls and returns
704
 
705 462 julius
void
706 51 julius
Or1200MonitorSC::callLog()
707
{
708 462 julius
        uint32_t exinsn, delaypc;
709
        uint32_t o_a;           // operand a
710
        uint32_t o_b;           // operand b
711
        struct label_entry *tmp;
712 51 julius
 
713 462 julius
        // Instructions should be valid when freeze is low and there are no exceptions
714
        //if (!accessor->getExFreeze())
715
        if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) {
716
                //exinsn = accessor->getExInsn();// & 0x3ffffff;
717
                exinsn = accessor->getWbInsn();
718
                // Check the instruction
719
                switch ((exinsn >> 26) & 0x3f) {        // Check Opcode - top 6 bits
720
                case 0x1:
721
                        /* Instruction: l.jal */
722
                        o_a = (exinsn >> 0) & 0x3ffffff;
723
                        if (o_a & 0x02000000)
724
                                o_a |= 0xfe000000;
725 51 julius
 
726 462 julius
                        //delaypc = accessor->getExPC() + (o_a * 4); // PC we're jumping to
727
                        delaypc = accessor->getWbPC() + (o_a * 4);      // PC we're jumping to
728
                        // Now we have info about where we're jumping to. Output the info, with label if possible
729
                        // We print the PC we're jumping from + 8 which is the return address
730
                        if (tmp = memoryload->get_label(delaypc))
731
                                profileFile << "+" << std::setfill('0') << hex
732
                                    << std::setw(8) << cycle_count << " " << hex
733
                                    << std::setw(8) << accessor->getWbPC() +
734
                                    8 << " " << hex << std::setw(8) << delaypc
735
                                    << " " << tmp->name << endl;
736
                        else
737
                                profileFile << "+" << std::setfill('0') << hex
738
                                    << std::setw(8) << cycle_count << " " << hex
739
                                    << std::setw(8) << accessor->getWbPC() +
740
                                    8 << " " << hex << std::setw(8) << delaypc
741
                                    << " @" << hex << std::setw(8) << delaypc <<
742
                                    endl;
743 51 julius
 
744 462 julius
                        break;
745
                case 0x11:
746
                        /* Instruction: l.jr */
747
                        // Bits 15-11 contain register number
748
                        o_b = (exinsn >> 11) & 0x1f;
749
                        if (o_b == 9)   // l.jr r9 is typical return
750
                        {
751
                                // Now get the value in this register
752
                                delaypc = accessor->getGpr(o_b);
753
                                // Output this jump
754
                                profileFile << "-" << std::setfill('0') << hex
755
                                    << std::setw(8) << cycle_count << " " << hex
756
                                    << std::setw(8) << delaypc << endl;
757
                        }
758
                        break;
759
                case 0x12:
760
                        /* Instruction: l.jalr */
761
                        o_b = (exinsn >> 11) & 0x1f;
762
                        // Now get the value in this register
763
                        delaypc = accessor->getGpr(o_b);
764
                        // Now we have info about where we're jumping to. Output the info, with label if possible
765
                        // We print the PC we're jumping from + 8 which is the return address
766
                        if (tmp = memoryload->get_label(delaypc))
767
                                profileFile << "+" << std::setfill('0') << hex
768
                                    << std::setw(8) << cycle_count << " " << hex
769
                                    << std::setw(8) << accessor->getWbPC() +
770
                                    8 << " " << hex << std::setw(8) << delaypc
771
                                    << " " << tmp->name << endl;
772
                        else
773
                                profileFile << "+" << std::setfill('0') << hex
774
                                    << std::setw(8) << cycle_count << " " << hex
775
                                    << std::setw(8) << accessor->getWbPC() +
776
                                    8 << " " << hex << std::setw(8) << delaypc
777
                                    << " @" << hex << std::setw(8) << delaypc <<
778
                                    endl;
779
 
780
                        break;
781
 
782
                }
783
        }
784
}                               // callLog()
785
 
786
void
787
Or1200MonitorSC::printTrace()
788
{
789
        // TODO: Make this like or1ksim's trace, but for now print the basics
790
        //XXXXXXPC: XXXXINSN l.insn rA,rB,Imm    etc...
791
        std::cout <<
792
                std::setfill('0') << hex << std::setw(8) <<
793
                accessor->getWbPC() << ": " <<
794
                std::setfill('0') << hex << std::setw(8) <<
795
                accessor->getWbInsn() <<
796
                endl;
797
}
798
 
799 44 julius
//! Method to output the state of the processor
800
 
801
//! This function will output to a file, if enabled, the status of the processor
802 57 julius
//! This copies what the verilog testbench module, or1200_monitor does in it its
803
//! process which calls the display_arch_state tasks. This is designed to be 
804
//! identical to that process, so the output is identical
805 63 julius
 
806 462 julius
void
807 44 julius
Or1200MonitorSC::displayState()
808
{
809 462 julius
        // Output the state if we're not frozen and not flushing during a delay slot
810
        if (!accessor->getWbFreeze()) {
811
                if ((((accessor->getWbInsn() & 0xfc000000) !=
812
                      (uint32_t) OR1200_OR32_NOP)
813
                     || !(accessor->getWbInsn() & (1 << 16)))
814
                    && !(accessor->getExceptFlushpipe()
815
                         && accessor->getExDslot())) {
816
                        // Print PC, instruction
817
                        statusFile << "\nEXECUTED(" << std::setfill(' ') <<
818
                            std::setw(11) << dec << insn_count << "): " <<
819
                            std::
820
                            setfill('0') << hex << std::setw(8) << accessor->
821
                            getWbPC() << ":  " << hex << std::
822
                            setw(8) << accessor->getWbInsn() << endl;
823
                }
824
                // Exception version
825
                else if (accessor->getExceptFlushpipe()) {
826
                        // Print PC, instruction, indicate it caused an exception
827
                        statusFile << "\nEXECUTED(" << std::setfill(' ') <<
828
                            std::setw(11) << dec << insn_count << "): " <<
829
                            std::
830
                            setfill('0') << hex << std::setw(8) << accessor->
831
                            getExPC() << ":  " << hex << std::
832
                            setw(8) << accessor->
833
                            getExInsn() << "  (exception)" << endl;
834
                } else
835
                        return;
836
        } else
837
                return;
838
 
839
        if (logging_regs) {
840
                // Print general purpose register contents
841
                for (int i = 0; i < 32; i++) {
842
                        if ((i % 4 == 0) && (i > 0))
843
                                statusFile << endl;
844
                        statusFile << std::setfill('0');
845
                        statusFile << "GPR" << dec << std::setw(2) << i << ": "
846
                            << hex << std::
847
                            setw(8) << (uint32_t) accessor->getGpr(i) << "  ";
848
                }
849
                statusFile << endl;
850
 
851
                statusFile << "SR   : " << hex << std::setw(8) << (uint32_t)
852
                    accessor->getSprSr() << "  ";
853
                statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t)
854
                    accessor->getSprEpcr() << "  ";
855
                statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t)
856
                    accessor->getSprEear() << "  ";
857
                statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t)
858
                    accessor->getSprEsr() << endl;
859
 
860 44 julius
        }
861 462 julius
 
862 63 julius
        return;
863 44 julius
 
864 462 julius
}                               // displayState()
865
 
866 63 julius
//! Method to output the state of the processor in binary format
867
//! File format is simply first byte indicating whether register
868
//! data is included, and then structs of the following type
869 462 julius
struct s_binary_output_buffer {
870
        long long insn_count;
871
        uint32_t pc;
872
        uint32_t insn;
873
        char exception;
874
        uint32_t regs[32];
875
        uint32_t sr;
876
        uint32_t epcr0;
877
        uint32_t eear0;
878
        uint32_t eser0;
879
} __attribute__ ((__packed__));
880 63 julius
 
881 462 julius
struct s_binary_output_buffer_sans_regs {
882
        long long insn_count;
883
        uint32_t pc;
884
        uint32_t insn;
885
        char exception;
886
} __attribute__ ((__packed__));
887
 
888
void
889 63 julius
Or1200MonitorSC::displayStateBinary()
890
{
891 462 julius
        struct s_binary_output_buffer outbuf;
892
 
893
        // Output the state if we're not frozen and not flushing during a delay slot
894
        if (!accessor->getWbFreeze()) {
895
                if ((((accessor->getWbInsn() & 0xfc000000) !=
896
                      (uint32_t) OR1200_OR32_NOP)
897
                     || !(accessor->getWbInsn() & (1 << 16)))
898
                    && !(accessor->getExceptFlushpipe()
899
                         && accessor->getExDslot())) {
900
                        outbuf.insn_count = insn_count;
901
                        outbuf.pc = (uint32_t) accessor->getWbPC();
902
                        outbuf.insn = (uint32_t) accessor->getWbInsn();
903
                        outbuf.exception = 0;
904
                }
905
                // Exception version
906
                else if (accessor->getExceptFlushpipe()) {
907
                        outbuf.insn_count = insn_count;
908
                        outbuf.pc = (uint32_t) accessor->getExPC();
909
                        outbuf.insn = (uint32_t) accessor->getExInsn();
910
                        outbuf.exception = 1;
911
                } else
912
                        return;
913
        } else
914
                return;
915
 
916
        if (logging_regs) {
917
                // Print general purpose register contents
918
                for (int i = 0; i < 32; i++)
919
                        outbuf.regs[i] = (uint32_t) accessor->getGpr(i);
920
 
921
                outbuf.sr = (uint32_t) accessor->getSprSr();
922
                outbuf.epcr0 = (uint32_t) accessor->getSprEpcr();
923
                outbuf.eear0 = (uint32_t) accessor->getSprEear();
924
                outbuf.eser0 = (uint32_t) accessor->getSprEsr();
925
 
926
                statusFile.write((char *)&outbuf,
927
                                 sizeof(struct s_binary_output_buffer));
928
 
929
        } else
930
                statusFile.write((char *)&outbuf,
931
                                 sizeof(struct
932
                                        s_binary_output_buffer_sans_regs));
933
 
934 63 julius
        return;
935
 
936 462 julius
}                               // displayStateBinary()
937 63 julius
 
938 44 julius
//! Function to calculate the number of instructions performed and the time taken
939
void
940
Or1200MonitorSC::perfSummary()
941
{
942 462 julius
        double ts;
943
        ts = sc_time_stamp().to_seconds() * 1000000000.0;
944
        int cycles = ts / (BENCH_CLK_HALFPERIOD * 2);   // Number of clock cycles we had
945
 
946
        clock_t finish = clock();
947
        double elapsedTime =
948
                (double (finish) - double (start))/CLOCKS_PER_SEC;
949
        // It took elapsedTime seconds to do insn_count instructions. Divide 
950
        // insn_count by the time to get instructions/second.
951
        double ips = (insn_count / elapsedTime);
952
        double kips = (insn_count / elapsedTime) /1000;
953
        double mips = (insn_count / elapsedTime) / 1000000;
954
        int hertz = (int)((cycles / elapsedTime) / 1000);
955
        std::cout << "* Or1200Monitor: simulator time at exit: " << ts
956
                  << " ns" << endl;
957
        std::cout << "* Or1200Monitor: system time elapsed: " << elapsedTime
958
                  << " seconds" << endl;
959
        std::cout << "* Or1200Monitor: simulated " << dec << cycles <<
960
                " clock cycles, executed at approx " << hertz << "kHz" <<
961
                endl;
962
        std::cout << "* Or1200Monitor: simulated " << insn_count <<
963
                " instructions, 1000's insn/sec. = " << kips << endl;
964
        return;
965
}                               // perfSummary
966 44 julius
 
967 52 julius
//! Dump contents of simulation's RAM to file
968
void
969
Or1200MonitorSC::memdump()
970
{
971 462 julius
        if (!do_memdump)
972
                return;
973
        uint32_t current_word;
974
        int size_words = (memdump_end_addr / 4) - (memdump_start_addr / 4);
975
        if (!(size_words > 0))
976
                return;
977
 
978
        // First try opening the file
979
        memdumpFile.open(memdumpFileName.c_str(), ios::binary); // Open memorydump file
980
        if (memdumpFile.is_open()) {
981
                // If we could open the file then turn on logging
982
                cout << "* Dumping system RAM from  0x" << hex <<
983
                    memdump_start_addr << "-0x" << hex << memdump_end_addr <<
984
                    " to file " << memdumpFileName << endl;
985
 
986
                while (size_words) {
987
                        // Read the data from the simulation memory
988
                        current_word = accessor->get_mem32(memdump_start_addr);
989
                        // Change from whatever endian the host is (most
990
                        // cases little) to big endian
991
                        current_word = htonl(current_word);
992
                        memdumpFile.write((char *)&current_word, 4);
993
                        memdump_start_addr += 4;
994
                        size_words--;
995
                }
996
 
997
                // Ideally we've now finished piping out the data
998
                // not 100% about the endianess of this.
999 52 julius
        }
1000 462 julius
        memdumpFile.close();
1001
 
1002 52 julius
}
1003 63 julius
 
1004 353 julius
/*
1005 462 julius
  void
1006
  Or1200MonitorSC::busMonitor()
1007
  {
1008 63 julius
 
1009
  // This is for the wb_conmax module. Presumably other Wishbone bus arbiters
1010
  // will need this section of the code to be re-written appropriately, along
1011
  // with the relevent functions in the OrpsocAccess module.
1012
 
1013
  static busLogStates busLogState = BUS_LOG_IDLE;
1014
  static int currentMaster = -1;
1015
  static uint32_t currentAddr = 0, currentDataIn = 0;
1016
  static uint32_t currentSel = 0, currentSlave = 0;
1017
  static bool currentWe = false;
1018
  static int cyclesWaited = 0;
1019
 
1020
  if (bus_trans_log_start_delay_enable)
1021 462 julius
  {
1022
  if (sc_time_stamp() >= bus_trans_log_start_delay)
1023
  {
1024
  // No longer waiting
1025
  bus_trans_log_start_delay_enable = false;
1026
  cout << "* System log now enabled (time =  " << bus_trans_log_start_delay.to_string() << ")" << endl;
1027
  }
1028 63 julius
 
1029 462 julius
  if (bus_trans_log_start_delay_enable)
1030
  return;
1031
  }
1032 63 julius
 
1033
  switch ( busLogState )
1034 462 julius
  {
1035
  case BUS_LOG_IDLE:
1036
  {
1037
  // Check the current granted master's cyc and stb inputs
1038
  uint32_t gnt = accessor->getWbArbGrant();
1039
  if (accessor->getWbArbMastCycI(gnt) && accessor->getWbArbMastStbI(gnt) &&
1040
  !accessor->getWbArbMastAckO(gnt))
1041
  {
1042
  currentAddr = accessor->getWbArbMastAdrI(gnt);
1043
  currentDataIn = accessor->getWbArbMastDatI(gnt);
1044
  currentSel = (uint32_t) accessor->getWbArbMastSelI(gnt);
1045
  currentSlave = (uint32_t)accessor->getWbArbMastSlaveSelDecoded(gnt)-1;
1046
  currentWe = accessor->getWbArbMastWeI(gnt);
1047
  currentMaster = gnt;
1048
  busLogState = BUS_LOG_WAIT_FOR_ACK;
1049
  cyclesWaited = 0;
1050
  }
1051
  }
1052 63 julius
 
1053 462 julius
  break;
1054 63 julius
 
1055 462 julius
  case BUS_LOG_WAIT_FOR_ACK:
1056 63 julius
 
1057 462 julius
  cyclesWaited++;
1058 63 julius
 
1059 462 julius
  // Check for ACK
1060
  if (accessor->getWbArbMastAckO(currentMaster))
1061
  {
1062
  // Transaction completed
1063
  busTransLog << sc_time_stamp() << " M" << currentMaster << " ";
1064
  if (currentWe)
1065
  busTransLog << " W " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec <<  currentSlave << " " << hex << std::setw(8) << currentDataIn << " " << dec << cyclesWaited << endl;
1066
  else
1067
  busTransLog << " R " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec << currentSlave << " "  << hex << std::setw(8) << accessor->getWbArbMastDatO(currentMaster) << " " << dec << cyclesWaited << endl;
1068 63 julius
 
1069 462 julius
  busLogState = BUS_LOG_IDLE;
1070
  }
1071 63 julius
 
1072 462 julius
  break;
1073 63 julius
 
1074 462 julius
  }
1075 63 julius
 
1076
  return;
1077
 
1078 462 julius
  }     // busMonitor ()
1079 353 julius
*/
1080 462 julius
void
1081 66 julius
Or1200MonitorSC::simPrintf(uint32_t stackaddr, uint32_t regparam)
1082
{
1083
 
1084 462 julius
        //cerr << hex << stackaddr << " " << regparam << endl;
1085 66 julius
#define FMTLEN 2000
1086 462 julius
        char fmtstr[FMTLEN];
1087
        uint32_t arg;
1088
        oraddr_t argaddr;
1089
        char *fmtstrend;
1090
        char *fmtstrpart = fmtstr;
1091
        int tee_exe_log;
1092 66 julius
 
1093 462 julius
        /*simgetstr (stackaddr, regparam); */
1094
        /* Get the format string */
1095
        uint32_t fmtaddr;
1096
        int i;
1097
        fmtaddr = regparam;
1098 66 julius
 
1099 462 julius
        i = 0;
1100
        while (accessor->get_mem8(fmtaddr) != '\0') {
1101
                fmtstr[i++] = accessor->get_mem8(fmtaddr);
1102
                fmtaddr++;
1103
                if (i == FMTLEN - 1)
1104
                        break;
1105 66 julius
        }
1106 462 julius
        fmtstr[i] = '\0';
1107 66 julius
 
1108 462 julius
        argaddr = stackaddr;
1109
        int index, last_index;
1110
        index = last_index = 0;
1111
        char tmp_char;
1112
        while (1) {
1113
                /* Look for the next format argument, or end of string */
1114
                while (!(fmtstrpart[index] == '\0' || fmtstrpart[index] == '%'))
1115
                        index++;
1116
 
1117
                if (fmtstrpart[index] == '\0' && index == last_index)
1118
                        /* We had something like "%d\0", so we're done */
1119
                        return;
1120
 
1121
                if (fmtstrpart[index] == '\0') {
1122
                        /* Final printf */
1123
                        printf("%s", (char *)fmtstrpart + last_index);
1124
                        return;
1125
                } else {
1126
                        /* We have a section between last_index and index that we should print out */
1127
                        fmtstrpart[index] = '\0';       /* Replace % with \0 for now */
1128
                        printf("%s", fmtstrpart + last_index);
1129
                        fmtstrpart[index] = '%';        /* Replace the % */
1130
                }
1131
 
1132
                last_index = index;     /* last_index now pointing at the % */
1133
 
1134
                /* Now extract the part that requires formatting */
1135
                /* Look for the end of the format argument */
1136
                while (!(fmtstrpart[index] == 'd' || fmtstrpart[index] == 'i'
1137
                         || fmtstrpart[index] == 'o' || fmtstrpart[index] == 'u'
1138
                         || fmtstrpart[index] == 'x' || fmtstrpart[index] == 'X'
1139
                         || fmtstrpart[index] == 'f' || fmtstrpart[index] == 'e'
1140
                         || fmtstrpart[index] == 'E' || fmtstrpart[index] == 'g'
1141
                         || fmtstrpart[index] == 'G' || fmtstrpart[index] == 'c'
1142
                         || fmtstrpart[index] == 's'
1143
                         || fmtstrpart[index] == '\0'
1144
                         || fmtstrpart[index + 1] == '%'))
1145
                        index++;
1146
 
1147
                if (fmtstrpart[index] == '\0') {
1148
                        // Error
1149
                        return;
1150
                } else if (fmtstrpart[index] == '%'
1151
                           && fmtstrpart[index + 1] == '%') {
1152
                        /* Deal with the %% case to print a single % */
1153
                        index++;
1154
                        printf("%%");
1155
                } else {
1156
                        /* We now will print the part that requires the next argument */
1157
                        /* Same trick, but this time remember what the char was */
1158
                        tmp_char = fmtstrpart[index + 1];
1159
                        fmtstrpart[index + 1] = '\0';   /* Replace % with \0 for now */
1160
                        /* Check what we're printing */
1161
                        if (fmtstrpart[index] == 's') {
1162
                                /* It's a string, so pull it out of memory into a local char*
1163
                                   and pass it to printf() */
1164
                                int tmp_string_len, z;
1165
                                /* Assume stackaddr already pointing at appropriate value */
1166
                                oraddr_t ormem_str_ptr =
1167
                                    accessor->get_mem32(argaddr);
1168
 
1169
                                while (accessor->get_mem8(ormem_str_ptr++) !=
1170
                                       '\0')
1171
                                        tmp_string_len++;
1172
                                tmp_string_len++;       /* One for terminating char */
1173
 
1174
                                char *str = (char *)malloc(tmp_string_len);
1175
                                if (str == NULL)
1176
                                        return; /* Malloc failed, bigger issues than printf'ing out of sim */
1177
                                ormem_str_ptr = accessor->get_mem32(argaddr);   /* Reset start pointer value */
1178
                                for (z = 0; z < tmp_string_len; z++)
1179
                                        str[z] =
1180
                                            accessor->get_mem8(ormem_str_ptr +
1181
                                                               z);
1182
 
1183
                                printf(fmtstrpart + last_index, str);
1184
                                free(str);
1185
                        } else {
1186
                                /*
1187
                                   Some other kind of variable, pull it off the stack and print
1188
                                   it out. Assume stackaddr already pointing at appropriate
1189
                                   value
1190
                                 */
1191
                                arg = accessor->get_mem32(argaddr);
1192
                                printf(fmtstrpart + last_index, arg);
1193
                        }
1194
                        argaddr += 4;   /* Increment argument pointer in stack */
1195
                        fmtstrpart[index + 1] = tmp_char;       /* Replace the char we took out */
1196
                }
1197
                index++;
1198
                last_index = index;
1199 66 julius
        }
1200
 
1201 462 julius
        return;
1202
}                               // simPrintf ()

powered by: WebSVN 2.1.0

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