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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [api_utils.cpp] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Core API utils methods implementation.
6
 */
7
 
8
#include <string.h>
9
#include <time.h>
10
#include <iostream>
11
#include <dirent.h>
12
#if defined(_WIN32) || defined(__CYGWIN__)
13
#else
14
    #include <dlfcn.h>
15
#endif
16
#include "api_types.h"
17
#include "api_utils.h"
18
#include "attribute.h"
19
#include "iservice.h"
20
#include "iclass.h"
21
#include "coreservices/irawlistener.h"
22
 
23
namespace debugger {
24
 
25
/** Plugin Entry point type definition */
26
typedef void (*plugin_init_proc)();
27
 
28
/** Temporary buffer for the log messages. */
29
static char bufLog[1<<12];
30
static int uniqueIdx_ = 0;
31
 
32
/** Redirect output to specified console. */
33
static AttributeType default_console(Attr_List);
34
mutex_def mutexDefaultConsoles_;
35
 
36
/** */
37
static FILE *logfile_ = 0;
38
 
39
static AttributeType log_file(Attr_String);
40
 
41
/** Mutex to avoid concurency for the output stream among threads. */
42
mutex_def mutex_printf;
43
 
44
/** Core log message interface object. */
45
extern IFace *getInterface(const char *name);
46
 
47
extern "C" void RISCV_generate_name(AttributeType *name) {
48
    char str[256];
49
    RISCV_sprintf(str, sizeof(str), "obj_%08x", uniqueIdx_++);
50
    name->make_string(str);
51
}
52
 
53
extern "C" void RISCV_add_default_output(void *iout) {
54
    AttributeType lstn(static_cast<IRawListener *>(iout));
55
    RISCV_mutex_lock(&mutexDefaultConsoles_);
56
    default_console.add_to_list(&lstn);
57
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
58
}
59
 
60
extern "C" void RISCV_remove_default_output(void *iout) {
61
    RISCV_mutex_lock(&mutexDefaultConsoles_);
62
    for (unsigned i = 0; i < default_console.size(); i++) {
63
        if (default_console[i].to_iface() == iout) {
64
            default_console.remove_from_list(i);
65
            break;
66
        }
67
    }
68
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
69
}
70
 
71
extern "C" int RISCV_enable_log(const char *filename) {
72
    if (logfile_) {
73
        fclose(logfile_);
74
        logfile_ = NULL;
75
    }
76
    logfile_ = fopen(filename, "w");
77
    if (!logfile_) {
78
        return 1;
79
    }
80
    return 0;
81
}
82
 
83
extern "C" void RISCV_disable_log() {
84
    if (logfile_) {
85
        fclose(logfile_);
86
    }
87
    logfile_ = 0;
88
}
89
 
90
extern "C" void RISCV_print_bin(int level, char *buf, int len) {
91
    std::cout.write(buf, len);
92
    //osLog.write(buf,len);
93
    //osLog.flush();
94
 
95
}
96
 
97
extern "C" int RISCV_printf(void *iface, int level,
98
                            const char *fmt, ...) {
99
    int ret = 0;
100
    va_list arg;
101
    IFace *iout = reinterpret_cast<IFace *>(iface);
102
 
103
    RISCV_mutex_lock(&mutex_printf);
104
    if (iout == NULL) {
105
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ", "unknown");
106
    } else if (strcmp(iout->getFaceName(), IFACE_SERVICE) == 0) {
107
        IService *iserv = static_cast<IService *>(iout);
108
        AttributeType *local_level =
109
                static_cast<AttributeType *>(iserv->getAttribute("LogLevel"));
110
        if (level > static_cast<int>(local_level->to_int64())) {
111
            RISCV_mutex_unlock(&mutex_printf);
112
            return 0;
113
        }
114
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
115
                                                   iserv->getObjName());
116
    } else if (strcmp(iout->getFaceName(), IFACE_CLASS) == 0) {
117
        IClass *icls = static_cast<IClass *>(iout);
118
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
119
                                                   icls->getClassName());
120
    } else {
121
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
122
                                                   iout->getFaceName());
123
    }
124
    va_start(arg, fmt);
