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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [remote/] [tcpcmd.cpp] - Rev 5

Compare with Previous | Blame | View Log

/**
 * @file
 * @copyright  Copyright 2017 GNSS Sensor Ltd. All right reserved.
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
 * @brief      TCP commands parser/processor.
 */
 
#include "tcpcmd.h"
 
namespace debugger {
 
TcpCommands::TcpCommands(IService *parent) : IHap(HAP_All) {
    parent_ = parent;
    rxcnt_ = 0;
 
    cpu_.make_string("core0");
    executor_.make_string("cmdexec0");
    source_.make_string("src0");
 
    iexec_ = static_cast<ICmdExecutor *>(
        RISCV_get_service_iface(executor_.to_string(), IFACE_CMD_EXECUTOR));
 
    iclk_ = static_cast<IClock *>(
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CLOCK));
    IService *iservcpu = static_cast<IService *>(
                        RISCV_get_service(cpu_.to_string()));
    cpuLogLevel_ = static_cast<AttributeType *>(
                        iservcpu->getAttribute("LogLevel"));
 
    iriscv_ = static_cast<ICpuRiscV *>(
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_RISCV));
 
    isrc_ = static_cast<ISourceCode *>(
        RISCV_get_service_iface(source_.to_string(), IFACE_SOURCE_CODE));
 
    char tstr[128];
    RISCV_sprintf(tstr, sizeof(tstr), "%s_halt", parent_->getObjName());
    RISCV_event_create(&eventHalt_, tstr);
    RISCV_sprintf(tstr, sizeof(tstr), "%s_delay_ms", parent_->getObjName());
    RISCV_event_create(&eventDelayMs_, tstr);
    RISCV_sprintf(tstr, sizeof(tstr), "%s_pwr", parent_->getObjName());
    RISCV_event_create(&eventPowerChanged_, tstr);
 
    RISCV_register_hap(static_cast<IHap *>(this));
}
 
TcpCommands::~TcpCommands() {
    RISCV_event_close(&eventHalt_);
    RISCV_event_close(&eventDelayMs_);
    RISCV_event_close(&eventPowerChanged_);
}
 
void TcpCommands::hapTriggered(IFace *isrc, EHapType type,
                                const char *descr) {
    if (type == HAP_Halt) {
        RISCV_event_set(&eventHalt_);
    } else if (type == HAP_CpuTurnON || type == HAP_CpuTurnOFF) {
        RISCV_event_set(&eventPowerChanged_);
    }
}
 
void TcpCommands::stepCallback(uint64_t t) {
    RISCV_event_set(&eventDelayMs_);
}
 
void TcpCommands::updateData(const char *buf, int buflen) {
    for (int i = 0; i < buflen; i++) {
        rxbuf_[rxcnt_++] = buf[i];
        if (buf[i] == 0) {
            processCommand();
            rxcnt_ = 0;
        }
    }
}
 
void TcpCommands::processCommand() {
    AttributeType cmd;
    cmd.from_config(rxbuf_);
    if (!cmd.is_list() || cmd.size() < 3) {
        return;
    }
 
    uint64_t idx = cmd[0u].to_uint64();
    resp_.make_list(2);
    resp_[0u].make_uint64(idx);
    resp_[1].make_string("OK");
 
    AttributeType &requestType = cmd[1];
    AttributeType &requestAction = cmd[2];
    AttributeType *resp = &resp_[1];
 
    if (requestType.is_equal("Command")) {
        /** Redirect command to console directly */
        iexec_->exec(requestAction.to_string(), resp, false);
    } else if (requestType.is_equal("Breakpoint")) {
        /** Breakpoints action */
        if (requestAction[0u].is_equal("Add")) {
            br_add(requestAction[1], resp);
        } else if (requestAction[0u].is_equal("Remove")) {
            br_rm(requestAction[1], resp);
        } else {
            resp->make_string("Wrong breakpoint command");
        }
    } else if (requestType.is_equal("Control")) {
        /** Run Control action */
        if (requestAction[0u].is_equal("GoUntil")) {
            go_until(requestAction[1], resp);
        } else if (requestAction[0u].is_equal("GoMsec")) {
            go_msec(requestAction[1], resp);
        } else if (requestAction[0u].is_equal("Step")) {
            step(requestAction[1].to_int(), resp);
        } else if (requestAction[0u].is_equal("PowerOn")) {
            power_on(resp);
            RISCV_debug("[%" RV_PRI64 "d] Command Power-On", idx);
        } else if (requestAction[0u].is_equal("PowerOff")) {
            power_off(resp);
            RISCV_debug("[%" RV_PRI64 "d] Command Power-Off", idx);
        } else {
            resp->make_string("Wrong control command");
        }
    } else if (requestType.is_equal("Status")) {
        /** Pump status */
        if (requestAction.is_equal("IsON")) {
            resp->make_boolean(true);
        } else if (requestAction.is_equal("IsHalt")) {
            //resp->make_boolean(iriscv_->isHalt());
        } else if (requestAction.is_equal("Steps")) {
            resp->make_uint64(iclk_->getStepCounter());
        } else if (requestAction.is_equal("TimeSec")) {
            double t1 = iclk_->getStepCounter() / iclk_->getFreqHz();
            resp->make_floating(t1);
        } else {
            resp->make_string("Wrong status command");
        }
    } else if (requestType.is_equal("Symbol")) {
        /** Symbols table conversion */
        if (requestAction[0u].is_equal("ToAddr")) {
            symb2addr(requestAction[1].to_string(), resp);
        } else if (requestAction[0u].is_equal("FromAddr")) {
            // todo:
        } else {
            resp->make_string("Wrong symbol command");
        }
    } else if (requestType.is_equal("Attribute")) {
        IService *isrv = static_cast<IService *>(
                        RISCV_get_service(requestAction[0u].to_string()));
        if (isrv) {
            AttributeType *iatr = static_cast<AttributeType *>(
                        isrv->getAttribute(requestAction[1].to_string()));
            if (iatr) {
                resp->clone(iatr);
            } else {
                resp->make_string("Attribute not found");
            }
        } else {
            resp->make_string("Service not found");
        }
    } else {
        resp->make_list(2);
        (*resp)[0u].make_string("ERROR");
        (*resp)[1].make_string("Wrong command format");
    }
    resp_.to_config();
}
 
