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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [api_core.cpp] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/*
2
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 */
16
 
17
#include <string>
18
#include "api_core.h"
19
#include "api_types.h"
20
#include "iclass.h"
21
#include "ihap.h"
22
#include "coreservices/ithread.h"
23
#include "coreservices/iclock.h"
24
 
25
namespace debugger {
26
 
27
static AttributeType Config_;
28
static AttributeType listClasses_(Attr_List);
29
static AttributeType listHap_(Attr_List);
30
static AttributeType listPlugins_(Attr_List);
31
extern mutex_def mutex_printf;
32
extern mutex_def mutexDefaultConsoles_;
33
 
34
extern void _load_plugins(AttributeType *list);
35
extern void _unload_plugins(AttributeType *list);
36
 
37
class CoreService : public IService {
38
public:
39
    CoreService(const char *name) : IService("CoreService") {
40
        active_ = 1;
41
        RISCV_mutex_init(&mutex_printf);
42
        RISCV_mutex_init(&mutexDefaultConsoles_);
43
        RISCV_event_create(&mutexExiting_, "mutexExiting_");
44
        //logLevel_.make_int64(LOG_DEBUG);  // default = LOG_ERROR
45
    }
46
    virtual ~CoreService() {
47
        RISCV_event_close(&mutexExiting_);
48
    }
49
 
50
    int isActive() { return active_; }
51
    void shutdown() { active_ = 0; }
52
    bool isExiting() { return mutexExiting_.state; }
53
    void setExiting() { RISCV_event_set(&mutexExiting_); }
54
private:
55
    int active_;
56
    event_def mutexExiting_;
57
};
58
static CoreService *pcore_ = NULL;
59
 
60
 
61
IFace *getInterface(const char *name) {
62
    return pcore_->getInterface(name);
63
}
64
 
65
 
66
extern "C" int RISCV_init() {
67
    pcore_ = new CoreService("core");
68
 
69
#if defined(_WIN32) || defined(__CYGWIN__)
70
    WSADATA wsaData;
71
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
72
        RISCV_error("Can't initialize sockets library", NULL);
73
    }
74
#endif
75
 
76
    _load_plugins(&listPlugins_);
77
    return 0;
78
}
79
 
80
extern "C" void RISCV_cleanup() {
81
    IClass *icls;
82
 
83
    // Pre-deletion
84
    for (unsigned i = 0; i < listClasses_.size(); i++) {
85
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
86
        icls->predeleteServices();
87
    }
88
 
89
#if defined(_WIN32) || defined(__CYGWIN__)
90
    WSACleanup();
91
#endif
92
 
93
    _unload_plugins(&listPlugins_);
94
    RISCV_mutex_lock(&mutex_printf);
95
    RISCV_mutex_destroy(&mutex_printf);
96
    RISCV_mutex_lock(&mutexDefaultConsoles_);
97
    RISCV_mutex_destroy(&mutexDefaultConsoles_);
98
    delete pcore_;
99
    RISCV_disable_log();
100
}
101
 
102
extern "C" int RISCV_set_configuration(AttributeType *cfg) {
103
    IClass *icls;
104
    IService *iserv;
105
 
106
    Config_.clone(cfg);
107
    if (!Config_.is_dict()) {
108
        printf("Wrong configuration.\n");
109
        return -1;
110
    }
111
 
112
    AttributeType &Services = Config_["Services"];
113
    if (Services.is_list()) {
114
        for (unsigned i = 0; i < Services.size(); i++) {
115
            const char *clsname = Services[i]["Class"].to_string();
116
            icls = static_cast<IClass *>(RISCV_get_class(clsname));
117
            if (icls == NULL) {
118
                printf("Class %s not found\n",
119
                             Services[i]["Class"].to_string());
120
                return -1;
121
            }
122
            /** Special global setting for the GUI class: */
123
            if (strcmp(icls->getClassName(), "GuiPluginClass") == 0) {
124
                if (!Config_["GlobalSettings"]["GUI"].to_bool()) {
125
                    RISCV_info("%s", "GUI disabled");
126
                    continue;
127
                }
128
            }
129
 
130
            AttributeType &Instances = Services[i]["Instances"];
131
            for (unsigned n = 0; n < Instances.size(); n++) {
132
                iserv = icls->createService(Instances[n]["Name"].to_string());
133
                iserv->initService(&Instances[n]["Attr"]);
134
            }
135
        }
136
    }
137
 
138
    // Post initialization
139
    for (unsigned i = 0; i < listClasses_.size(); i++) {
140
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
141
        icls->postinitServices();
142
    }
143
 
144
    RISCV_printf(getInterface(IFACE_SERVICE), 0, "%s",
145
    "\n**********************************************************\n"
146
    "  System Emulator and Debugger\n"
147
    "  Copyright (c) 2017 Sergey Khabarov.\n"
148
    "  All rights reserved.\n"
149
    "  e-mail: sergeykhbr@gmail.com\n"
150
    "**********************************************************");
151
 
152
    IHap *ihap;
153
    for (unsigned i = 0; i < listHap_.size(); i++) {
154
        ihap = static_cast<IHap *>(listHap_[i].to_iface());
155
        if (ihap->getType() == HAP_ConfigDone) {
156
            ihap->hapTriggered(getInterface(IFACE_SERVICE),
157
                        HAP_ConfigDone, "Initial config done");
158
        }
159
    }
160
    return 0;
161
}
162
 