125
#if defined(_WIN32) || defined(__CYGWIN__)
126
    ret += vsprintf_s(&bufLog[ret], sizeof(bufLog) - ret, fmt, arg);
127
#else
128
    ret += vsprintf(&bufLog[ret], fmt, arg);
129
#endif
130
    va_end(arg);
131
 
132
    bufLog[ret++] = '\n';
133
    bufLog[ret] = '\0';
134
    IRawListener *ilstn;
135
    RISCV_mutex_lock(&mutexDefaultConsoles_);
136
    for (unsigned i = 0; i < default_console.size(); i++) {
137
        ilstn = static_cast<IRawListener *>(default_console[i].to_iface());
138
        ilstn->updateData(bufLog, ret);
139
    }
140
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
141
    if (logfile_) {
142
        fwrite(bufLog, ret, 1, logfile_);
143
        fflush(logfile_);
144
    }
145
    RISCV_mutex_unlock(&mutex_printf);
146
    return ret;
147
}
148
 
149
extern "C" int RISCV_sprintf(char *s, size_t len, const char *fmt, ...) {
150
    int ret;
151
    va_list arg;
152
    va_start(arg, fmt);
153
#if defined(_WIN32) || defined(__CYGWIN__)
154
    ret = vsprintf_s(s, len, fmt, arg);
155
#else
156
    ret = vsprintf(s, fmt, arg);
157
#endif
158
    va_end(arg);
159
    return ret;
160
}
161
 
162
/* Suspend thread on certain number of milliseconds */
163
extern "C" void RISCV_sleep_ms(int ms) {
164
#if defined(_WIN32) || defined(__CYGWIN__)
165
    Sleep(ms);
166
#else
167
    usleep(1000*ms);
168
#endif
169
}
170
 
171
extern "C" uint64_t RISCV_get_time_ms() {
172
#if defined(_WIN32) || defined(__CYGWIN__)
173
    return 1000*(clock()/CLOCKS_PER_SEC);
174
#else
175
    struct timeval tc;
176
    gettimeofday(&tc, NULL);
177
    return 1000*tc.tv_sec + tc.tv_usec/1000;
178
#endif
179
}
180
 
181
extern "C" int RISCV_get_pid() {
182
#if defined(_WIN32) || defined(__CYGWIN__)
183
    return _getpid();
184
#else
185
    return getpid();
186
#endif
187
}
188
 
189
 
190
extern "C" void RISCV_thread_create(void *data) {
191
    LibThreadType *p = (LibThreadType *)data;
192
#if defined(_WIN32) || defined(__CYGWIN__)
193
    p->Handle = (thread_def)_beginthreadex(0, 0, p->func, p->args, 0, 0);
194
#else
195
    pthread_create(&p->Handle, 0, p->func, p->args);
196
#endif
197
}
198
 
199
extern "C" uint64_t RISCV_thread_id() {
200
          uint64_t r;
201
#if defined(_WIN32) || defined(__CYGWIN__)
202
          r = GetCurrentThreadId();
203
#else
204
          r = pthread_self();
205
#endif
206
          return r;
207
}
208
 
209
extern "C" void RISCV_thread_join(thread_def th, int ms) {
210
#if defined(_WIN32) || defined(__CYGWIN__)
211
    WaitForSingleObject(th, ms);
212
#else
213
    pthread_join(th, 0);
214
#endif
215
}
216
 
217
extern "C" void RISCV_event_create(event_def *ev, const char *name) {
218
#if defined(_WIN32) || defined(__CYGWIN__)
219
    ev->state = false;
220
    ev->cond = CreateEvent(
221
                NULL,               // default security attributes
222
                TRUE,               // manual-reset event
223
                FALSE,              // initial state is nonsignaled
224
                TEXT(name)          // object name
225
                );
226
#else
227
    pthread_mutex_init(&ev->mut, NULL);
228
    pthread_cond_init(&ev->cond, NULL);
229
    ev->state = false;
230
#endif
231
}
232
 
233
extern "C" void RISCV_event_close(event_def *ev) {
234
#if defined(_WIN32) || defined(__CYGWIN__)
235
    CloseHandle(ev->cond);
236
#else
237
    pthread_mutex_destroy(&ev->mut);
238
    pthread_cond_destroy(&ev->cond);
239
#endif
240
}
241
 
