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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [cpp/] [pdump.cpp] - Blame information for rev 186

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 58 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    pdump.cpp
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
6
//
7
// Purpose:     Disassemble machine code files onto the stdout file.  Unlike
8
//              the zdump program that is part of the assembler suite, this
9
//      program takes the pfile.bin output of the bench test suite and adds
10
//      profiling information to the output.  It's useful for finding out where,
11
//      at least in simulation, your time is being spent.  It can also be used,
12
//      after the fact, to get a trace of what instructions the CPU executed.
13
//
14
// Creator:     Dan Gisselquist, Ph.D.
15 69 dgisselq
//              Gisselquist Technology, LLC
16 58 dgisselq
//
17
////////////////////////////////////////////////////////////////////////////////
18
//
19
// Copyright (C) 2015, Gisselquist Technology, LLC
20
//
21
// This program is free software (firmware): you can redistribute it and/or
22
// modify it under the terms of  the GNU General Public License as published
23
// by the Free Software Foundation, either version 3 of the License, or (at
24
// your option) any later version.
25
//
26
// This program is distributed in the hope that it will be useful, but WITHOUT
27
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
28
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
// for more details.
30
//
31
// You should have received a copy of the GNU General Public License along
32
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
33
// target there if the PDF file isn't present.)  If not, see
34
// <http://www.gnu.org/licenses/> for a copy.
35
//
36
// License:     GPL, v3, as defined and found on www.gnu.org,
37
//              http://www.gnu.org/licenses/gpl.html
38
//
39
//
40
////////////////////////////////////////////////////////////////////////////////
41
#include <algorithm>
42
#include <stdio.h>
43
#include <unistd.h>
44
#include <ctype.h>
45
 
46
#include "zopcodes.h"
47
 
48
typedef struct  { unsigned clks, addr; } ALT;
49
bool    altcmp(const ALT &a, const ALT &b) {
50
        return a.clks < b.clks;
51
}
52
 
53 186 dgisselq
#include <sys/types.h>
54
#include <sys/stat.h>
55
#include <fcntl.h>
56
#include <string.h>
57
#include <libelf.h>
58
#include <gelf.h>
59
 
60
 
61
bool    iself(const char *fname) {
62
        FILE    *fp;
63
        bool    ret = true;
64
        fp = fopen(fname, "rb");
65
 
66
        if (!fp)        return false;
67
        if (0x7f != fgetc(fp))  ret = false;
68
        if ('E'  != fgetc(fp))  ret = false;
69
        if ('L'  != fgetc(fp))  ret = false;
70
        if ('F'  != fgetc(fp))  ret = false;
71
        fclose(fp);
72
        return  ret;
73
 
74
}
75
 
76
 
77
long    fgetwords(FILE *fp) {
78
        // Return the number of words in the current file, and return the 
79
        // file as though it had never been adjusted
80
        long    fpos, flen;
81
        fpos = ftell(fp);
82
        if (0 != fseek(fp, 0l, SEEK_END)) {
83
                fprintf(stderr, "ERR: Could not determine file size\n");
84
                perror("O/S Err:");
85
                exit(-2);
86
        } flen = ftell(fp);
87
        if (0 != fseek(fp, fpos, SEEK_SET)) {
88
                fprintf(stderr, "ERR: Could not seek on file\n");
89
                perror("O/S Err:");
90
                exit(-2);
91
        } flen /= sizeof(ZIPI);
92
        return flen;
93
}
94
 
95
class   SECTION {
96
public:
97
        unsigned        m_start, m_len;
98
        ZIPI            m_data[1];
99
};
100
 
101
SECTION **singlesection(int nwords) {
102
        fprintf(stderr, "NWORDS = %d\n", nwords);
103
        size_t  sz = (2*(sizeof(SECTION)+sizeof(SECTION *))
104
                +(nwords-1)*(sizeof(ZIPI)));
105
        char    *d = (char *)malloc(sz);
106
        SECTION **r = (SECTION **)d;
107
        memset(r, 0, sz);
108
        r[0] = (SECTION *)(&d[2*sizeof(SECTION *)]);
109
        r[0]->m_len   = nwords;
110
        r[1] = (SECTION *)(&r[0]->m_data[r[0]->m_len]);
111
        r[0]->m_start = 0;
112
        r[1]->m_start = 0;
113
        r[1]->m_len   = 0;
114
 
115
        return r;
116
}
117
 
