| 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 methods implementation.
|
| 6 |
|
|
*/
|
| 7 |
|
|
|
| 8 |
|
|
#include <string>
|
| 9 |
|
|
#include "api_core.h"
|
| 10 |
|
|
#include "api_types.h"
|
| 11 |
|
|
#include "iclass.h"
|
| 12 |
|
|
#include "ihap.h"
|
| 13 |
|
|
#include "coreservices/ithread.h"
|
| 14 |
|
|
#include "coreservices/iclock.h"
|
| 15 |
|
|
|
| 16 |
|
|
namespace debugger {
|
| 17 |
|
|
|
| 18 |
|
|
static AttributeType Config_;
|
| 19 |
|
|
static AttributeType listClasses_(Attr_List);
|
| 20 |
|
|
static AttributeType listHap_(Attr_List);
|
| 21 |
|
|
static AttributeType listPlugins_(Attr_List);
|
| 22 |
|
|
extern mutex_def mutex_printf;
|
| 23 |
|
|
extern mutex_def mutexDefaultConsoles_;
|
| 24 |
|
|
|
| 25 |
|
|
extern void _load_plugins(AttributeType *list);
|
| 26 |
|
|
extern void _unload_plugins(AttributeType *list);
|
| 27 |
|
|
|
| 28 |
|
|
class CoreService : public IService {
|
| 29 |
|
|
public:
|
| 30 |
|
|
CoreService(const char *name) : IService("CoreService") {
|
| 31 |
|
|
active_ = 1;
|
| 32 |
|
|
RISCV_mutex_init(&mutex_printf);
|
| 33 |
|
|
RISCV_mutex_init(&mutexDefaultConsoles_);
|
| 34 |
|
|
RISCV_event_create(&mutexExiting_, "mutexExiting_");
|
| 35 |
|
|
//logLevel_.make_int64(LOG_DEBUG); // default = LOG_ERROR
|
| 36 |
|
|
}
|
| 37 |
|
|
virtual ~CoreService() {
|
| 38 |
|
|
RISCV_event_close(&mutexExiting_);
|
| 39 |
|
|
}
|
| 40 |
|
|
|
| 41 |
|
|
int isActive() { return active_; }
|
| 42 |
|
|
void shutdown() { active_ = 0; }
|
| 43 |
|
|
bool isExiting() { return mutexExiting_.state; }
|
| 44 |
|
|
void setExiting() { RISCV_event_set(&mutexExiting_); }
|
| 45 |
|
|
private:
|
| 46 |
|
|
int active_;
|
| 47 |
|
|
event_def mutexExiting_;
|
| 48 |
|
|
};
|
| 49 |
|
|
static CoreService core_("core");
|
| 50 |
|
|
|
| 51 |
|
|
|
| 52 |
|
|
IFace *getInterface(const char *name) {
|
| 53 |
|
|
return core_.getInterface(name);
|
| 54 |
|
|
}
|
| 55 |
|
|
|
| 56 |
|
|
|
| 57 |
|
|
extern "C" int RISCV_init() {
|
| 58 |
|
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
| 59 |
|
|
WSADATA wsaData;
|
| 60 |
|
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
|
| 61 |
|
|
RISCV_error("Can't initialize sockets library", NULL);
|
| 62 |
|
|
}
|
| 63 |
|
|
#endif
|
| 64 |
|
|
|
| 65 |
|
|
_load_plugins(&listPlugins_);
|
| 66 |
|
|
return 0;
|
| 67 |
|
|
}
|
| 68 |
|
|
|
| 69 |
|
|
extern "C" void RISCV_cleanup() {
|
| 70 |
|
|
IClass *icls;
|
| 71 |
|
|
|
| 72 |
|
|
// Pre-deletion
|
| 73 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 74 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 75 |
|
|
icls->predeleteServices();
|
| 76 |
|
|
}
|
| 77 |
|
|
|
| 78 |
|
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
| 79 |
|
|
WSACleanup();
|
| 80 |
|
|
#endif
|
| 81 |
|
|
|
| 82 |
|
|
_unload_plugins(&listPlugins_);
|
| 83 |
|
|
RISCV_mutex_lock(&mutex_printf);
|
| 84 |
|
|
RISCV_mutex_destroy(&mutex_printf);
|
| 85 |
|
|
RISCV_mutex_lock(&mutexDefaultConsoles_);
|
| 86 |
|
|
RISCV_mutex_destroy(&mutexDefaultConsoles_);
|
| 87 |
|
|
RISCV_disable_log();
|
| 88 |
|
|
}
|
| 89 |
|
|
|
| 90 |
|
|
extern "C" int RISCV_set_configuration(AttributeType *cfg) {
|
| 91 |
|
|
IClass *icls;
|
| 92 |
|
|
IService *iserv;
|
| 93 |
|
|
|
| 94 |
|
|
Config_.clone(cfg);
|
| 95 |
|
|
if (!Config_.is_dict()) {
|
| 96 |
|
|
RISCV_error("Wrong configuration.", NULL);
|
| 97 |
|
|
return -1;
|
| 98 |
|
|
}
|
| 99 |
|
|
|
| 100 |
|
|
AttributeType &Services = Config_["Services"];
|
| 101 |
|
|
if (Services.is_list()) {
|
| 102 |
|
|
for (unsigned i = 0; i < Services.size(); i++) {
|
| 103 |
|
|
icls = static_cast<IClass *>(
|
| 104 |
|
|
RISCV_get_class(Services[i]["Class"].to_string()));
|
| 105 |
|
|
if (icls == NULL) {
|
| 106 |
|
|
RISCV_error("Class %s not found",
|
| 107 |
|
|
Services[i]["Class"].to_string());
|
| 108 |
|
|
return -1;
|
| 109 |
|
|
}
|
| 110 |
|
|
/** Special global setting for the GUI class: */
|
| 111 |
|
|
if (strcmp(icls->getClassName(), "GuiPluginClass") == 0) {
|
| 112 |
|
|
if (!Config_["GlobalSettings"]["GUI"].to_bool()) {
|
| 113 |
|
|
RISCV_info("%s", "GUI disabled");
|
| 114 |
|
|
continue;
|
| 115 |
|
|
}
|
| 116 |
|
|
}
|
| 117 |
|
|
|
| 118 |
|
|
AttributeType &Instances = Services[i]["Instances"];
|
| 119 |
|
|
for (unsigned n = 0; n < Instances.size(); n++) {
|
| 120 |
|
|
iserv = icls->createService(Instances[n]["Name"].to_string());
|
| 121 |
|
|
iserv->initService(&Instances[n]["Attr"]);
|
| 122 |
|
|
}
|
| 123 |
|
|
}
|
| 124 |
|
|
}
|
| 125 |
|
|
|
| 126 |
|
|
// Post initialization
|
| 127 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 128 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 129 |
|
|
icls->postinitServices();
|
| 130 |
|
|
}
|
| 131 |
|
|
|
| 132 |
|
|
RISCV_printf(getInterface(IFACE_SERVICE), 0, "%s",
|
| 133 |
|
|
"\n**********************************************************\n"
|
| 134 |
|
|
" RISC-V debugger\n"
|
| 135 |
|
|
" Author: Sergey Khabarov - sergeykhbr@gmail.com\n"
|
| 136 |
|
|
" Copyright 2016 GNSS Sensor Ltd. All right reserved.\n"
|
| 137 |
|
|
"**********************************************************");
|
| 138 |
|
|
|
| 139 |
|
|
IHap *ihap;
|
| 140 |
|
|
for (unsigned i = 0; i < listHap_.size(); i++) {
|
| 141 |
|
|
ihap = static_cast<IHap *>(listHap_[i].to_iface());
|
| 142 |
|
|
if (ihap->getType() == HAP_ConfigDone) {
|
| 143 |
|
|
ihap->hapTriggered(getInterface(IFACE_SERVICE),
|
| 144 |
|
|
HAP_ConfigDone, "Initial config done");
|
| 145 |
|
|
}
|
| 146 |
|
|
}
|
| 147 |
|
|
return 0;
|
| 148 |
|
|
}
|
| 149 |
|
|
|
| 150 |
|
|
extern "C" const char *RISCV_get_configuration() {
|
| 151 |
|
|
IClass *icls;
|
| 152 |
|
|
AttributeType ret(Attr_Dict);
|
| 153 |
|
|
ret["GlobalSettings"] = Config_["GlobalSettings"];
|
| 154 |
|
|
ret["Services"].make_list(0);
|
| 155 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 156 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 157 |
|
|
AttributeType val = icls->getConfiguration();
|
| 158 |
|
|
ret["Services"].add_to_list(&val);
|
| 159 |
|
|
}
|
| 160 |
|
|
return ret.to_config();
|
| 161 |
|
|
}
|
| 162 |
|
|
|
| 163 |
|
|
extern "C" const AttributeType *RISCV_get_global_settings() {
|
| 164 |
|
|
return &Config_["GlobalSettings"];
|
| 165 |
|
|
}
|
| 166 |
|
|
|
| 167 |
|
|
extern "C" void RISCV_register_class(IFace *icls) {
|
| 168 |
|
|
AttributeType item(icls);
|
| 169 |
|
|
listClasses_.add_to_list(&item);
|
| 170 |
|
|
}
|
| 171 |
|
|
|
| 172 |
|
|
extern "C" void RISCV_register_hap(IFace *ihap) {
|
| 173 |
|
|
AttributeType item(ihap);
|
| 174 |
|
|
listHap_.add_to_list(&item);
|
| 175 |
|
|
}
|
| 176 |
|
|
|
| 177 |
|
|
extern "C" void RISCV_trigger_hap(IFace *isrc, int type,
|
| 178 |
|
|
const char *descr) {
|
| 179 |
|
|
IHap *ihap;
|
| 180 |
|
|
EHapType etype = static_cast<EHapType>(type);
|
| 181 |
|
|
for (unsigned i = 0; i < listHap_.size(); i++) {
|
| 182 |
|
|
ihap = static_cast<IHap *>(listHap_[i].to_iface());
|
| 183 |
|
|
if (ihap->getType() == etype) {
|
| 184 |
|
|
ihap->hapTriggered(isrc, etype, descr);
|
| 185 |
|
|
}
|
| 186 |
|
|
}
|
| 187 |
|
|
}
|
| 188 |
|
|
|
| 189 |
|
|
|
| 190 |
|
|
extern "C" IFace *RISCV_get_class(const char *name) {
|
| 191 |
|
|
IClass *icls;
|
| 192 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 193 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 194 |
|
|
if (strcmp(name, icls->getClassName()) == 0) {
|
| 195 |
|
|
return icls;
|
| 196 |
|
|
}
|
| 197 |
|
|
}
|
| 198 |
|
|
return NULL;
|
| 199 |
|
|
}
|
| 200 |
|
|
|
| 201 |
|
|
extern "C" IFace *RISCV_create_service(IFace *iclass, const char *name,
|
| 202 |
|
|
AttributeType *args) {
|
| 203 |
|
|
IClass *icls = static_cast<IClass *>(iclass);
|
| 204 |
|
|
IService *iobj = icls->createService(name);
|
| 205 |
|
|
iobj->initService(args);
|
| 206 |
|
|
iobj->postinitService();
|
| 207 |
|
|
return iobj;
|
| 208 |
|
|
}
|
| 209 |
|
|
|
| 210 |
|
|
extern "C" IFace *RISCV_get_service(const char *name) {
|
| 211 |
|
|
IClass *icls;
|
| 212 |
|
|
IService *iserv;
|
| 213 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 214 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 215 |
|
|
if ((iserv = icls->getInstance(name)) != NULL) {
|
| 216 |
|
|
return iserv;
|
| 217 |
|
|
}
|
| 218 |
|
|
}
|
| 219 |
|
|
return NULL;
|
| 220 |
|
|
}
|
| 221 |
|
|
|
| 222 |
|
|
extern "C" IFace *RISCV_get_service_iface(const char *servname,
|
| 223 |
|
|
const char *facename) {
|
| 224 |
|
|
IService *iserv = static_cast<IService *>(RISCV_get_service(servname));
|
| 225 |
|
|
if (iserv == NULL) {
|
| 226 |
|
|
RISCV_error("Service '%s' not found.", servname);
|
| 227 |
|
|
return NULL;
|
| 228 |
|
|
}
|
| 229 |
|
|
return iserv->getInterface(facename);
|
| 230 |
|
|
}
|
| 231 |
|
|
|
| 232 |
|
|
extern "C" void RISCV_get_services_with_iface(const char *iname,
|
| 233 |
|
|
AttributeType *list) {
|
| 234 |
|
|
IClass *icls;
|
| 235 |
|
|
IService *iserv;
|
| 236 |
|
|
IFace *iface;
|
| 237 |
|
|
const AttributeType *tlist;
|
| 238 |
|
|
list->make_list(0);
|
| 239 |
|
|
|
| 240 |
|
|
for (unsigned i = 0; i < listClasses_.size(); i++) {
|
| 241 |
|
|
icls = static_cast<IClass *>(listClasses_[i].to_iface());
|
| 242 |
|
|
tlist = icls->getInstanceList();
|
| 243 |
|
|
if (tlist->size()) {
|
| 244 |
|
|
iserv = static_cast<IService *>((*tlist)[0u].to_iface());
|
| 245 |
|
|
iface = iserv->getInterface(iname);
|
| 246 |
|
|
if (iface) {
|
| 247 |
|
|
AttributeType t1(iserv);
|
| 248 |
|
|
list->add_to_list(&t1);
|
| 249 |
|
|
}
|
| 250 |
|
|
}
|
| 251 |
|
|
}
|
| 252 |
|
|
}
|
| 253 |
|
|
|
| 254 |
|
|
extern "C" void RISCV_get_clock_services(AttributeType *list) {
|
| 255 |
|
|
IService *iserv;
|
| 256 |
|
|
RISCV_get_services_with_iface(IFACE_CLOCK, list);
|
| 257 |
|
|
for (unsigned i = 0; i < list->size(); i++) {
|
| 258 |
|
|
iserv = static_cast<IService *>((*list)[i].to_iface());
|
| 259 |
|
|
(*list)[i].make_iface(iserv->getInterface(IFACE_CLOCK));
|
| 260 |
|
|
}
|
| 261 |
|
|
}
|
| 262 |
|
|
|
| 263 |
|
|
static thread_return_t safe_exit_thread(void *args) {
|
| 264 |
|
|
AttributeType t1, t2;
|
| 265 |
|
|
IService *iserv;
|
| 266 |
|
|
IThread *ith;
|
| 267 |
|
|
RISCV_get_services_with_iface(IFACE_THREAD, &t1);
|
| 268 |
|
|
|
| 269 |
|
|
for (unsigned i = 0; i < t1.size(); i++) {
|
| 270 |
|
|
iserv = static_cast<IService *>(t1[i].to_iface());
|
| 271 |
|
|
ith = static_cast<IThread *>(iserv->getInterface(IFACE_THREAD));
|
| 272 |
|
|
printf("Stopping thread service '%s'. . .", iserv->getObjName());
|
| 273 |
|
|
ith->stop();
|
| 274 |
|
|
printf("Stopped\n");
|
| 275 |
|
|
}
|
| 276 |
|
|
|
| 277 |
|
|
RISCV_trigger_hap(getInterface(IFACE_SERVICE),
|
| 278 |
|
|
HAP_BreakSimulation, "Exiting");
|
| 279 |
|
|
printf("All threads were stopped!\n");
|
| 280 |
|
|
core_.shutdown();
|
| 281 |
|
|
return 0;
|
| 282 |
|
|
}
|
| 283 |
|
|
|
| 284 |
|
|
extern "C" void RISCV_break_simulation() {
|
| 285 |
|
|
if (core_.isExiting()) {
|
| 286 |
|
|
return;
|
| 287 |
|
|
}
|
| 288 |
|
|
core_.setExiting();
|
| 289 |
|
|
LibThreadType data;
|
| 290 |
|
|
data.func = reinterpret_cast<lib_thread_func>(safe_exit_thread);
|
| 291 |
|
|
data.args = 0;
|
| 292 |
|
|
RISCV_thread_create(&data);
|
| 293 |
|
|
}
|
| 294 |
|
|
|
| 295 |
|
|
extern "C" int RISCV_is_active() {
|
| 296 |
|
|
return core_.isActive();
|
| 297 |
|
|
}
|
| 298 |
|
|
|
| 299 |
|
|
} // namespace debugger
|