242
extern "C" void RISCV_event_set(event_def *ev) {
243
#if defined(_WIN32) || defined(__CYGWIN__)
244
    ev->state = true;
245
    SetEvent(ev->cond);
246
#else
247
    pthread_mutex_lock(&ev->mut);
248
    ev->state = true;
249
    pthread_mutex_unlock(&ev->mut);
250
    pthread_cond_signal(&ev->cond);
251
#endif
252
}
253
 
254
extern "C" int RISCV_event_is_set(event_def *ev) {
255
    return ev->state ? 1: 0;
256
}
257
 
258
extern "C" void RISCV_event_clear(event_def *ev) {
259
#if defined(_WIN32) || defined(__CYGWIN__)
260
    ev->state = false;
261
    ResetEvent(ev->cond);
262
#else
263
    ev->state = false;
264
#endif
265
}
266
 
267
extern "C" void RISCV_event_wait(event_def *ev) {
268
#if defined(_WIN32) || defined(__CYGWIN__)
269
    WaitForSingleObject(ev->cond, INFINITE);
270
#else
271
    int result = 0;
272
    pthread_mutex_lock(&ev->mut);
273
    while (result == 0 && !ev->state) {
274
        result = pthread_cond_wait(&ev->cond, &ev->mut);
275
    }
276
    pthread_mutex_unlock(&ev->mut);
277
#endif
278
}
279
 
280
extern "C" int RISCV_event_wait_ms(event_def *ev, int ms) {
281
#if defined(_WIN32) || defined(__CYGWIN__)
282
    DWORD wait_ms = ms;
283
    if (ms == 0) {
284
        wait_ms = INFINITE;
285
    }
286
    if (WAIT_TIMEOUT == WaitForSingleObject(ev->cond, wait_ms)) {
287
        return 1;
288
    }
289
    return 0;
290
#else
291
    struct timeval tc;
292
    struct timespec ts;
293
    int next_us;
294
    int result = 0;
295
    gettimeofday(&tc, NULL);
296
    next_us = tc.tv_usec + 1000 * ms;
297
    ts.tv_sec = tc.tv_sec + (next_us / 1000000);
298
    next_us -= 1000000 * (next_us / 1000000);
299
    ts.tv_nsec = 1000 * next_us;
300
 
301
    pthread_mutex_lock(&ev->mut);
302
    while (result == 0 && !ev->state) {
303
        result = pthread_cond_timedwait(&ev->cond, &ev->mut, &ts);
304
    }
305
    pthread_mutex_unlock(&ev->mut);
306
    if (ETIMEDOUT == result) {
307
        return 1;
308
    }
309
    return 0;
310
#endif
311
}
312
 
313
extern "C" int RISCV_mutex_init(mutex_def *mutex) {
314
#if defined(_WIN32) || defined(__CYGWIN__)
315
    InitializeCriticalSection(mutex);
316
#else
317
    pthread_mutex_init(mutex, NULL);
318
#endif
319
    return 0;
320
}
321
 
322
extern "C" int RISCV_mutex_lock(mutex_def *mutex) {
323
#if defined(_WIN32) || defined(__CYGWIN__)
324
    EnterCriticalSection(mutex);
325
#else
326
    pthread_mutex_lock(mutex) ;
327
#endif
328
    return 0;
329
}
330
 
331
extern "C" int RISCV_mutex_unlock(mutex_def * mutex) {
332
#if defined(_WIN32) || defined(__CYGWIN__)
333
    LeaveCriticalSection(mutex);
334
#else
335
    pthread_mutex_unlock(mutex);
336
#endif
337
    return 0;
338
}
339
 
340
extern "C" int RISCV_mutex_destroy(mutex_def *mutex) {
341
#if defined(_WIN32) || defined(__CYGWIN__)
342
    DeleteCriticalSection(mutex);
343
#else
344
    pthread_mutex_destroy(mutex);
345
#endif
346
    return 0;
347
}
348
 
349
extern "C" void *RISCV_malloc(uint64_t sz) {
350
    return malloc((size_t)sz);
351
}
352
 
353
extern "C" void RISCV_free(void *p) {
354
    if (p) {
355
        free(p);
356
    }
357
}
358
 