118
/*
119
SECTION **rawsection(const char *fname) {
120
        SECTION         **secpp, *secp;
121
        unsigned        num_words;
122
        FILE            *fp;
123
        int             nr;
124
 
125
        fp = fopen(fname, "r");
126
        if (fp == NULL) {
127
                fprintf(stderr, "Could not open: %s\n", fname);
128
                exit(-1);
129
        }
130
 
131
        if ((num_words=fgetwords(fp)) > MEMWORDS) {
132
                fprintf(stderr, "File overruns Block RAM\n");
133
                exit(-1);
134
        }
135
        secpp = singlesection(num_words);
136
        secp = secpp[0];
137
        secp->m_start = RAMBASE;
138
        secp->m_len = num_words;
139
        nr= fread(secp->m_data, sizeof(ZIPI), num_words, fp);
140
        if (nr != (int)num_words) {
141
                fprintf(stderr, "Could not read entire file\n");
142
                perror("O/S Err:");
143
                exit(-2);
144
        } assert(secpp[1]->m_len == 0);
145
 
146
        return secpp;
147
}*/
148
 
149
unsigned        byteswap(unsigned n) {
150
        unsigned        r;
151
 
152
        r = (n&0x0ff); n>>= 8;
153
        r = (r<<8) | (n&0x0ff); n>>= 8;
154
        r = (r<<8) | (n&0x0ff); n>>= 8;
155
        r = (r<<8) | (n&0x0ff); n>>= 8;
156
 
157
        return r;
158
}
159
 
160
void    elfread(const char *fname, unsigned &entry, SECTION **&sections) {
161
        Elf     *e;
162
        int     fd, i;
163
        size_t  n;
164
        char    *id;
165
        Elf_Kind        ek;
166
        GElf_Ehdr       ehdr;
167
        GElf_Phdr       phdr;
168
        const   bool    dbg = false;
169
 
170
        if (elf_version(EV_CURRENT) == EV_NONE) {
171
                fprintf(stderr, "ELF library initialization err, %s\n", elf_errmsg(-1));
172
                perror("O/S Err:");
173
                exit(EXIT_FAILURE);
174
        } if ((fd = open(fname, O_RDONLY, 0)) < 0) {
175
                fprintf(stderr, "Could not open %s\n", fname);
176
                perror("O/S Err:");
177
                exit(EXIT_FAILURE);
178
        } if ((e = elf_begin(fd, ELF_C_READ, NULL))==NULL) {
179
                fprintf(stderr, "Could not run elf_begin, %s\n", elf_errmsg(-1));
180
                exit(EXIT_FAILURE);
181
        }
182
 
183
        ek = elf_kind(e);
184
        if (ek == ELF_K_ELF) {
185
                ; // This is the kind of file we should expect
186
        } else if (ek == ELF_K_AR) {
187
                fprintf(stderr, "Cannot run an archive!\n");
188
                exit(EXIT_FAILURE);
189
        } else if (ek == ELF_K_NONE) {
190
                ;
191
        } else {
192
                fprintf(stderr, "Unexpected ELF file kind!\n");
193
                exit(EXIT_FAILURE);
194
        }
195
 
196
        if (gelf_getehdr(e, &ehdr) == NULL) {
197
                fprintf(stderr, "getehdr() failed: %s\n", elf_errmsg(-1));
198
                exit(EXIT_FAILURE);
199
        } if ((i=gelf_getclass(e)) == ELFCLASSNONE) {
200
                fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1));
201
                exit(EXIT_FAILURE);
202
        } if ((id = elf_getident(e, NULL)) == NULL) {
203
                fprintf(stderr, "getident() failed: %s\n", elf_errmsg(-1));
204
                exit(EXIT_FAILURE);
205
        } if (i != ELFCLASS32) {
206
                fprintf(stderr, "This is a 64-bit ELF file, ZipCPU ELF files are all 32-bit\n");
207
                exit(EXIT_FAILURE);
208
        }
209
 