AttributeType *TcpCommands::response() {
    return &resp_;
}
 
void TcpCommands::br_add(const AttributeType &symb, AttributeType *res) {
    uint64_t addr;
    if (symb.is_string()) {
        AttributeType t1;
        symb2addr(symb.to_string(), &t1);
        if (t1.is_nil()) {
            res->make_string("br_add: Symbol not found");
            return;
        }
        addr = t1.to_uint64();
    } else if (symb.is_integer()) {
        addr = symb.to_uint64();
    } else {
        res->make_string("br_add: Wrong format");
        return;
    }
    char tstr[256];
    RISCV_sprintf(tstr, sizeof(tstr), "br add 0x%x", addr);
    iexec_->exec(tstr, res, false);
}
 
void TcpCommands::br_rm(const AttributeType &symb, AttributeType *res) {
    uint64_t addr;
    if (symb.is_string()) {
        AttributeType t1;
        symb2addr(symb.to_string(), &t1);
        if (t1.is_nil()) {
            res->make_string("br_rm: Symbol not found");
            return;
        }
        addr = t1.to_uint64();
    } else if (symb.is_integer()) {
        addr = symb.to_uint64();
    } else {
        res->make_string("br_rm: Wrong format");
        return;
    }
    char tstr[256];
    RISCV_sprintf(tstr, sizeof(tstr), "br rm 0x%x", addr);
    iexec_->exec(tstr, res, false);
}
 
void TcpCommands::step(int cnt, AttributeType *res) {
    char tstr[16];
    RISCV_sprintf(tstr, sizeof(tstr), "c %d", cnt);
 
    int log_level_old = cpuLogLevel_->to_int();
    cpuLogLevel_->make_int64(4);
 
    RISCV_event_clear(&eventHalt_);
    iexec_->exec(tstr, res, false);
    RISCV_event_wait(&eventHalt_);
    cpuLogLevel_->make_int64(log_level_old);
}
 
void TcpCommands::go_until(const AttributeType &symb, AttributeType *res) {
    uint64_t addr;
    if (symb.is_string()) {
        AttributeType t1;
        symb2addr(symb.to_string(), &t1);
        if (t1.is_nil()) {
            res->make_string("br_rm: Symbol not found");
            return;
        }
        addr = t1.to_uint64();
    } else if (symb.is_integer()) {
        addr = symb.to_uint64();
    } else {
        res->make_string("br_rm: Wrong format");
        return;
    }
    // Add breakpoint
    char tstr[256];
    RISCV_sprintf(tstr, sizeof(tstr), "br add 0x%x", addr);
    iexec_->exec(tstr, res, false);
 
    // Set CPU LogLevel=1 to hide all debugging messages
    int log_level_old = cpuLogLevel_->to_int();
    cpuLogLevel_->make_int64(1);
 
    // Run simulation
    RISCV_event_clear(&eventHalt_);
    RISCV_sprintf(tstr, sizeof(tstr), "c", 0);
    iexec_->exec(tstr, res, false);
    RISCV_event_wait(&eventHalt_);
    cpuLogLevel_->make_int64(log_level_old);
 
    // Remove breakpoint:
    RISCV_sprintf(tstr, sizeof(tstr), "br rm 0x%x", addr);
    iexec_->exec(tstr, res, false);
}
 
void TcpCommands::symb2addr(const char *symbol, AttributeType *res) {
    res->make_nil();
    if (!isrc_) {
        return;
    }
    // Letters capitalization:
    char capital[256];
    int i = 0;
    while (symbol[i]) {
        capital[i] = symbol[i];
        if (symbol[i] >= 'a' && symbol[i] <= 'z') {
            capital[i] += ('A' - 'a');
        }
        i++;
        capital[i] = '\0';
    }
    uint64_t addr;
    if (isrc_->symbol2Address(capital, &addr) == 0) {
        res->make_uint64(addr);
        return;
    }
}
 
void TcpCommands::power_on(AttributeType *res) {
}
 
void TcpCommands::power_off(AttributeType *res) {
}
 
void TcpCommands::go_msec(const AttributeType &msec, AttributeType *res) {
    RISCV_event_clear(&eventDelayMs_);
    RISCV_event_clear(&eventHalt_);
 
    uint64_t step = iclk_->getStepCounter();
    double delta = 0.001 * iclk_->getFreqHz() * msec.to_float();
    if (delta == 0) {
        delta = 1;
    }
    iclk_->registerStepCallback(static_cast<IClockListener *>(this),
                                step + static_cast<uint64_t>(delta));
 
    iexec_->exec("c", res, false);
    RISCV_event_wait(&eventDelayMs_);
    iexec_->exec("s", res, false);
    RISCV_event_wait(&eventHalt_);
}
 
 
}  // namespace debugger
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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