163
extern "C" void RISCV_get_configuration(AttributeType *cfg) {
164
    IClass *icls;
165
    cfg->make_dict();
166
    (*cfg)["GlobalSettings"] = Config_["GlobalSettings"];
167
    (*cfg)["Services"].make_list(0);
168
    for (unsigned i = 0; i < listClasses_.size(); i++) {
169
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
170
        AttributeType val = icls->getConfiguration();
171
        (*cfg)["Services"].add_to_list(&val);
172
    }
173
    cfg->to_config();
174
}
175
 
176
extern "C" const AttributeType *RISCV_get_global_settings() {
177
    return &Config_["GlobalSettings"];
178
}
179
 
180
extern "C" void RISCV_register_class(IFace *icls) {
181
    AttributeType item(icls);
182
    listClasses_.add_to_list(&item);
183
}
184
 
185
extern "C" void RISCV_register_hap(IFace *ihap) {
186
    AttributeType item(ihap);
187
    listHap_.add_to_list(&item);
188
}
189
 
190
extern "C" void RISCV_trigger_hap(IFace *isrc, int type,
191
                                  const char *descr) {
192
    IHap *ihap;
193
    EHapType etype = static_cast<EHapType>(type);
194
    for (unsigned i = 0; i < listHap_.size(); i++) {
195
        ihap = static_cast<IHap *>(listHap_[i].to_iface());
196
        if (ihap->getType() == HAP_All || ihap->getType() == etype) {
197
            ihap->hapTriggered(isrc, etype, descr);
198
        }
199
    }
200
}
201
 
202
 
203
extern "C" IFace *RISCV_get_class(const char *name) {
204
    IClass *icls;
205
    for (unsigned i = 0; i < listClasses_.size(); i++) {
206
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
207
        if (strcmp(name, icls->getClassName()) == 0) {
208
            return icls;
209
        }
210
    }
211
    return NULL;
212
}
213
 
214
extern "C" IFace *RISCV_create_service(IFace *iclass, const char *name,
215
                                        AttributeType *args) {
216
    IClass *icls = static_cast<IClass *>(iclass);
217
    IService *iobj = icls->createService(name);
218
    iobj->initService(args);
219
    iobj->postinitService();
220
    return iobj;
221
}
222
 
223
extern "C" IFace *RISCV_get_service(const char *name) {
224
    IClass *icls;
225
    IService *iserv;
226
    for (unsigned i = 0; i < listClasses_.size(); i++) {
227
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
228
        if ((iserv = icls->getInstance(name)) != NULL) {
229
            return iserv;
230
        }
231
    }
232
    return NULL;
233
}
234
 
235
extern "C" IFace *RISCV_get_service_iface(const char *servname,
236
                                          const char *facename) {
237
    IService *iserv = static_cast<IService *>(RISCV_get_service(servname));
238
    if (iserv == NULL) {
239
        RISCV_error("Service '%s' not found.", servname);
240
        return NULL;
241
    }
242
    return iserv->getInterface(facename);
243
}
244
 
245
extern "C" IFace *RISCV_get_service_port_iface(const char *servname,
246
                                               const char *portname,
247
                                               const char *facename) {
248
    IService *iserv = static_cast<IService *>(RISCV_get_service(servname));
249
    if (iserv == NULL) {
250
        RISCV_error("Service '%s' not found.", servname);
251
        return NULL;
252
    }
253
    return iserv->getPortInterface(portname, facename);
254
}
255
 