210
        if (dbg) {
211
        printf("    %-20s 0x%jx\n", "e_type", (uintmax_t)ehdr.e_type);
212
        printf("    %-20s 0x%jx\n", "e_machine", (uintmax_t)ehdr.e_machine);
213
        printf("    %-20s 0x%jx\n", "e_version", (uintmax_t)ehdr.e_version);
214
        printf("    %-20s 0x%jx\n", "e_entry", (uintmax_t)ehdr.e_entry);
215
        printf("    %-20s 0x%jx\n", "e_phoff", (uintmax_t)ehdr.e_phoff);
216
        printf("    %-20s 0x%jx\n", "e_shoff", (uintmax_t)ehdr.e_shoff);
217
        printf("    %-20s 0x%jx\n", "e_flags", (uintmax_t)ehdr.e_flags);
218
        printf("    %-20s 0x%jx\n", "e_ehsize", (uintmax_t)ehdr.e_ehsize);
219
        printf("    %-20s 0x%jx\n", "e_phentsize", (uintmax_t)ehdr.e_phentsize);
220
        printf("    %-20s 0x%jx\n", "e_shentsize", (uintmax_t)ehdr.e_shentsize);
221
        printf("\n");
222
        }
223
 
224
 
225
        // Check whether or not this is an ELF file for the ZipCPU ...
226
        if (ehdr.e_machine != 0x0dadd) {
227
                fprintf(stderr, "This is not a ZipCPU ELF file\n");
228
                exit(EXIT_FAILURE);
229
        }
230
 
231
        // Get our entry address
232
        entry = ehdr.e_entry;
233
 
234
 
235
        // Now, let's go look at the program header
236
        if (elf_getphdrnum(e, &n) != 0) {
237
                fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
238
                exit(EXIT_FAILURE);
239
        }
240
 
241
        unsigned total_octets = 0, current_offset=0, current_section=0;
242
        for(i=0; i<(int)n; i++) {
243
                total_octets += sizeof(SECTION *)+sizeof(SECTION);
244
 
245
                if (gelf_getphdr(e, i, &phdr) != &phdr) {
246
                        fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1));
247
                        exit(EXIT_FAILURE);
248
                }
249
 
250
                if (dbg) {
251
                printf("    %-20s 0x%x\n", "p_type",   phdr.p_type);
252
                printf("    %-20s 0x%jx\n", "p_offset", phdr.p_offset);
253
                printf("    %-20s 0x%jx\n", "p_vaddr",  phdr.p_vaddr);
254
                printf("    %-20s 0x%jx\n", "p_paddr",  phdr.p_paddr);
255
                printf("    %-20s 0x%jx\n", "p_filesz", phdr.p_filesz);
256
                printf("    %-20s 0x%jx\n", "p_memsz",  phdr.p_memsz);
257
                printf("    %-20s 0x%x [", "p_flags",  phdr.p_flags);
258
 
259
                if (phdr.p_flags & PF_X)        printf(" Execute");
260
                if (phdr.p_flags & PF_R)        printf(" Read");
261
                if (phdr.p_flags & PF_W)        printf(" Write");
262
                printf("]\n");
263
                printf("    %-20s 0x%jx\n", "p_align", phdr.p_align);
264
                }
265
 
266
                total_octets += phdr.p_memsz;
267
        }
268
 
269
        char    *d = (char *)malloc(total_octets + sizeof(SECTION)+sizeof(SECTION *));
270
        memset(d, 0, total_octets);
271
 
272
        SECTION **r = sections = (SECTION **)d;
273
        current_offset = (n+1)*sizeof(SECTION *);
274
        current_section = 0;
275
 
276
        for(i=0; i<(int)n; i++) {
277
                r[i] = (SECTION *)(&d[current_offset]);
278
 
279
                if (gelf_getphdr(e, i, &phdr) != &phdr) {
280
                        fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1));
281
                        exit(EXIT_FAILURE);
282
                }
283
 