359
extern "C" int RISCV_get_core_folder(char *out, int sz) {
360
#if defined(_WIN32) || defined(__CYGWIN__)
361
    HMODULE hm = NULL;
362
    if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
363
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
364
            (LPCSTR)&RISCV_get_core_folder,
365
            &hm)) {
366
 
367
        return GetLastError();
368
    }
369
    GetModuleFileNameA(hm, out, sz);
370
#else
371
    Dl_info dl_info;
372
    dladdr((void *)RISCV_get_core_folder, &dl_info);
373
    RISCV_sprintf(out, sz, "%s", dl_info.dli_fname);
374
#endif
375
    int n = (int)strlen(out);
376
    while (n > 0 && out[n] != '\\' && out[n] != '/') n--;
377
 
378
    out[n+1] = '\0';
379
    return 0;
380
}
381
 
382
extern "C" void RISCV_set_current_dir() {
383
#if defined(_WIN32) || defined(__CYGWIN__)
384
    HMODULE hMod = GetModuleHandle(NULL);
385
    char path[MAX_PATH] = "";
386
    GetModuleFileNameA(hMod, path, MAX_PATH);
387
#else         // Linux
388
    // Get path of executable.
389
    char path[1024];
390
    ssize_t n = readlink("/proc/self/exe", path, sizeof(path)/sizeof(path[0]) - 1);
391
    if (n == -1) {
392
        return;
393
    }
394
    path[n] = 0;
395
#endif
396
 
397
    size_t i;
398
    for(i = strlen(path) - 1; i > 0 && path[i] != '/' && path[i] != '\\'; --i);
399
    path[i] = '\0';
400
 
401
#if defined(_WIN32) || defined(__CYGWIN__)
402
    SetCurrentDirectoryA(path);
403
#else         // Linux
404
    chdir(path);
405
#endif
406
}
407
 
408
/**
409
 * @brief   Loading all plugins from the 'plugins' sub-folder.
410
 * @details I suppose only one folders level so no itteration algorithm.
411
 */
412
void _load_plugins(AttributeType *list) {
413
#if defined(_WIN32) || defined(__CYGWIN__)
414
    HMODULE hlib;
415
#else
416
    void *hlib;
417
#endif
418
    DIR *dir;
419
    struct dirent *ent;
420
    plugin_init_proc plugin_init;
421
    char curdir[1024];
422
    std::string plugin_dir, plugin_lib;
423
 
424
    RISCV_get_core_folder(curdir, sizeof(curdir));
425
 
426
    plugin_dir = std::string(curdir) + "plugins/";
427
    dir = opendir(plugin_dir.c_str());
428
 
429
    if (dir == NULL) {
430
          RISCV_error("Plugins directory '%s' not found", curdir);
431
          return;
432
    }
433
 
434
    while ((ent = readdir(dir)) != NULL) {
435
        if (ent->d_type != DT_REG) {
436
            continue;
437
        }
438
        if ((strstr(ent->d_name, ".dll") == NULL)
439
         && (strstr(ent->d_name, ".so") == NULL)) {
440
            continue;
441
        }
442
        plugin_lib = plugin_dir + std::string(ent->d_name);
443
#if defined(_WIN32) || defined(__CYGWIN__)
444
        if ((hlib = LoadLibrary(plugin_lib.c_str())) == 0) {
445
            continue;
446
        }
447
        plugin_init = (plugin_init_proc)GetProcAddress(hlib, "plugin_init");
448
        if (!plugin_init) {
449
            FreeLibrary(hlib);
450
            continue;
451
        }
452
#else
453
        // reset errors
454
        dlerror();
455
        if ((hlib = dlopen(plugin_lib.c_str(), RTLD_LAZY)) == 0) {
456
            RISCV_info("Can't open library '%s': %s",
457
                       plugin_lib.c_str(), dlerror());
458
            continue;
459
        }
460
        plugin_init = (plugin_init_proc)dlsym(hlib, "plugin_init");
461
        if (dlerror()) {
462
            RISCV_info("Not found plugin_init() in file '%s'",
463
                       plugin_lib.c_str());
464
            dlclose(hlib);
465
            continue;
466
        }
467
#endif
468
 
469
        RISCV_info("Loading plugin file '%s'", plugin_lib.c_str());
470
        plugin_init();
471
 
472
        AttributeType item;
473
        item.make_list(2);
474
        item[0u] = AttributeType(plugin_lib.c_str());
475
        item[1] = AttributeType(Attr_UInteger,
476
                                reinterpret_cast<uint64_t>(hlib));
477
        list->add_to_list(&item);
478
    }
479
    closedir(dir);
480
}
481
 
