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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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