284
                if (dbg) {
285
                printf("    %-20s 0x%jx\n", "p_offset", phdr.p_offset);
286
                printf("    %-20s 0x%jx\n", "p_vaddr",  phdr.p_vaddr);
287
                printf("    %-20s 0x%jx\n", "p_paddr",  phdr.p_paddr);
288
                printf("    %-20s 0x%jx\n", "p_filesz", phdr.p_filesz);
289
                printf("    %-20s 0x%jx\n", "p_memsz",  phdr.p_memsz);
290
                printf("    %-20s 0x%x [", "p_flags",  phdr.p_flags);
291
 
292
                if (phdr.p_flags & PF_X)        printf(" Execute");
293
                if (phdr.p_flags & PF_R)        printf(" Read");
294
                if (phdr.p_flags & PF_W)        printf(" Write");
295
                printf("]\n");
296
 
297
                printf("    %-20s 0x%jx\n", "p_align", phdr.p_align);
298
                }
299
 
300
                current_section++;
301
 
302
                r[i]->m_start = phdr.p_vaddr;
303
                r[i]->m_len   = phdr.p_filesz/ sizeof(ZIPI);
304
 
305
                current_offset += phdr.p_memsz + sizeof(SECTION);
306
 
307
                // Now, let's read in our section ...
308
                if (lseek(fd, phdr.p_offset, SEEK_SET) < 0) {
309
                        fprintf(stderr, "Could not seek to file position %08lx\n", phdr.p_offset);
310
                        perror("O/S Err:");
311
                        exit(EXIT_FAILURE);
312
                } if (phdr.p_filesz > phdr.p_memsz)
313
                        phdr.p_filesz = 0;
314
                if (read(fd, r[i]->m_data, phdr.p_filesz) != (int)phdr.p_filesz) {
315
                        fprintf(stderr, "Didnt read entire section\n");
316
                        perror("O/S Err:");
317
                        exit(EXIT_FAILURE);
318
                }
319
 
320
                // Next, we need to byte swap it from big to little endian
321
                for(unsigned j=0; j<r[i]->m_len; j++)
322
                        r[i]->m_data[j] = byteswap(r[i]->m_data[j]);
323
 
324
                if (dbg) for(unsigned j=0; j<r[i]->m_len; j++)
325
                        fprintf(stderr, "ADR[%04x] = %08x\n", r[i]->m_start+j,
326
                        r[i]->m_data[j]);
327
        }
328
 
329
        r[i] = (SECTION *)(&d[current_offset]);
330
        r[current_section]->m_start = 0;
331
        r[current_section]->m_len   = 0;
332
 
333
        elf_end(e);
334
        close(fd);
335
}
336
 