482
void _unload_plugins(AttributeType *list) {
483
    for (unsigned i = 0; i < list->size(); i++) {
484
        if (!(*list)[i].is_list()) {
485
            RISCV_error("Can't free plugin[%d] library", i);
486
            continue;
487
        }
488
#if defined(_WIN32) || defined(__CYGWIN__)
489
        HMODULE hlib = reinterpret_cast<HMODULE>((*list)[i][1].to_uint64());
490
        FreeLibrary(hlib);
491
#else
492
        void *hlib = reinterpret_cast<void *>((*list)[i][1].to_uint64());
493
        dlclose(hlib);
494
#endif
495
    }
496
}
497
 
498
void put_char(char s, FILE *f) {
499
    fputc(s, f);
500
    fflush(f);
501
}
502
 
503
// check if this attribute like list with items <= 2: [a,b]
504
bool is_single_line(const char *s) {
505
    bool ret = false;
506
    if (*s == '[') {
507
        const char *pcheck = s + 1;
508
        int item_cnt = 0;
509
        int symbol_cnt = 0;
510
        while (*pcheck != ']') {
511
            symbol_cnt++;
512
            if (*pcheck == ',') {
513
                item_cnt++;
514
            } else if (*pcheck == '[' || *pcheck == '{') {
515
                item_cnt = 100;
516
                break;
517
            }
518
            ++pcheck;
519
        }
520
        if (item_cnt <= 2 && symbol_cnt < 80) {
521
            ret = true;
522
        }
523
    }
524
    return ret;
525
}
526
 
527
const char *writeAttrToFile(FILE *f, const char *s, int depth) {
528
    const char *ret = s;
529
    bool end_attr = false;
530
    bool do_single_line = false;
531
 
532
    if ((*s) == 0) {
533
        return ret;
534
    }
535
 
536
    put_char('\n', f);
537
    for (int i = 0; i < depth; i++) {
538
        put_char(' ', f);
539
        put_char(' ', f);
540
    }
541
 
542
 
543
    while ((*ret) && !end_attr) {
544
        put_char(*ret, f);
545
        if ((*ret) == ',') {
546
            if (!do_single_line) {
547
                put_char('\n', f);
548
                for (int i = 0; i < depth; i++) {
549
                    put_char(' ', f);
550
                    put_char(' ', f);
551
                }
552
            }
553
        } else if ((*ret) == ']' || (*ret) == '}') {
554
            if (do_single_line) {
555
                do_single_line = false;
556
            } else {
557
                return ret;
558
            }
559
        } else if ((*ret) == '[' || (*ret) == '{') {
560
            do_single_line = is_single_line(ret);
561
            if (!do_single_line) {
562
                ret = writeAttrToFile(f, ret + 1, depth + 1);
563
            }
564
        }
565
        ++ret;
566
    }
567
 
568
    return ret;
569
}
570
 
571
void RISCV_write_json_file(const char *filename, const char *s) {
572
    FILE *f = fopen(filename, "w");
573
    if (!f) {
574
        return;
575
    }
576
    writeAttrToFile(f, s, 0);
577
    fclose(f);
578
}
579
 
580
int RISCV_read_json_file(const char *filename, void *outattr) {
581
    AttributeType *out = reinterpret_cast<AttributeType *>(outattr);
582
    FILE *f = fopen(filename, "r");
583
    if (!f) {
584
        return 0;
585
    }
586
    fseek(f, 0, SEEK_END);
587
    int sz = ftell(f);
588
    out->make_data(sz);
589
 
590
    fseek(f, 0, SEEK_SET);
591
    fread(out->data(), sz, 1, f);
592
    return sz;
593
}
594
 
595
}  // namespace debugger

powered by: WebSVN 2.1.0

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