256
extern "C" void RISCV_get_services_with_iface(const char *iname,
257
                                             AttributeType *list) {
258
    IClass *icls;
259
    IService *iserv;
260
    IFace *iface;
261
    const AttributeType *tlist;
262
    list->make_list(0);
263
 
264
    for (unsigned i = 0; i < listClasses_.size(); i++) {
265
        icls = static_cast<IClass *>(listClasses_[i].to_iface());
266
        tlist = icls->getInstanceList();
267
        for (unsigned n = 0; n < tlist->size(); n++) {
268
            iserv = static_cast<IService *>((*tlist)[n].to_iface());
269
            iface = iserv->getInterface(iname);
270
            if (iface) {
271
                AttributeType t1(iserv);
272
                list->add_to_list(&t1);
273
            }
274
        }
275
    }
276
}
277
 
278
extern "C" void RISCV_get_clock_services(AttributeType *list) {
279
    IService *iserv;
280
    RISCV_get_services_with_iface(IFACE_CLOCK, list);
281
    for (unsigned i = 0; i < list->size(); i++) {
282
        iserv = static_cast<IService *>((*list)[i].to_iface());
283
        (*list)[i].make_iface(iserv->getInterface(IFACE_CLOCK));
284
    }
285
}
286
 
287
static thread_return_t safe_exit_thread(void *args) {
288
    AttributeType t1, t2;
289
    IService *iserv;
290
    IThread *ith;
291
    RISCV_get_services_with_iface(IFACE_THREAD, &t1);
292
 
293
    for (unsigned i = 0; i < t1.size(); i++) {
294
        iserv = static_cast<IService *>(t1[i].to_iface());
295
        ith = static_cast<IThread *>(iserv->getInterface(IFACE_THREAD));
296
        printf("Stopping thread service '%s'. . .", iserv->getObjName());
297
        ith->stop();
298
        printf("Stopped\n");
299
    }
300
 
301
    RISCV_trigger_hap(getInterface(IFACE_SERVICE),
302
                      HAP_BreakSimulation, "Exiting");
303
    printf("All threads were stopped!\n");
304
    pcore_->shutdown();
305
    return 0;
306
}
307
 
308
struct TimerType {
309
    timer_callback_type cb;
310
    void *args;
311
    int interval;
312
    int delta;
313
    int single_shot;
314
};
315
 
316
static const int TIMERS_MAX = 2;
317
static TimerType timers_[TIMERS_MAX] = {{0}};
318
 
319
extern "C" void RISCV_break_simulation() {
320
    if (pcore_->isExiting()) {
321
        return;
322
    }
323
    pcore_->setExiting();
324
    LibThreadType data;
325
    data.func = reinterpret_cast<lib_thread_func>(safe_exit_thread);
326
    data.args = 0;
327
    RISCV_thread_create(&data);
328
}
329
 
330
 
331
extern "C" void RISCV_dispatcher_start() {
332
    TimerType *tmr;
333
    int sleep_interval = 20;
334
    int delta;
335
    while (pcore_->isActive()) {
336
        delta = 20;
337
        for (int i = 0; i < TIMERS_MAX; i++) {
338
            tmr = &timers_[i];
339
            if (!tmr->cb || !tmr->interval) {
340
                continue;
341
            }
342
 
343
            tmr->delta -= sleep_interval;
344
            if (tmr->delta <= 0) {
345
                tmr->cb(tmr->args);
346
                tmr->delta += tmr->interval;
347
                if (tmr->single_shot) {
348
                    RISCV_unregister_timer(tmr->cb);
349
                    continue;
350
                }
351
            }
352
            if (delta > tmr->delta) {
353
                delta = tmr->delta;
354
            }
355
        }
356
        sleep_interval = delta;
357
        RISCV_sleep_ms(sleep_interval);
358
    }
359
}
360
 
361
extern "C" void RISCV_register_timer(int msec, int single_shot,
362
                                     timer_callback_type cb, void *args) {
363
    TimerType *tmr = 0;
364
    for (int i = 0; i < TIMERS_MAX; i++) {
365
        if (timers_[i].cb == 0) {
366
            tmr = &timers_[i];
367
            break;
368
        }
369
    }
370
    if (tmr == 0) {
371
        RISCV_error("%s", "No available timer slot");
372
        return;
373
    }
374
    tmr->cb = cb;
375
    tmr->args = args;
376
    tmr->interval = msec;
377
    tmr->delta = msec;
378
    tmr->single_shot = single_shot;
379
}
380
 
381
extern "C" void RISCV_unregister_timer(timer_callback_type cb) {
382
    for (int i = 0; i < TIMERS_MAX; i++) {
383
        if (timers_[i].cb == cb) {
384
            timers_[i].cb = 0;
385
            timers_[i].args = 0;
386
            timers_[i].interval = 0;
387
            timers_[i].delta = 0;
388
            timers_[i].single_shot = 0;
389
        }
390
    }
391
}
392
 
393
}  // namespace debugger

powered by: WebSVN 2.1.0

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