337 58 dgisselq
void    dump_file(const char *fn) {
338
        const   int     NZIP = 4096;
339 75 dgisselq
        char    lna[NZIP], lnb[NZIP];
340 58 dgisselq
        ZIPI    ibuf[NZIP];
341
        FILE    *fp, *pf;
342
        int     nr;
343 186 dgisselq
        unsigned        addr=0x0100000, mina = -1, maxa = 0,
344 58 dgisselq
                        *pfcnt = NULL, *pfclk = NULL;
345
 
346
        pf = fopen("pfile.bin","rb");
347
        if (pf) {
348
                ALT     *pfalt;
349
                unsigned        buf[2], total_clks = 0;
350
                while(2 == fread(buf, sizeof(unsigned), 2, pf)) {
351
                        if (mina > buf[0])
352
                                mina = buf[0];
353
                        if (maxa < buf[0])
354
                                maxa = buf[0];
355
                }
356
 
357
                addr = mina;
358
                pfcnt = new unsigned[(maxa+2-mina)];
359
                pfclk = new unsigned[(maxa+2-mina)];
360
                pfalt = new ALT[(maxa+2-mina)];
361
                unsigned ncnt = maxa+2-mina;
362
                for(int i=0; i<(int)ncnt; i++)
363
                        pfcnt[i] = pfclk[i] = 0;
364
                for(int i=0; i<(int)ncnt; i++)
365
                        pfalt[i].addr = pfalt[i].clks = 0;
366
 
367
                rewind(pf);
368
                while(2 == fread(buf, sizeof(unsigned), 2, pf)) {
369
                        pfcnt[buf[0]-addr]++;
370
                        pfclk[buf[0]-addr] += buf[1];
371
                        pfalt[buf[0]-addr].clks += buf[1];
372
                        pfalt[buf[0]-addr].addr = buf[0];
373
                        total_clks += buf[1];
374
 
375
                        printf("%08x\n", buf[0]);
376
                } fclose(pf);
377
 
378
                printf("%08x (%8d) total clocks\n", total_clks, total_clks);
379
 
380
                std::sort(&pfalt[0], &pfalt[ncnt], altcmp);
381
 
382
                for(int i=0; i<(int)ncnt; i++)
383
                        printf("%08x: %8d\n", pfalt[i].addr, pfalt[i].clks);
384
        }
385
 
386
        printf("%s:\n", fn);
387 186 dgisselq
        if (iself(fn)) {
388
                SECTION **secpp=NULL, *secp;
389
                unsigned entry;
390
                elfread(fn, entry, secpp);
391
                for(int i=0; secpp[i]->m_len; i++) {
392
                        secp = secpp[i];
393
                        for(unsigned j=0; j<secp->m_len; j++) {
394
                                ZIPI    w = secp->m_data[j],a = secp->m_start+j;
395
                                zipi_to_string(secp->m_data[j], lna, lnb);
396
                                // printf("%s\n", ln);
397
                                printf("%08x[%08x-%08x]: (0x%08x %c%c%c%c) ",
398
                                        secp->m_start+j, maxa, mina, w,
399
                                        isgraph((w>>24)&0x0ff)?((w>>24)&0x0ff) : '.',
400
                                        isgraph((w>>16)&0x0ff)?((w>>16)&0x0ff) : '.',
401
                                        isgraph((w>> 8)&0x0ff)?((w>> 8)&0x0ff) : '.',
402
                                        isgraph((w    )&0x0ff)?((w    )&0x0ff) : '.'
403
                                        );
404
                                if ((a>=mina)&&(a<maxa)&&(pfcnt))
405
                                        printf("%8d %8d ", pfcnt[a-mina], pfclk[a-mina]);
406
                                printf("%s\n", lna);
407
                                if (lnb[0])
408
                                        printf("%26s%s\n", "", lnb);
409
                        }
410
                }
411
        } else {
412
                fp = fopen(fn, "r");
413
                if (!fp)
414
                        return;
415 58 dgisselq
 
416 186 dgisselq
                while((nr=fread(ibuf, sizeof(ZIPI), NZIP, fp))>0) {
417
                        for(int i=0; i<nr; i++) {
418
                                zipi_to_string(ibuf[i], lna, lnb);
419
                                // printf("%s\n", ln);
420
                                printf("%08x[%08x-%08x]: (0x%08x %c%c%c%c) ", addr,
421
                                        maxa, mina,
422
                                        ibuf[i],
423
                                        isgraph((ibuf[i]>>24)&0x0ff)?((ibuf[i]>>24)&0x0ff) : '.',
424
                                        isgraph((ibuf[i]>>16)&0x0ff)?((ibuf[i]>>16)&0x0ff) : '.',
425
                                        isgraph((ibuf[i]>> 8)&0x0ff)?((ibuf[i]>> 8)&0x0ff) : '.',
426
                                        isgraph((ibuf[i]    )&0x0ff)?((ibuf[i]    )&0x0ff) : '.'
427
                                        );
428
                                if ((addr>=mina)&&(addr<maxa)&&(pfcnt))
429
                                        printf("%8d %8d ", pfcnt[addr-mina], pfclk[addr-mina]);
430
                                printf("%s\n", lna);
431
                                if (lnb[0])
432
                                        printf("%26s%s\n", "", lnb);
433
 
434
                                addr++;
435
                        } if (nr < NZIP)
436
                                break;
437
                } fclose(fp);
438
        }
439 58 dgisselq
}
440
 
441
int main(int argc, char **argv) {
442 75 dgisselq
        if (argc <= 1)
443
                printf("USAGE: pdump <dump-file> | less\n");
444 58 dgisselq
        for(int argn=1; argn<argc; argn++) {
445
                if(access(argv[argn], R_OK)==0)
446
                        dump_file(argv[argn]);
447
        }
448
 
449
        return 0;
450
}
451
 

powered by: WebSVN 2.1.0

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