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

Subversion Repositories riscv_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /riscv_vhdl/trunk/debugger/src/libdbg64g/services/exec
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/cmd/cmd_br.cpp
1,90 → 1,90
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Add or remove memory breakpoint.
*/
 
#include "cmd_br.h"
 
namespace debugger {
 
CmdBr::CmdBr(ITap *tap, ISocInfo *info)
: ICommand ("br", tap, info) {
 
briefDescr_.make_string("Add or remove breakpoint.");
detailedDescr_.make_string(
"Description:\n"
" Get breakpoints list or add/remove breakpoint with specified\n"
" flags.\n"
"Response:\n"
" List of lists [[iii]*] if breakpoint list was requested, where:\n"
" i - uint64_t address value\n"
" i - uint32_t instruction value\n"
" i - uint64_t Breakpoint flags: hardware,...\n"
" Nil in a case of add/rm breakpoint\n"
"Usage:\n"
" br"
" br add <addr>\n"
" br rm <addr>\n"
" br add <addr> hw\n"
"Example:\n"
" br add 0x10000000\n"
" br add 0x00020040 hw\n"
" br rm 0x10000000\n");
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
isrc_ = 0;
if (lstServ.size() != 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
isrc_ = static_cast<ISourceCode *>(
iserv->getInterface(IFACE_SOURCE_CODE));
}
}
 
bool CmdBr::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 1 || (args->size() >= 3 && (*args)[1].is_string()))
) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdBr::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isrc_ || !isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
if (args->size() == 1) {
isrc_->getBreakpointList(res);
return;
}
 
uint64_t flags = 0;
if (args->size() == 4 && (*args)[3].is_equal("hw")) {
flags |= BreakFlag_HW;
}
 
Reg64Type instr;
uint64_t addr = (*args)[2].to_uint64();
tap_->read(addr, 4, instr.buf);
isrc_->registerBreakpoint(addr, instr.buf32[0], flags);
 
instr.buf32[0] = 0x00100073; // EBREAK instruction
 
if ((*args)[1].is_equal("add")) {
tap_->write(addr, 4, instr.buf);
return;
}
if ((*args)[1].is_equal("rm")) {
if (!isrc_->unregisterBreakpoint(addr, instr.buf32, &flags)) {
tap_->write(addr, 4, instr.buf);
}
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Add or remove memory breakpoint.
*/
 
#include "cmd_br.h"
 
namespace debugger {
 
CmdBr::CmdBr(ITap *tap, ISocInfo *info)
: ICommand ("br", tap, info) {
 
briefDescr_.make_string("Add or remove breakpoint.");
detailedDescr_.make_string(
"Description:\n"
" Get breakpoints list or add/remove breakpoint with specified\n"
" flags.\n"
"Response:\n"
" List of lists [[iii]*] if breakpoint list was requested, where:\n"
" i - uint64_t address value\n"
" i - uint32_t instruction value\n"
" i - uint64_t Breakpoint flags: hardware,...\n"
" Nil in a case of add/rm breakpoint\n"
"Usage:\n"
" br"
" br add <addr>\n"
" br rm <addr>\n"
" br add <addr> hw\n"
"Example:\n"
" br add 0x10000000\n"
" br add 0x00020040 hw\n"
" br rm 0x10000000\n");
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
isrc_ = 0;
if (lstServ.size() != 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
isrc_ = static_cast<ISourceCode *>(
iserv->getInterface(IFACE_SOURCE_CODE));
}
}
 
bool CmdBr::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 1 || (args->size() >= 3 && (*args)[1].is_string()))
) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdBr::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isrc_ || !isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
if (args->size() == 1) {
isrc_->getBreakpointList(res);
return;
}
 
uint64_t flags = 0;
if (args->size() == 4 && (*args)[3].is_equal("hw")) {
flags |= BreakFlag_HW;
}
 
Reg64Type instr;
uint64_t addr = (*args)[2].to_uint64();
tap_->read(addr, 4, instr.buf);
isrc_->registerBreakpoint(addr, instr.buf32[0], flags);
 
instr.buf32[0] = 0x00100073; // EBREAK instruction
 
if ((*args)[1].is_equal("add")) {
tap_->write(addr, 4, instr.buf);
return;
}
if ((*args)[1].is_equal("rm")) {
if (!isrc_->unregisterBreakpoint(addr, instr.buf32, &flags)) {
tap_->write(addr, 4, instr.buf);
}
}
}
 
} // namespace debugger
/cmd/cmd_br.h
1,34 → 1,34
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Add or remove memory breakpoint.
*/
 
#ifndef __DEBUGGER_CMD_BR_H__
#define __DEBUGGER_CMD_BR_H__
 
#include "api_core.h"
#include "iservice.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include "coreservices/isrccode.h"
 
namespace debugger {
 
class CmdBr : public ICommand {
public:
explicit CmdBr(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
ISourceCode *isrc_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOG_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Add or remove memory breakpoint.
*/
 
#ifndef __DEBUGGER_CMD_BR_H__
#define __DEBUGGER_CMD_BR_H__
 
#include "api_core.h"
#include "iservice.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include "coreservices/isrccode.h"
 
namespace debugger {
 
class CmdBr : public ICommand {
public:
explicit CmdBr(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
ISourceCode *isrc_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOG_H__
/cmd/cmd_busutil.cpp
1,90 → 1,90
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Bus utilization computation
*
* @details Read CPU dport registers: clock counter and per
* master counters with read/write transactions to compute
* utilization characteristic.
*/
 
#include "cmd_busutil.h"
 
namespace debugger {
 
CmdBusUtil::CmdBusUtil(ITap *tap, ISocInfo *info)
: ICommand ("busutil", tap, info) {
 
briefDescr_.make_string("Compute Clocks Per Instruction (CPI) rate");
detailedDescr_.make_string(
"Description:\n"
" Read and normalize per master bus utilization statistic\n"
" using information about total number of clocks and counters\n"
" of clocks spending on read/write transactions.\n"
"Warning:\n"
" For functional simulation accumulated utilization may exceed\n"
" 100.0 percentage of bus because all masters can request data\n"
" at the same step without arbiter implementation.\n"
"Output format:\n"
" [[d,d]*]\n"
" d - Write access for master[0] in range 0 to 100.\n"
" d - Read access for master[0] in range 0 to 100.\n"
" * - For each master.\n"
"Example:\n"
" busutil\n");
 
clock_cnt_z_ = 0;
memset(bus_util_z_, 0, sizeof(bus_util_z_));
}
 
bool CmdBusUtil::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdBusUtil::exec(AttributeType *args, AttributeType *res) {
unsigned mst_total = info_->getMastersTotal();
res->make_list(mst_total);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
struct MasterStatType {
Reg64Type w_cnt;
Reg64Type r_cnt;
} mst_stat;
Reg64Type cnt_total;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->udbg.v.clock_cnt);
tap_->read(addr, 8, cnt_total.buf);
double d_cnt_total = static_cast<double>(cnt_total.val - clock_cnt_z_);
if (d_cnt_total == 0) {
return;
}
 
addr = reinterpret_cast<uint64_t>(dsu->ulocal.v.bus_util);
for (unsigned i = 0; i < mst_total; i++) {
AttributeType &mst = (*res)[i];
if (!mst.is_list() || mst.size() != 2) {
mst.make_list(2);
}
tap_->read(addr, 16, mst_stat.w_cnt.buf);
mst[0u].make_floating(100.0 *
static_cast<double>(mst_stat.w_cnt.val - bus_util_z_[i].w_cnt)
/ d_cnt_total);
mst[1].make_floating(100.0 *
static_cast<double>(mst_stat.r_cnt.val - bus_util_z_[i].r_cnt)
/ d_cnt_total);
 
bus_util_z_[i].w_cnt = mst_stat.w_cnt.val;
bus_util_z_[i].r_cnt = mst_stat.r_cnt.val;
addr += 16;
}
clock_cnt_z_ = cnt_total.val;
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Bus utilization computation
*
* @details Read CPU dport registers: clock counter and per
* master counters with read/write transactions to compute
* utilization characteristic.
*/
 
#include "cmd_busutil.h"
 
namespace debugger {
 
CmdBusUtil::CmdBusUtil(ITap *tap, ISocInfo *info)
: ICommand ("busutil", tap, info) {
 
briefDescr_.make_string("Compute Clocks Per Instruction (CPI) rate");
detailedDescr_.make_string(
"Description:\n"
" Read and normalize per master bus utilization statistic\n"
" using information about total number of clocks and counters\n"
" of clocks spending on read/write transactions.\n"
"Warning:\n"
" For functional simulation accumulated utilization may exceed\n"
" 100.0 percentage of bus because all masters can request data\n"
" at the same step without arbiter implementation.\n"
"Output format:\n"
" [[d,d]*]\n"
" d - Write access for master[0] in range 0 to 100.\n"
" d - Read access for master[0] in range 0 to 100.\n"
" * - For each master.\n"
"Example:\n"
" busutil\n");
 
clock_cnt_z_ = 0;
memset(bus_util_z_, 0, sizeof(bus_util_z_));
}
 
bool CmdBusUtil::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdBusUtil::exec(AttributeType *args, AttributeType *res) {
unsigned mst_total = info_->getMastersTotal();
res->make_list(mst_total);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
struct MasterStatType {
Reg64Type w_cnt;
Reg64Type r_cnt;
} mst_stat;
Reg64Type cnt_total;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->udbg.v.clock_cnt);
tap_->read(addr, 8, cnt_total.buf);
double d_cnt_total = static_cast<double>(cnt_total.val - clock_cnt_z_);
if (d_cnt_total == 0) {
return;
}
 
addr = reinterpret_cast<uint64_t>(dsu->ulocal.v.bus_util);
for (unsigned i = 0; i < mst_total; i++) {
AttributeType &mst = (*res)[i];
if (!mst.is_list() || mst.size() != 2) {
mst.make_list(2);
}
tap_->read(addr, 16, mst_stat.w_cnt.buf);
mst[0u].make_floating(100.0 *
static_cast<double>(mst_stat.w_cnt.val - bus_util_z_[i].w_cnt)
/ d_cnt_total);
mst[1].make_floating(100.0 *
static_cast<double>(mst_stat.r_cnt.val - bus_util_z_[i].r_cnt)
/ d_cnt_total);
 
bus_util_z_[i].w_cnt = mst_stat.w_cnt.val;
bus_util_z_[i].r_cnt = mst_stat.r_cnt.val;
addr += 16;
}
clock_cnt_z_ = cnt_total.val;
}
 
} // namespace debugger
/cmd/cmd_busutil.h
1,38 → 1,38
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Bus utilization computation
*
* @details Read CPU dport registers: clock counter and per
* master counters with read/write transactions to compute
* utilization characteristic.
*/
 
#ifndef __DEBUGGER_CMD_BUSUTIL_H__
#define __DEBUGGER_CMD_BUSUTIL_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdBusUtil : public ICommand {
public:
explicit CmdBusUtil(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
uint64_t clock_cnt_z_;
DsuMapType::local_regs_type::local_region_type::mst_bus_util_type
bus_util_z_[32];
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_BUSUTIL_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Bus utilization computation
*
* @details Read CPU dport registers: clock counter and per
* master counters with read/write transactions to compute
* utilization characteristic.
*/
 
#ifndef __DEBUGGER_CMD_BUSUTIL_H__
#define __DEBUGGER_CMD_BUSUTIL_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdBusUtil : public ICommand {
public:
explicit CmdBusUtil(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
uint64_t clock_cnt_z_;
DsuMapType::local_regs_type::local_region_type::mst_bus_util_type
bus_util_z_[32];
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_BUSUTIL_H__
/cmd/cmd_cpi.cpp
1,87 → 1,87
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU dport registers (step counter and clock
* counter) to compute CPI in run-time.
*/
 
#include "cmd_cpi.h"
 
namespace debugger {
 
CmdCpi::CmdCpi(ITap *tap, ISocInfo *info)
: ICommand ("cpi", tap, info) {
 
briefDescr_.make_string("Compute Clocks Per Instruction (CPI) rate");
detailedDescr_.make_string(
"Description:\n"
" This commands reads CPU registers: 'clock counter' and.\n"
" 'step counter' and computes Clocks Per Instruction (CPI) rate\n"
" in run-time.\n"
"Output format:\n"
" [i,i,i,i,d]\n"
" i - Current CPU clock counter value (int64_t).\n"
" i - Current CPU step counter value (int64_t).\n"
" i - (Current - Previous) CPU clock counter value (int64_t).\n"
" i - (Current - Previous) CPU step counter value (int64_t).\n"
" d - CPI rate (double) = (delta clocks)/(delta steps).\n"
"Example:\n"
" cpi\n");
 
stepCnt_z = 0;
clockCnt_z = 0;
}
 
bool CmdCpi::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdCpi::exec(AttributeType *args, AttributeType *res) {
res->make_list(5);
(*res)[0u].make_uint64(0);
(*res)[1].make_uint64(0);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
struct CpiRegsType {
Reg64Type clock_cnt;
Reg64Type executed_cnt;
};
union CpiRegionType {
CpiRegsType regs;
uint8_t buf[sizeof(CpiRegsType)];
} t1;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->udbg.v.clock_cnt);
uint64_t d1, d2;
tap_->read(addr, 16, t1.buf);
 
d1 = t1.regs.clock_cnt.val - clockCnt_z;
d2 = t1.regs.executed_cnt.val - stepCnt_z;
 
(*res)[0u].make_uint64(t1.regs.clock_cnt.val);
(*res)[1].make_uint64(t1.regs.executed_cnt.val);
(*res)[2].make_uint64(d1);
(*res)[3].make_uint64(d2);
if (d2 == 0) {
if (t1.regs.executed_cnt.val == 0) {
(*res)[4].make_floating(0);
} else {
(*res)[4].make_floating(1.0);
}
} else {
(*res)[4].make_floating(
static_cast<double>(d1) / static_cast<double>(d2));
}
 
clockCnt_z = t1.regs.clock_cnt.val;
stepCnt_z = t1.regs.executed_cnt.val;
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU dport registers (step counter and clock
* counter) to compute CPI in run-time.
*/
 
#include "cmd_cpi.h"
 
namespace debugger {
 
CmdCpi::CmdCpi(ITap *tap, ISocInfo *info)
: ICommand ("cpi", tap, info) {
 
briefDescr_.make_string("Compute Clocks Per Instruction (CPI) rate");
detailedDescr_.make_string(
"Description:\n"
" This commands reads CPU registers: 'clock counter' and.\n"
" 'step counter' and computes Clocks Per Instruction (CPI) rate\n"
" in run-time.\n"
"Output format:\n"
" [i,i,i,i,d]\n"
" i - Current CPU clock counter value (int64_t).\n"
" i - Current CPU step counter value (int64_t).\n"
" i - (Current - Previous) CPU clock counter value (int64_t).\n"
" i - (Current - Previous) CPU step counter value (int64_t).\n"
" d - CPI rate (double) = (delta clocks)/(delta steps).\n"
"Example:\n"
" cpi\n");
 
stepCnt_z = 0;
clockCnt_z = 0;
}
 
bool CmdCpi::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdCpi::exec(AttributeType *args, AttributeType *res) {
res->make_list(5);
(*res)[0u].make_uint64(0);
(*res)[1].make_uint64(0);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
struct CpiRegsType {
Reg64Type clock_cnt;
Reg64Type executed_cnt;
};
union CpiRegionType {
CpiRegsType regs;
uint8_t buf[sizeof(CpiRegsType)];
} t1;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->udbg.v.clock_cnt);
uint64_t d1, d2;
tap_->read(addr, 16, t1.buf);
 
d1 = t1.regs.clock_cnt.val - clockCnt_z;
d2 = t1.regs.executed_cnt.val - stepCnt_z;
 
(*res)[0u].make_uint64(t1.regs.clock_cnt.val);
(*res)[1].make_uint64(t1.regs.executed_cnt.val);
(*res)[2].make_uint64(d1);
(*res)[3].make_uint64(d2);
if (d2 == 0) {
if (t1.regs.executed_cnt.val == 0) {
(*res)[4].make_floating(0);
} else {
(*res)[4].make_floating(1.0);
}
} else {
(*res)[4].make_floating(
static_cast<double>(d1) / static_cast<double>(d2));
}
 
clockCnt_z = t1.regs.clock_cnt.val;
stepCnt_z = t1.regs.executed_cnt.val;
}
 
} // namespace debugger
/cmd/cmd_cpi.h
1,34 → 1,34
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU dport registers (step counter and clock
* counter) to compute CPI in run-time.
*/
 
#ifndef __DEBUGGER_CMD_CPI_H__
#define __DEBUGGER_CMD_CPI_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdCpi : public ICommand {
public:
explicit CmdCpi(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
uint64_t stepCnt_z;
uint64_t clockCnt_z;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_CPI_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU dport registers (step counter and clock
* counter) to compute CPI in run-time.
*/
 
#ifndef __DEBUGGER_CMD_CPI_H__
#define __DEBUGGER_CMD_CPI_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdCpi : public ICommand {
public:
explicit CmdCpi(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
uint64_t stepCnt_z;
uint64_t clockCnt_z;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_CPI_H__
/cmd/cmd_csr.cpp
1,122 → 1,122
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write CSR register value.
*/
 
#include "cmd_csr.h"
 
namespace debugger {
 
CmdCsr::CmdCsr(ITap *tap, ISocInfo *info)
: ICommand ("csr", tap, info) {
 
briefDescr_.make_string("Access to CSR registers");
detailedDescr_.make_string(
"Description:\n"
" Access to CSRs registers of the CPU.\n"
"Usage:\n"
" READ: csr <addr|name>\n"
" WRITE: csr <addr|name> <value>\n"
"Example:\n"
" csr MISA\n"
" csr 0xf10 1\n");
}
 
bool CmdCsr::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdCsr::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
AttributeType &arg1 = (*args)[1];
uint64_t val;
int bytes = 8;
uint64_t addr;
if (arg1.is_string()) {
const char *csrname = arg1.to_string();
addr = info_->csr2addr(csrname);
if (addr == REG_ADDR_ERROR) {
char tstr[128];
RISCV_sprintf(tstr, sizeof(tstr), "%s not found", csrname);
generateError(res, tstr);
return;
}
} else {
addr = arg1.to_uint64();
}
 
if (args->size() == 2) {
tap_->read(addr, bytes, reinterpret_cast<uint8_t *>(&val));
res->make_uint64(val);
} else {
val = (*args)[2].to_uint64();
tap_->write(addr, bytes, reinterpret_cast<uint8_t *>(&val));
}
}
 
void CmdCsr::to_string(AttributeType *args, AttributeType *res, AttributeType *out) {
if (args->size() != 2) {
out->make_nil();
return;
}
 
char tstr[256];
int tstrsz;
uint64_t csr = res->to_uint64();
uint64_t addr = info_->csr2addr((*args)[1].to_string());
 
tstr[0] = '\0';
if (addr == static_cast<uint64_t>(-1)) {
RISCV_sprintf(tstr, sizeof(tstr),
"Unknown CSR '%s'\n", (*args)[1].to_string());
out->make_string(tstr);
return;
}
 
tstrsz = RISCV_sprintf(tstr, sizeof(tstr),
"CSR[%03x] => %016" RV_PRI64 "x\n",
static_cast<uint32_t>((addr >> 4) & 0xfff), res->to_uint64());
if (!(*args)[1].is_string()) {
return;
}
if ((*args)[1].is_equal("MISA")) {
static const char *MISA_BASE[4] = {
"RV32I", "RV32E", "RV64I", "RV128I"
};
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
" Base: %s", MISA_BASE[(csr >> 62) & 0x3]);
// total 26 extensions
char extenstion[2] = {0};
for (int i = 0; i < 26; i++) {
if (csr & (1LL << i)) {
extenstion[0] = 'A' + i;
if (extenstion[0] == 'I') {
continue;
}
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
"%s", extenstion);
}
}
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz, "\n");
} else if ((*args)[1].is_equal("MTIME")) {
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
" Clock: %" RV_PRI64 "d; ms: %.1f\n",
csr, static_cast<double>(csr)/60000.0);
}
out->make_string(tstr);
return;
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write CSR register value.
*/
 
#include "cmd_csr.h"
 
namespace debugger {
 
CmdCsr::CmdCsr(ITap *tap, ISocInfo *info)
: ICommand ("csr", tap, info) {
 
briefDescr_.make_string("Access to CSR registers");
detailedDescr_.make_string(
"Description:\n"
" Access to CSRs registers of the CPU.\n"
"Usage:\n"
" READ: csr <addr|name>\n"
" WRITE: csr <addr|name> <value>\n"
"Example:\n"
" csr MISA\n"
" csr 0xf10 1\n");
}
 
bool CmdCsr::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdCsr::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
AttributeType &arg1 = (*args)[1];
uint64_t val;
int bytes = 8;
uint64_t addr;
if (arg1.is_string()) {
const char *csrname = arg1.to_string();
addr = info_->csr2addr(csrname);
if (addr == REG_ADDR_ERROR) {
char tstr[128];
RISCV_sprintf(tstr, sizeof(tstr), "%s not found", csrname);
generateError(res, tstr);
return;
}
} else {
addr = arg1.to_uint64();
}
 
if (args->size() == 2) {
tap_->read(addr, bytes, reinterpret_cast<uint8_t *>(&val));
res->make_uint64(val);
} else {
val = (*args)[2].to_uint64();
tap_->write(addr, bytes, reinterpret_cast<uint8_t *>(&val));
}
}
 
void CmdCsr::to_string(AttributeType *args, AttributeType *res, AttributeType *out) {
if (args->size() != 2) {
out->make_nil();
return;
}
 
char tstr[256];
int tstrsz;
uint64_t csr = res->to_uint64();
uint64_t addr = info_->csr2addr((*args)[1].to_string());
 
tstr[0] = '\0';
if (addr == static_cast<uint64_t>(-1)) {
RISCV_sprintf(tstr, sizeof(tstr),
"Unknown CSR '%s'\n", (*args)[1].to_string());
out->make_string(tstr);
return;
}
 
tstrsz = RISCV_sprintf(tstr, sizeof(tstr),
"CSR[%03x] => %016" RV_PRI64 "x\n",
static_cast<uint32_t>((addr >> 4) & 0xfff), res->to_uint64());
if (!(*args)[1].is_string()) {
return;
}
if ((*args)[1].is_equal("MISA")) {
static const char *MISA_BASE[4] = {
"RV32I", "RV32E", "RV64I", "RV128I"
};
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
" Base: %s", MISA_BASE[(csr >> 62) & 0x3]);
// total 26 extensions
char extenstion[2] = {0};
for (int i = 0; i < 26; i++) {
if (csr & (1LL << i)) {
extenstion[0] = 'A' + i;
if (extenstion[0] == 'I') {
continue;
}
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
"%s", extenstion);
}
}
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz, "\n");
} else if ((*args)[1].is_equal("MTIME")) {
tstrsz += RISCV_sprintf(&tstr[tstrsz], sizeof(tstr) - tstrsz,
" Clock: %" RV_PRI64 "d; ms: %.1f\n",
csr, static_cast<double>(csr)/60000.0);
}
out->make_string(tstr);
return;
}
 
} // namespace debugger
/cmd/cmd_csr.h
1,32 → 1,32
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write CSR register value.
*/
 
#ifndef __DEBUGGER_CMD_CSR_H__
#define __DEBUGGER_CMD_CSR_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdCsr : public ICommand {
public:
explicit CmdCsr(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void to_string(AttributeType *args, AttributeType *res, AttributeType *out);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_CSR_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write CSR register value.
*/
 
#ifndef __DEBUGGER_CMD_CSR_H__
#define __DEBUGGER_CMD_CSR_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdCsr : public ICommand {
public:
explicit CmdCsr(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void to_string(AttributeType *args, AttributeType *res, AttributeType *out);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_CSR_H__
/cmd/cmd_disas.cpp
1,108 → 1,108
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Disassemble data block command.
*/
 
#include <string>
#include "cmd_disas.h"
 
namespace debugger {
 
CmdDisas::CmdDisas(ITap *tap, ISocInfo *info)
: ICommand ("disas", tap, info) {
 
briefDescr_.make_string("Disassemble block of data.");
detailedDescr_.make_string(
"Description:\n"
" Disassemble memory range or a block of data. Convert result\n"
" to a list of assembler items where each of them has\n"
" ASM_Total sub-items. You can add 'str' flag to receive\n"
" formatted text output.\n"
"Usage:\n"
" disas <addr> <byte> [str]\n"
" disas <addr> <data> [str]\n"
"Example:\n"
" data 0x40000000 100\n"
" data 0x40000000 100 str\n"
" data 0x1000 (73,00,10,00)\n"
" ['data',0x1000,(73,00,10,00)]\n");
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
isrc_ = 0;
if (lstServ.size() != 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
isrc_ = static_cast<ISourceCode *>(
iserv->getInterface(IFACE_SOURCE_CODE));
}
}
 
bool CmdDisas::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& args->size() >= 3 && (*args)[1].is_integer()
&& ((*args)[2].is_data() || (*args)[2].is_integer())
) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdDisas::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isrc_ || !isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_list(0);
 
uint64_t addr = (*args)[1].to_uint64();
AttributeType *mem_data, *asm_data;
AttributeType membuf, asmbuf;
if ((*args)[2].is_integer()) {
// 4-bytes alignment
uint32_t sz = ((*args)[2].to_uint32() + 3) & ~0x3;
membuf.make_data(sz);
mem_data = &membuf;
if (tap_->read(addr, sz, membuf.data()) == TAP_ERROR) {
res->make_nil();
return;
}
} else {
mem_data = &(*args)[2];
}
 
asm_data = res;
bool do_format = false;
if (args->size() == 4 && (*args)[3].is_equal("str")) {
asm_data = &asmbuf;
do_format = true;
}
 
isrc_->disasm(addr, mem_data, asm_data);
 
if (do_format) {
format(asm_data, res);
}
}
 
void CmdDisas::format(AttributeType *asmbuf, AttributeType *fmtstr) {
char tstr[128];
std::string tout;
for (unsigned i = 0; i < asmbuf->size(); i++) {
const AttributeType &line = (*asmbuf)[i];
if (line[ASM_list_type].to_int() != AsmList_disasm) {
continue;
}
RISCV_sprintf(tstr, sizeof(tstr), "%016" RV_PRI64 "x: %08x %s\n",
line[ASM_addrline].to_uint64(),
line[ASM_code].to_uint32(),
line[ASM_mnemonic].to_string()
);
tout += tstr;
}
fmtstr->make_string(tout.c_str());
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Disassemble data block command.
*/
 
#include <string>
#include "cmd_disas.h"
 
namespace debugger {
 
CmdDisas::CmdDisas(ITap *tap, ISocInfo *info)
: ICommand ("disas", tap, info) {
 
briefDescr_.make_string("Disassemble block of data.");
detailedDescr_.make_string(
"Description:\n"
" Disassemble memory range or a block of data. Convert result\n"
" to a list of assembler items where each of them has\n"
" ASM_Total sub-items. You can add 'str' flag to receive\n"
" formatted text output.\n"
"Usage:\n"
" disas <addr> <byte> [str]\n"
" disas <addr> <data> [str]\n"
"Example:\n"
" data 0x40000000 100\n"
" data 0x40000000 100 str\n"
" data 0x1000 (73,00,10,00)\n"
" ['data',0x1000,(73,00,10,00)]\n");
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
isrc_ = 0;
if (lstServ.size() != 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
isrc_ = static_cast<ISourceCode *>(
iserv->getInterface(IFACE_SOURCE_CODE));
}
}
 
bool CmdDisas::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& args->size() >= 3 && (*args)[1].is_integer()
&& ((*args)[2].is_data() || (*args)[2].is_integer())
) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdDisas::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isrc_ || !isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_list(0);
 
uint64_t addr = (*args)[1].to_uint64();
AttributeType *mem_data, *asm_data;
AttributeType membuf, asmbuf;
if ((*args)[2].is_integer()) {
// 4-bytes alignment
uint32_t sz = ((*args)[2].to_uint32() + 3) & ~0x3;
membuf.make_data(sz);
mem_data = &membuf;
if (tap_->read(addr, sz, membuf.data()) == TAP_ERROR) {
res->make_nil();
return;
}
} else {
mem_data = &(*args)[2];
}
 
asm_data = res;
bool do_format = false;
if (args->size() == 4 && (*args)[3].is_equal("str")) {
asm_data = &asmbuf;
do_format = true;
}
 
isrc_->disasm(addr, mem_data, asm_data);
 
if (do_format) {
format(asm_data, res);
}
}
 
void CmdDisas::format(AttributeType *asmbuf, AttributeType *fmtstr) {
char tstr[128];
std::string tout;
for (unsigned i = 0; i < asmbuf->size(); i++) {
const AttributeType &line = (*asmbuf)[i];
if (line[ASM_list_type].to_int() != AsmList_disasm) {
continue;
}
RISCV_sprintf(tstr, sizeof(tstr), "%016" RV_PRI64 "x: %08x %s\n",
line[ASM_addrline].to_uint64(),
line[ASM_code].to_uint32(),
line[ASM_mnemonic].to_string()
);
tout += tstr;
}
fmtstr->make_string(tout.c_str());
}
 
} // namespace debugger
/cmd/cmd_disas.h
1,37 → 1,37
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Disassemble data block command.
*/
 
#ifndef __DEBUGGER_CMD_DISAS_H__
#define __DEBUGGER_CMD_DISAS_H__
 
#include "api_core.h"
#include "iservice.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include "coreservices/isrccode.h"
 
namespace debugger {
 
class CmdDisas : public ICommand {
public:
explicit CmdDisas(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void format(AttributeType *asmbuf, AttributeType *fmtstr);
 
private:
ISourceCode *isrc_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_DISAS_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Disassemble data block command.
*/
 
#ifndef __DEBUGGER_CMD_DISAS_H__
#define __DEBUGGER_CMD_DISAS_H__
 
#include "api_core.h"
#include "iservice.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include "coreservices/isrccode.h"
 
namespace debugger {
 
class CmdDisas : public ICommand {
public:
explicit CmdDisas(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void format(AttributeType *asmbuf, AttributeType *fmtstr);
 
private:
ISourceCode *isrc_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_DISAS_H__
/cmd/cmd_exit.cpp
1,39 → 1,39
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Exit and close application.
*/
 
#include "cmd_exit.h"
 
namespace debugger {
 
CmdExit::CmdExit(ITap *tap, ISocInfo *info)
: ICommand ("exit", tap, info) {
 
briefDescr_.make_string("Exit and close application");
detailedDescr_.make_string(
"Description:\n"
" Immediate close the application and exit.\n"
"Example:\n"
" exit\n");
}
 
bool CmdExit::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdExit::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
RISCV_break_simulation();
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Exit and close application.
*/
 
#include "cmd_exit.h"
 
namespace debugger {
 
CmdExit::CmdExit(ITap *tap, ISocInfo *info)
: ICommand ("exit", tap, info) {
 
briefDescr_.make_string("Exit and close application");
detailedDescr_.make_string(
"Description:\n"
" Immediate close the application and exit.\n"
"Example:\n"
" exit\n");
}
 
bool CmdExit::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdExit::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
RISCV_break_simulation();
}
 
} // namespace debugger
/cmd/cmd_exit.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Exit and close application.
*/
 
#ifndef __DEBUGGER_CMD_EXIT_H__
#define __DEBUGGER_CMD_EXIT_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdExit : public ICommand {
public:
explicit CmdExit(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_EXIT_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Exit and close application.
*/
 
#ifndef __DEBUGGER_CMD_EXIT_H__
#define __DEBUGGER_CMD_EXIT_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdExit : public ICommand {
public:
explicit CmdExit(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_EXIT_H__
/cmd/cmd_halt.cpp
1,52 → 1,52
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Halt simulation.
*/
 
#include "cmd_halt.h"
 
namespace debugger {
 
CmdHalt::CmdHalt(ITap *tap, ISocInfo *info)
: ICommand ("halt", tap, info) {
 
briefDescr_.make_string("Stop simulation");
detailedDescr_.make_string(
"Description:\n"
" Stop simulation.\n"
"Example:\n"
" halt\n"
" stop\n"
" s\n");
}
 
 
bool CmdHalt::isValid(AttributeType *args) {
AttributeType &name = (*args)[0u];
if (name.is_equal("halt") || name.is_equal("break")
|| name.is_equal("stop") || name.is_equal("s")) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdHalt::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType *dsu = info_->getpDsu();
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
uint64_t addr_run_ctrl = reinterpret_cast<uint64_t>(&dsu->udbg.v.control);
ctrl.val = 0;
ctrl.bits.halt = 1;
t1.val = ctrl.val;
tap_->write(addr_run_ctrl, 8, t1.buf);
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Halt simulation.
*/
 
#include "cmd_halt.h"
 
namespace debugger {
 
CmdHalt::CmdHalt(ITap *tap, ISocInfo *info)
: ICommand ("halt", tap, info) {
 
briefDescr_.make_string("Stop simulation");
detailedDescr_.make_string(
"Description:\n"
" Stop simulation.\n"
"Example:\n"
" halt\n"
" stop\n"
" s\n");
}
 
 
bool CmdHalt::isValid(AttributeType *args) {
AttributeType &name = (*args)[0u];
if (name.is_equal("halt") || name.is_equal("break")
|| name.is_equal("stop") || name.is_equal("s")) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdHalt::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType *dsu = info_->getpDsu();
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
uint64_t addr_run_ctrl = reinterpret_cast<uint64_t>(&dsu->udbg.v.control);
ctrl.val = 0;
ctrl.bits.halt = 1;
t1.val = ctrl.val;
tap_->write(addr_run_ctrl, 8, t1.buf);
}
 
} // namespace debugger
/cmd/cmd_halt.h
1,29 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Halt simulation.
*/
 
#ifndef __DEBUGGER_CMD_HALT_H__
#define __DEBUGGER_CMD_HALT_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdHalt : public ICommand {
public:
explicit CmdHalt(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_HALT_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Halt simulation.
*/
 
#ifndef __DEBUGGER_CMD_HALT_H__
#define __DEBUGGER_CMD_HALT_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdHalt : public ICommand {
public:
explicit CmdHalt(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_HALT_H__
/cmd/cmd_isrunning.cpp
1,50 → 1,50
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Check target status: run or not.
*/
 
#include "cmd_isrunning.h"
 
namespace debugger {
 
CmdIsRunning::CmdIsRunning(ITap *tap, ISocInfo *info)
: ICommand ("isrunning", tap, info) {
 
briefDescr_.make_string("Check target's status");
detailedDescr_.make_string(
"Description:\n"
" Check target's status as a boolean value.\n"
"Example:\n"
" isrunning\n");
}
 
bool CmdIsRunning::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdIsRunning::exec(AttributeType *args, AttributeType *res) {
res->make_boolean(false);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->udbg.v.control);
tap_->read(addr, 8, t1.buf);
ctrl.val = t1.val;
if (ctrl.bits.halt) {
res->make_boolean(false);
} else {
res->make_boolean(true);
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Check target status: run or not.
*/
 
#include "cmd_isrunning.h"
 
namespace debugger {
 
CmdIsRunning::CmdIsRunning(ITap *tap, ISocInfo *info)
: ICommand ("isrunning", tap, info) {
 
briefDescr_.make_string("Check target's status");
detailedDescr_.make_string(
"Description:\n"
" Check target's status as a boolean value.\n"
"Example:\n"
" isrunning\n");
}
 
bool CmdIsRunning::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdIsRunning::exec(AttributeType *args, AttributeType *res) {
res->make_boolean(false);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->udbg.v.control);
tap_->read(addr, 8, t1.buf);
ctrl.val = t1.val;
if (ctrl.bits.halt) {
res->make_boolean(false);
} else {
res->make_boolean(true);
}
}
 
} // namespace debugger
/cmd/cmd_isrunning.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Check target status: run or not.
*/
 
#ifndef __DEBUGGER_CMD_ISRUNNING_H__
#define __DEBUGGER_CMD_ISRUNNING_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdIsRunning : public ICommand {
public:
explicit CmdIsRunning(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_ISRUNNING_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Check target status: run or not.
*/
 
#ifndef __DEBUGGER_CMD_ISRUNNING_H__
#define __DEBUGGER_CMD_ISRUNNING_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdIsRunning : public ICommand {
public:
explicit CmdIsRunning(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_ISRUNNING_H__
/cmd/cmd_loadelf.cpp
1,85 → 1,85
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Elf-file loader command.
*/
 
#include "iservice.h"
#include "cmd_loadelf.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdLoadElf::CmdLoadElf(ITap *tap, ISocInfo *info)
: ICommand ("loadelf", tap, info) {
 
briefDescr_.make_string("Load ELF-file");
detailedDescr_.make_string(
"Description:\n"
" Load ELF-file to SOC target memory. Optional key 'nocode'\n"
" allows to read debug information from the elf-file without\n"
" target programming.\n"
"Usage:\n"
" loadelf filename [nocode]\n"
"Example:\n"
" loadelf /home/riscv/image.elf\n"
" loadelf /home/riscv/image.elf nocode\n");
}
 
bool CmdLoadElf::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("loadelf")
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdLoadElf::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
bool program = true;
if (args->size() == 3
&& (*args)[2].is_string() && (*args)[2].is_equal("nocode")) {
program = false;
}
 
/**
* @todo Elf Loader service change on elf-reader
*/
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() == 0) {
generateError(res, "Elf-service not found");
return;
}
 
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
IElfReader *elf = static_cast<IElfReader *>(
iserv->getInterface(IFACE_ELFREADER));
elf->readFile((*args)[1].to_string());
 
if (!program) {
return;
}
 
DsuMapType *dsu = info_->getpDsu();
uint64_t soft_reset = 1;
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->ulocal.v.soft_reset);
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
 
for (unsigned i = 0; i < elf->loadableSectionTotal(); i++) {
tap_->write(elf->sectionAddress(i),
static_cast<int>(elf->sectionSize(i)),
elf->sectionData(i));
}
 
soft_reset = 0;
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
}
 
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Elf-file loader command.
*/
 
#include "iservice.h"
#include "cmd_loadelf.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdLoadElf::CmdLoadElf(ITap *tap, ISocInfo *info)
: ICommand ("loadelf", tap, info) {
 
briefDescr_.make_string("Load ELF-file");
detailedDescr_.make_string(
"Description:\n"
" Load ELF-file to SOC target memory. Optional key 'nocode'\n"
" allows to read debug information from the elf-file without\n"
" target programming.\n"
"Usage:\n"
" loadelf filename [nocode]\n"
"Example:\n"
" loadelf /home/riscv/image.elf\n"
" loadelf /home/riscv/image.elf nocode\n");
}
 
bool CmdLoadElf::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("loadelf")
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdLoadElf::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
bool program = true;
if (args->size() == 3
&& (*args)[2].is_string() && (*args)[2].is_equal("nocode")) {
program = false;
}
 
/**
* @todo Elf Loader service change on elf-reader
*/
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() == 0) {
generateError(res, "Elf-service not found");
return;
}
 
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
IElfReader *elf = static_cast<IElfReader *>(
iserv->getInterface(IFACE_ELFREADER));
elf->readFile((*args)[1].to_string());
 
if (!program) {
return;
}
 
DsuMapType *dsu = info_->getpDsu();
uint64_t soft_reset = 1;
uint64_t addr = reinterpret_cast<uint64_t>(&dsu->ulocal.v.soft_reset);
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
 
for (unsigned i = 0; i < elf->loadableSectionTotal(); i++) {
tap_->write(elf->sectionAddress(i),
static_cast<int>(elf->sectionSize(i)),
elf->sectionData(i));
}
 
soft_reset = 0;
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
}
 
 
} // namespace debugger
/cmd/cmd_loadelf.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Elf-file loader command.
*/
 
#ifndef __DEBUGGER_CMD_LOADELF_H__
#define __DEBUGGER_CMD_LOADELF_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdLoadElf : public ICommand {
public:
explicit CmdLoadElf(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOADELF_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Elf-file loader command.
*/
 
#ifndef __DEBUGGER_CMD_LOADELF_H__
#define __DEBUGGER_CMD_LOADELF_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdLoadElf : public ICommand {
public:
explicit CmdLoadElf(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOADELF_H__
/cmd/cmd_log.cpp
1,50 → 1,50
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Log file enable/disable.
*/
 
#include "cmd_log.h"
 
namespace debugger {
 
CmdLog::CmdLog(ITap *tap, ISocInfo *info)
: ICommand ("log", tap, info) {
 
briefDescr_.make_string("Enable log-file");
detailedDescr_.make_string(
"Description:\n"
" Write console output into specified file.\n"
" Close log-file if the filename not specified.\n"
"Example:\n"
" log session.log\n"
" log /home/riscv/session.log\n");
}
 
bool CmdLog::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdLog::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
if (args->size() == 1) {
RISCV_disable_log();
} else {
const char *filename = (*args)[1].to_string();
if (RISCV_enable_log(filename)) {
generateError(res, "Can't open file");
}
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Log file enable/disable.
*/
 
#include "cmd_log.h"
 
namespace debugger {
 
CmdLog::CmdLog(ITap *tap, ISocInfo *info)
: ICommand ("log", tap, info) {
 
briefDescr_.make_string("Enable log-file");
detailedDescr_.make_string(
"Description:\n"
" Write console output into specified file.\n"
" Close log-file if the filename not specified.\n"
"Example:\n"
" log session.log\n"
" log /home/riscv/session.log\n");
}
 
bool CmdLog::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdLog::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
if (args->size() == 1) {
RISCV_disable_log();
} else {
const char *filename = (*args)[1].to_string();
if (RISCV_enable_log(filename)) {
generateError(res, "Can't open file");
}
}
}
 
} // namespace debugger
/cmd/cmd_log.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Log file enable/disable.
*/
 
#ifndef __DEBUGGER_CMD_LOG_H__
#define __DEBUGGER_CMD_LOG_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdLog : public ICommand {
public:
explicit CmdLog(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOG_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Log file enable/disable.
*/
 
#ifndef __DEBUGGER_CMD_LOG_H__
#define __DEBUGGER_CMD_LOG_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdLog : public ICommand {
public:
explicit CmdLog(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_LOG_H__
/cmd/cmd_memdump.cpp
1,84 → 1,84
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dump memory range into file.
*/
 
#include "cmd_memdump.h"
#include <string>
 
namespace debugger {
 
CmdMemDump::CmdMemDump(ITap *tap, ISocInfo *info)
: ICommand ("memdump", tap, info) {
 
briefDescr_.make_string("Dump memory to file");
detailedDescr_.make_string(
"Description:\n"
" Dump memory to file (default in Binary format).\n"
"Usage:\n"
" memdump <addr> <bytes> [filepath] [bin|hex]\n"
"Example:\n"
" memdump 0x0 8192 dump.bin\n"
" memdump 0x40000000 524288 dump.hex hex\n"
" memdump 0x10000000 128 \"c:/My Documents/dump.bin\"\n");
}
 
bool CmdMemDump::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 4 || args->size() == 5)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdMemDump::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
const char *filename = (*args)[3].to_string();
FILE *fd = fopen(filename, "w");
if (fd == NULL) {
char tst[256];
RISCV_sprintf(tst, sizeof(tst), "Can't open '%s' file", filename);
generateError(res, tst);
return;
}
uint64_t addr = (*args)[1].to_uint64();
int len = static_cast<int>((*args)[2].to_uint64());
res->make_data(len);
 
tap_->read(addr, len, res->data());
uint8_t *dumpbuf = res->data();
 
if (args->size() == 5 && (*args)[4].is_equal("hex")) {
char t1[256];
int t1_cnt = 0;
int idx;
for (int i = 0; i < ((len + 0xf) & ~0xf); i++) {
idx = (i & ~0xf) | (0xf - (i & 0xf));
if (idx > len) {
t1[t1_cnt++] = ' ';
t1[t1_cnt++] = ' ';
continue;
}
t1_cnt += RISCV_sprintf(&t1[t1_cnt], sizeof(t1) - t1_cnt, "%02x",
dumpbuf[idx]);
if ((i & 0xf) != 0xf) {
continue;
}
t1_cnt += RISCV_sprintf(&t1[t1_cnt], sizeof(t1) - t1_cnt, "\n");
fwrite(t1, t1_cnt, 1, fd);
t1_cnt = 0;
}
} else {
fwrite(dumpbuf, len, 1, fd);
}
fclose(fd);
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dump memory range into file.
*/
 
#include "cmd_memdump.h"
#include <string>
 
namespace debugger {
 
CmdMemDump::CmdMemDump(ITap *tap, ISocInfo *info)
: ICommand ("memdump", tap, info) {
 
briefDescr_.make_string("Dump memory to file");
detailedDescr_.make_string(
"Description:\n"
" Dump memory to file (default in Binary format).\n"
"Usage:\n"
" memdump <addr> <bytes> [filepath] [bin|hex]\n"
"Example:\n"
" memdump 0x0 8192 dump.bin\n"
" memdump 0x40000000 524288 dump.hex hex\n"
" memdump 0x10000000 128 \"c:/My Documents/dump.bin\"\n");
}
 
bool CmdMemDump::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 4 || args->size() == 5)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdMemDump::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
const char *filename = (*args)[3].to_string();
FILE *fd = fopen(filename, "w");
if (fd == NULL) {
char tst[256];
RISCV_sprintf(tst, sizeof(tst), "Can't open '%s' file", filename);
generateError(res, tst);
return;
}
uint64_t addr = (*args)[1].to_uint64();
int len = static_cast<int>((*args)[2].to_uint64());
res->make_data(len);
 
tap_->read(addr, len, res->data());
uint8_t *dumpbuf = res->data();
 
if (args->size() == 5 && (*args)[4].is_equal("hex")) {
char t1[256];
int t1_cnt = 0;
int idx;
for (int i = 0; i < ((len + 0xf) & ~0xf); i++) {
idx = (i & ~0xf) | (0xf - (i & 0xf));
if (idx > len) {
t1[t1_cnt++] = ' ';
t1[t1_cnt++] = ' ';
continue;
}
t1_cnt += RISCV_sprintf(&t1[t1_cnt], sizeof(t1) - t1_cnt, "%02x",
dumpbuf[idx]);
if ((i & 0xf) != 0xf) {
continue;
}
t1_cnt += RISCV_sprintf(&t1[t1_cnt], sizeof(t1) - t1_cnt, "\n");
fwrite(t1, t1_cnt, 1, fd);
t1_cnt = 0;
}
} else {
fwrite(dumpbuf, len, 1, fd);
}
fclose(fd);
}
 
} // namespace debugger
/cmd/cmd_memdump.h
1,29 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dump memory range into file.
*/
 
#ifndef __DEBUGGER_CMD_MEMDUMP_H__
#define __DEBUGGER_CMD_MEMDUMP_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdMemDump : public ICommand {
public:
explicit CmdMemDump(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_MEMDUMP_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dump memory range into file.
*/
 
#ifndef __DEBUGGER_CMD_MEMDUMP_H__
#define __DEBUGGER_CMD_MEMDUMP_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdMemDump : public ICommand {
public:
explicit CmdMemDump(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_MEMDUMP_H__
/cmd/cmd_read.cpp
1,96 → 1,96
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write memory.
*/
 
#include "cmd_read.h"
 
namespace debugger {
 
CmdRead::CmdRead(ITap *tap, ISocInfo *info)
: ICommand ("read", tap, info) {
 
briefDescr_.make_string("Read memory");
detailedDescr_.make_string(
"Description:\n"
" 32-bits aligned memory reading. Default bytes = 4 bytes.\n"
"Usage:\n"
" read <addr> <bytes>\n"
"Example:\n"
" read 0xfffff004 16\n"
" read 0xfffff004\n");
 
rdData_.make_data(1024);
}
 
bool CmdRead::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRead::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
uint64_t addr = (*args)[1].to_uint64();
unsigned bytes = 4;
if (args->size() == 3) {
bytes = static_cast<unsigned>((*args)[2].to_uint64());
}
/** Use 4 x Buffer size to store formatted output */
if (4 * bytes > rdData_.size()) {
rdData_.make_data(4 * bytes);
}
 
if (tap_->read(addr, bytes, rdData_.data()) == TAP_ERROR) {
res->make_nil();
return;
}
 
res->make_data(bytes, rdData_.data());
}
 
void CmdRead::to_string(AttributeType *args, AttributeType *res, AttributeType *out) {
uint64_t addr = (*args)[1].to_uint64();
int bytes = 4;
if (args->size() == 3) {
bytes = static_cast<int>((*args)[2].to_uint64());
}
 
const uint64_t MSK64 = 0x7ull;
uint64_t addr_start, addr_end, inv_i;
addr_start = addr & ~MSK64;
addr_end = (addr + bytes + 7) & ~MSK64;
 
int strsz = 0;
int rdBufSz = static_cast<int>(rdData_.size());
char *strbuf = reinterpret_cast<char *>(rdData_.data());
for (uint64_t i = addr_start; i < addr_end; i++) {
if ((i & MSK64) == 0) {
// Output address:
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz,
"[%016" RV_PRI64 "x]: ", i);
}
inv_i = (i & ~MSK64) | (MSK64 - (i & MSK64));
if ((addr <= inv_i) && (inv_i < (addr + bytes))) {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, " %02x",
res->data()[inv_i - addr]);
} else {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, " ..");
}
if ((i & MSK64) == MSK64) {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, "\n");
}
}
out->make_string(strbuf);
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write memory.
*/
 
#include "cmd_read.h"
 
namespace debugger {
 
CmdRead::CmdRead(ITap *tap, ISocInfo *info)
: ICommand ("read", tap, info) {
 
briefDescr_.make_string("Read memory");
detailedDescr_.make_string(
"Description:\n"
" 32-bits aligned memory reading. Default bytes = 4 bytes.\n"
"Usage:\n"
" read <addr> <bytes>\n"
"Example:\n"
" read 0xfffff004 16\n"
" read 0xfffff004\n");
 
rdData_.make_data(1024);
}
 
bool CmdRead::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRead::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
uint64_t addr = (*args)[1].to_uint64();
unsigned bytes = 4;
if (args->size() == 3) {
bytes = static_cast<unsigned>((*args)[2].to_uint64());
}
/** Use 4 x Buffer size to store formatted output */
if (4 * bytes > rdData_.size()) {
rdData_.make_data(4 * bytes);
}
 
if (tap_->read(addr, bytes, rdData_.data()) == TAP_ERROR) {
res->make_nil();
return;
}
 
res->make_data(bytes, rdData_.data());
}
 
void CmdRead::to_string(AttributeType *args, AttributeType *res, AttributeType *out) {
uint64_t addr = (*args)[1].to_uint64();
int bytes = 4;
if (args->size() == 3) {
bytes = static_cast<int>((*args)[2].to_uint64());
}
 
const uint64_t MSK64 = 0x7ull;
uint64_t addr_start, addr_end, inv_i;
addr_start = addr & ~MSK64;
addr_end = (addr + bytes + 7) & ~MSK64;
 
int strsz = 0;
int rdBufSz = static_cast<int>(rdData_.size());
char *strbuf = reinterpret_cast<char *>(rdData_.data());
for (uint64_t i = addr_start; i < addr_end; i++) {
if ((i & MSK64) == 0) {
// Output address:
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz,
"[%016" RV_PRI64 "x]: ", i);
}
inv_i = (i & ~MSK64) | (MSK64 - (i & MSK64));
if ((addr <= inv_i) && (inv_i < (addr + bytes))) {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, " %02x",
res->data()[inv_i - addr]);
} else {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, " ..");
}
if ((i & MSK64) == MSK64) {
strsz += RISCV_sprintf(&strbuf[strsz], rdBufSz - strsz, "\n");
}
}
out->make_string(strbuf);
}
 
} // namespace debugger
/cmd/cmd_read.h
1,33 → 1,33
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write memory.
*/
 
#ifndef __DEBUGGER_CMD_READ_H__
#define __DEBUGGER_CMD_READ_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRead : public ICommand {
public:
explicit CmdRead(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void to_string(AttributeType *args, AttributeType *res, AttributeType *out);
 
private:
AttributeType rdData_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_READ_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write memory.
*/
 
#ifndef __DEBUGGER_CMD_READ_H__
#define __DEBUGGER_CMD_READ_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRead : public ICommand {
public:
explicit CmdRead(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void to_string(AttributeType *args, AttributeType *res, AttributeType *out);
 
private:
AttributeType rdData_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_READ_H__
/cmd/cmd_reg.cpp
1,65 → 1,65
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write register value.
*/
 
#include "cmd_reg.h"
 
namespace debugger {
 
CmdReg::CmdReg(ITap *tap, ISocInfo *info)
: ICommand ("reg", tap, info) {
 
briefDescr_.make_string("Read/write register value");
detailedDescr_.make_string(
"Description:\n"
" Read or modify the specific CPU's register.\n"
"Usage:\n"
" reg name\n"
" reg name wrvalue\n"
"Example:\n"
" reg\n"
" reg pc\n"
" reg sp 0x10007fc0\n");
}
 
bool CmdReg::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdReg::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_nil();
 
uint64_t val;
const char *reg_name = (*args)[1].to_string();
uint64_t addr = info_->reg2addr(reg_name);
if (addr == REG_ADDR_ERROR) {
char tstr[128];
RISCV_sprintf(tstr, sizeof(tstr), "%s not found", reg_name);
generateError(res, tstr);
return;
}
 
if (args->size() == 2) {
int err = tap_->read(addr, 8, reinterpret_cast<uint8_t *>(&val));
if (err == TAP_ERROR) {
return;
}
res->make_uint64(val);
} else {
val = (*args)[2].to_uint64();
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&val));
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write register value.
*/
 
#include "cmd_reg.h"
 
namespace debugger {
 
CmdReg::CmdReg(ITap *tap, ISocInfo *info)
: ICommand ("reg", tap, info) {
 
briefDescr_.make_string("Read/write register value");
detailedDescr_.make_string(
"Description:\n"
" Read or modify the specific CPU's register.\n"
"Usage:\n"
" reg name\n"
" reg name wrvalue\n"
"Example:\n"
" reg\n"
" reg pc\n"
" reg sp 0x10007fc0\n");
}
 
bool CmdReg::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string())
&& (args->size() == 2 || args->size() == 3)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdReg::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_nil();
 
uint64_t val;
const char *reg_name = (*args)[1].to_string();
uint64_t addr = info_->reg2addr(reg_name);
if (addr == REG_ADDR_ERROR) {
char tstr[128];
RISCV_sprintf(tstr, sizeof(tstr), "%s not found", reg_name);
generateError(res, tstr);
return;
}
 
if (args->size() == 2) {
int err = tap_->read(addr, 8, reinterpret_cast<uint8_t *>(&val));
if (err == TAP_ERROR) {
return;
}
res->make_uint64(val);
} else {
val = (*args)[2].to_uint64();
tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&val));
}
}
 
} // namespace debugger
/cmd/cmd_reg.h
1,29 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write register value.
*/
 
#ifndef __DEBUGGER_CMD_REG_H__
#define __DEBUGGER_CMD_REG_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdReg : public ICommand {
public:
explicit CmdReg(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_REG_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read/write register value.
*/
 
#ifndef __DEBUGGER_CMD_REG_H__
#define __DEBUGGER_CMD_REG_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdReg : public ICommand {
public:
explicit CmdReg(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_REG_H__
/cmd/cmd_regs.cpp
1,77 → 1,77
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read only registers values.
*/
 
#include "cmd_regs.h"
 
namespace debugger {
 
// Any value greater or equal than 32 + 2 (general iregs + pc + npc)
#define REGS_MAX 64
 
CmdRegs::CmdRegs(ITap *tap, ISocInfo *info)
: ICommand ("regs", tap, info) {
 
briefDescr_.make_string("List of Core's registers values");
detailedDescr_.make_string(
"Description:\n"
" Print values of CPU's registers.\n"
"Return:\n"
" Dictionary if no names specified, list of int64_t otherwise.\n"
"Usage:\n"
" regs\n"
" regs name1 name2 ..\n"
"Example:\n"
" regs\n"
" regs a0 s0 sp\n");
}
 
bool CmdRegs::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() >= 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRegs::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type u;
if (args->size() != 1) {
res->make_list(args->size() - 1);
for (unsigned i = 1; i < args->size(); i++) {
const char *name = (*args)[i].to_string();
tap_->read(info_->reg2addr(name), 8, u.buf);
(*res)[i - 1].make_uint64(u.val);
}
return;
}
 
AttributeType soclst;
info_->getRegsList(&soclst);
 
struct RegsArrType {
Reg64Type reg[REGS_MAX];
};
union CpiRegionType {
RegsArrType regarr;
uint8_t buf[sizeof(RegsArrType)];
} t1;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(dsu->ureg.v.iregs);
tap_->read(addr, 8 * soclst.size(), t1.buf);
 
res->make_dict();
for (unsigned i = 0; i < soclst.size(); i++) {
const char *name = soclst[i].to_string();
(*res)[name].make_uint64(t1.regarr.reg[i].val);
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read only registers values.
*/
 
#include "cmd_regs.h"
 
namespace debugger {
 
// Any value greater or equal than 32 + 2 (general iregs + pc + npc)
#define REGS_MAX 64
 
CmdRegs::CmdRegs(ITap *tap, ISocInfo *info)
: ICommand ("regs", tap, info) {
 
briefDescr_.make_string("List of Core's registers values");
detailedDescr_.make_string(
"Description:\n"
" Print values of CPU's registers.\n"
"Return:\n"
" Dictionary if no names specified, list of int64_t otherwise.\n"
"Usage:\n"
" regs\n"
" regs name1 name2 ..\n"
"Example:\n"
" regs\n"
" regs a0 s0 sp\n");
}
 
bool CmdRegs::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() >= 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRegs::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type u;
if (args->size() != 1) {
res->make_list(args->size() - 1);
for (unsigned i = 1; i < args->size(); i++) {
const char *name = (*args)[i].to_string();
tap_->read(info_->reg2addr(name), 8, u.buf);
(*res)[i - 1].make_uint64(u.val);
}
return;
}
 
AttributeType soclst;
info_->getRegsList(&soclst);
 
struct RegsArrType {
Reg64Type reg[REGS_MAX];
};
union CpiRegionType {
RegsArrType regarr;
uint8_t buf[sizeof(RegsArrType)];
} t1;
DsuMapType *dsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(dsu->ureg.v.iregs);
tap_->read(addr, 8 * soclst.size(), t1.buf);
 
res->make_dict();
for (unsigned i = 0; i < soclst.size(); i++) {
const char *name = soclst[i].to_string();
(*res)[name].make_uint64(t1.regarr.reg[i].val);
}
}
 
} // namespace debugger
/cmd/cmd_regs.h
1,29 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read only registers values.
*/
 
#ifndef __DEBUGGER_CMD_REGS_H__
#define __DEBUGGER_CMD_REGS_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRegs : public ICommand {
public:
explicit CmdRegs(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_REGS_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read only registers values.
*/
 
#ifndef __DEBUGGER_CMD_REGS_H__
#define __DEBUGGER_CMD_REGS_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRegs : public ICommand {
public:
explicit CmdRegs(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_REGS_H__
/cmd/cmd_reset.cpp
1,62 → 1,62
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Reset, Un-reset or Reboot target command.
*/
 
#include "iservice.h"
#include "cmd_reset.h"
 
namespace debugger {
 
CmdReset::CmdReset(ITap *tap, ISocInfo *info)
: ICommand ("reset", tap, info) {
 
briefDescr_.make_string("Reset, Un-reset or Reboot target");
detailedDescr_.make_string(
"Description:\n"
" Reset, Un-reset or Reboot target.\n"
"Warning:\n"
" When reset is HIGH CPU debug port is resetting also and cannot\n"
" response on debugger requests.\n"
"Example:\n"
" reset\n"
" reset 1\n"
" reset 0\n");
}
 
bool CmdReset::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("reset") && args->size() <= 2) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdReset::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type rst;
DsuMapType *dsu = info_->getpDsu();
uint64_t sw_rst_addr =
reinterpret_cast<uint64_t>(&dsu->ulocal.v.soft_reset);
 
if (args->size() == 2) {
rst.val = (*args)[1].to_uint64();
tap_->write(sw_rst_addr, 8, rst.buf);
} else {
// Reboot
rst.val = 1;
tap_->write(sw_rst_addr, 8, rst.buf);
RISCV_sleep_ms(10);
rst.val = 0;
tap_->write(sw_rst_addr, 8, rst.buf);
}
}
 
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Reset, Un-reset or Reboot target command.
*/
 
#include "iservice.h"
#include "cmd_reset.h"
 
namespace debugger {
 
CmdReset::CmdReset(ITap *tap, ISocInfo *info)
: ICommand ("reset", tap, info) {
 
briefDescr_.make_string("Reset, Un-reset or Reboot target");
detailedDescr_.make_string(
"Description:\n"
" Reset, Un-reset or Reboot target.\n"
"Warning:\n"
" When reset is HIGH CPU debug port is resetting also and cannot\n"
" response on debugger requests.\n"
"Example:\n"
" reset\n"
" reset 1\n"
" reset 0\n");
}
 
bool CmdReset::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("reset") && args->size() <= 2) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdReset::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type rst;
DsuMapType *dsu = info_->getpDsu();
uint64_t sw_rst_addr =
reinterpret_cast<uint64_t>(&dsu->ulocal.v.soft_reset);
 
if (args->size() == 2) {
rst.val = (*args)[1].to_uint64();
tap_->write(sw_rst_addr, 8, rst.buf);
} else {
// Reboot
rst.val = 1;
tap_->write(sw_rst_addr, 8, rst.buf);
RISCV_sleep_ms(10);
rst.val = 0;
tap_->write(sw_rst_addr, 8, rst.buf);
}
}
 
 
} // namespace debugger
/cmd/cmd_reset.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Reset, Un-reset or Reboot target command.
*/
 
#ifndef __DEBUGGER_CMD_RESET_H__
#define __DEBUGGER_CMD_RESET_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdReset : public ICommand {
public:
explicit CmdReset(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_RESET_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Reset, Un-reset or Reboot target command.
*/
 
#ifndef __DEBUGGER_CMD_RESET_H__
#define __DEBUGGER_CMD_RESET_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdReset : public ICommand {
public:
explicit CmdReset(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_RESET_H__
/cmd/cmd_run.cpp
1,64 → 1,64
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Run simulation.
*/
 
#include "cmd_run.h"
 
namespace debugger {
 
CmdRun::CmdRun(ITap *tap, ISocInfo *info)
: ICommand ("run", tap, info) {
 
briefDescr_.make_string("Run simulation for a specify number of steps\"");
detailedDescr_.make_string(
"Description:\n"
" Run simulation for a specified number of steps.\n"
"Usage:\n"
" run <N steps>\n"
"Example:\n"
" run\n"
" go 1000\n"
" c 1\n");
}
 
 
bool CmdRun::isValid(AttributeType *args) {
AttributeType &name = (*args)[0u];
if ((name.is_equal("run") || name.is_equal("c") || name.is_equal("go"))
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRun::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
DsuMapType *dsu = info_->getpDsu();
Reg64Type runctrl;
uint64_t addr_run_ctrl = reinterpret_cast<uint64_t>(&dsu->udbg.v.control);
uint64_t addr_step_cnt =
reinterpret_cast<uint64_t>(&dsu->udbg.v.stepping_mode_steps);
 
if (args->size() == 1) {
runctrl.val = 0;
tap_->write(addr_run_ctrl, 8, runctrl.buf);
} else if (args->size() == 2) {
runctrl.val = (*args)[1].to_uint64();
tap_->write(addr_step_cnt, 8, runctrl.buf);
 
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
ctrl.val = 0;
ctrl.bits.stepping = 1;
runctrl.val = ctrl.val;
tap_->write(addr_run_ctrl, 8, runctrl.buf);
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Run simulation.
*/
 
#include "cmd_run.h"
 
namespace debugger {
 
CmdRun::CmdRun(ITap *tap, ISocInfo *info)
: ICommand ("run", tap, info) {
 
briefDescr_.make_string("Run simulation for a specify number of steps\"");
detailedDescr_.make_string(
"Description:\n"
" Run simulation for a specified number of steps.\n"
"Usage:\n"
" run <N steps>\n"
"Example:\n"
" run\n"
" go 1000\n"
" c 1\n");
}
 
 
bool CmdRun::isValid(AttributeType *args) {
AttributeType &name = (*args)[0u];
if ((name.is_equal("run") || name.is_equal("c") || name.is_equal("go"))
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdRun::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
DsuMapType *dsu = info_->getpDsu();
Reg64Type runctrl;
uint64_t addr_run_ctrl = reinterpret_cast<uint64_t>(&dsu->udbg.v.control);
uint64_t addr_step_cnt =
reinterpret_cast<uint64_t>(&dsu->udbg.v.stepping_mode_steps);
 
if (args->size() == 1) {
runctrl.val = 0;
tap_->write(addr_run_ctrl, 8, runctrl.buf);
} else if (args->size() == 2) {
runctrl.val = (*args)[1].to_uint64();
tap_->write(addr_step_cnt, 8, runctrl.buf);
 
DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
ctrl.val = 0;
ctrl.bits.stepping = 1;
runctrl.val = ctrl.val;
tap_->write(addr_run_ctrl, 8, runctrl.buf);
}
}
 
} // namespace debugger
/cmd/cmd_run.h
1,29 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Run simulation.
*/
 
#ifndef __DEBUGGER_CMD_RUN_H__
#define __DEBUGGER_CMD_RUN_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRun : public ICommand {
public:
explicit CmdRun(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_RUN_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Run simulation.
*/
 
#ifndef __DEBUGGER_CMD_RUN_H__
#define __DEBUGGER_CMD_RUN_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdRun : public ICommand {
public:
explicit CmdRun(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_RUN_H__
/cmd/cmd_stack.cpp
1,91 → 1,91
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU stack trace buffer.
*/
 
#include "cmd_stack.h"
#include "iservice.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdStack::CmdStack(ITap *tap, ISocInfo *info)
: ICommand ("stack", tap, info) {
 
briefDescr_.make_string("Read CPU Stack Trace buffer");
detailedDescr_.make_string(
"Description:\n"
" Read CPU stack trace buffer. Buffer's size is defined\n"
" by VHDL configuration parameter:\n"
"Usage:\n"
" stack <depth>\n"
"Example:\n"
" stack\n"
" stack 3\n");
}
 
bool CmdStack::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && (args->size() == 1
|| (args->size() == 2 && (*args)[1].is_integer()))) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdStack::exec(AttributeType *args, AttributeType *res) {
res->make_list(0);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_cnt);
t1.val = 0;
tap_->read(addr, 8, t1.buf);
 
addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_buf[0]);
unsigned trace_sz = t1.buf32[0];
if (args->size() == 2 && args[1].to_uint64() < trace_sz) {
addr += 8 * (trace_sz - args[1].to_uint32());
trace_sz = args[1].to_uint32();
}
 
if (trace_sz == 0) {
return;
}
 
AttributeType tbuf, lstServ;
uint64_t *p_data;
IElfReader *elf = 0;
uint64_t from_addr, to_addr;
tbuf.make_data(16*trace_sz);
tap_->read(addr, tbuf.size(), tbuf.data());
 
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() >= 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
elf = static_cast<IElfReader *>(iserv->getInterface(IFACE_ELFREADER));
}
 
res->make_list(t1.buf32[0]);
p_data = reinterpret_cast<uint64_t *>(tbuf.data());
for (unsigned i = 0; i < trace_sz; i++) {
AttributeType &item = (*res)[i];
from_addr = p_data[2*(trace_sz - i) - 2];
to_addr = p_data[2*(trace_sz - i) - 1];
// [from, ['symb_name',symb_offset], to, ['symb_name',symb_offset]]
item.make_list(4);
item[0u].make_uint64(from_addr);
item[2].make_uint64(to_addr);
if (elf) {
elf->addressToSymbol(from_addr, &item[1]);
elf->addressToSymbol(to_addr, &item[3]);
}
}
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU stack trace buffer.
*/
 
#include "cmd_stack.h"
#include "iservice.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdStack::CmdStack(ITap *tap, ISocInfo *info)
: ICommand ("stack", tap, info) {
 
briefDescr_.make_string("Read CPU Stack Trace buffer");
detailedDescr_.make_string(
"Description:\n"
" Read CPU stack trace buffer. Buffer's size is defined\n"
" by VHDL configuration parameter:\n"
"Usage:\n"
" stack <depth>\n"
"Example:\n"
" stack\n"
" stack 3\n");
}
 
bool CmdStack::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && (args->size() == 1
|| (args->size() == 2 && (*args)[1].is_integer()))) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdStack::exec(AttributeType *args, AttributeType *res) {
res->make_list(0);
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
Reg64Type t1;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_cnt);
t1.val = 0;
tap_->read(addr, 8, t1.buf);
 
addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_buf[0]);
unsigned trace_sz = t1.buf32[0];
if (args->size() == 2 && args[1].to_uint64() < trace_sz) {
addr += 8 * (trace_sz - args[1].to_uint32());
trace_sz = args[1].to_uint32();
}
 
if (trace_sz == 0) {
return;
}
 
AttributeType tbuf, lstServ;
uint64_t *p_data;
IElfReader *elf = 0;
uint64_t from_addr, to_addr;
tbuf.make_data(16*trace_sz);
tap_->read(addr, tbuf.size(), tbuf.data());
 
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() >= 0) {
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
elf = static_cast<IElfReader *>(iserv->getInterface(IFACE_ELFREADER));
}
 
res->make_list(t1.buf32[0]);
p_data = reinterpret_cast<uint64_t *>(tbuf.data());
for (unsigned i = 0; i < trace_sz; i++) {
AttributeType &item = (*res)[i];
from_addr = p_data[2*(trace_sz - i) - 2];
to_addr = p_data[2*(trace_sz - i) - 1];
// [from, ['symb_name',symb_offset], to, ['symb_name',symb_offset]]
item.make_list(4);
item[0u].make_uint64(from_addr);
item[2].make_uint64(to_addr);
if (elf) {
elf->addressToSymbol(from_addr, &item[1]);
elf->addressToSymbol(to_addr, &item[3]);
}
}
}
 
} // namespace debugger
/cmd/cmd_stack.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU stack trace buffer.
*/
 
#ifndef __DEBUGGER_CMD_STACK_H__
#define __DEBUGGER_CMD_STACK_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdStack : public ICommand {
public:
explicit CmdStack(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_STACK_H__
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read CPU stack trace buffer.
*/
 
#ifndef __DEBUGGER_CMD_STACK_H__
#define __DEBUGGER_CMD_STACK_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdStack : public ICommand {
public:
explicit CmdStack(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_STACK_H__
/cmd/cmd_status.cpp
1,66 → 1,66
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read target's status register.
*/
 
#include "cmd_status.h"
 
namespace debugger {
 
CmdStatus::CmdStatus(ITap *tap, ISocInfo *info)
: ICommand ("status", tap, info) {
 
briefDescr_.make_string("Read target's status register");
detailedDescr_.make_string(
"Description:\n"
" Read target's status register as a uint64_t value.\n"
" Status register bits:\n"
" [0] - Halt bit. 0 = running; 1 = is halted.\n"
" [1] - Stepping mode enable bit.\n"
" [2] - Breakpoint hit signaling bit.\n"
" [19:4] - Core ID hardwired value.\n"
"Example:\n"
" status\n");
}
 
bool CmdStatus::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdStatus::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_nil();
 
Reg64Type t1;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->udbg.v.control);
if (tap_->read(addr, 8, t1.buf) == TAP_ERROR) {
return;
}
res->make_uint64(t1.val);
 
#if 0
// Instr trace info
addr = reinterpret_cast<uint64_t>(pdsu->ureg.v.instr_buf);
AttributeType t2;
t2.make_data(4*8);
if (tap_->read(addr, 4*8, t2.data()) == TAP_ERROR) {
return;
}
Reg64Type *instr = reinterpret_cast<Reg64Type *>(t2.data());
RISCV_printf(0, 0, " 3. [%08x] %08x", instr[3].buf32[1], instr[3].buf32[0]);
RISCV_printf(0, 0, " 2. [%08x] %08x", instr[2].buf32[1], instr[2].buf32[0]);
RISCV_printf(0, 0, " 1. [%08x] %08x", instr[1].buf32[1], instr[1].buf32[0]);
RISCV_printf(0, 0, " 0. [%08x] %08x", instr[0].buf32[1], instr[0].buf32[0]);
#endif
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read target's status register.
*/
 
#include "cmd_status.h"
 
namespace debugger {
 
CmdStatus::CmdStatus(ITap *tap, ISocInfo *info)
: ICommand ("status", tap, info) {
 
briefDescr_.make_string("Read target's status register");
detailedDescr_.make_string(
"Description:\n"
" Read target's status register as a uint64_t value.\n"
" Status register bits:\n"
" [0] - Halt bit. 0 = running; 1 = is halted.\n"
" [1] - Stepping mode enable bit.\n"
" [2] - Breakpoint hit signaling bit.\n"
" [19:4] - Core ID hardwired value.\n"
"Example:\n"
" status\n");
}
 
bool CmdStatus::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 1) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdStatus::exec(AttributeType *args, AttributeType *res) {
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
res->make_nil();
 
Reg64Type t1;
DsuMapType *pdsu = info_->getpDsu();
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->udbg.v.control);
if (tap_->read(addr, 8, t1.buf) == TAP_ERROR) {
return;
}
res->make_uint64(t1.val);
 
#if 0
// Instr trace info
addr = reinterpret_cast<uint64_t>(pdsu->ureg.v.instr_buf);
AttributeType t2;
t2.make_data(4*8);
if (tap_->read(addr, 4*8, t2.data()) == TAP_ERROR) {
return;
}
Reg64Type *instr = reinterpret_cast<Reg64Type *>(t2.data());
RISCV_printf(0, 0, " 3. [%08x] %08x", instr[3].buf32[1], instr[3].buf32[0]);
RISCV_printf(0, 0, " 2. [%08x] %08x", instr[2].buf32[1], instr[2].buf32[0]);
RISCV_printf(0, 0, " 1. [%08x] %08x", instr[1].buf32[1], instr[1].buf32[0]);
RISCV_printf(0, 0, " 0. [%08x] %08x", instr[0].buf32[1], instr[0].buf32[0]);
#endif
}
 
} // namespace debugger
/cmd/cmd_status.h
1,31 → 1,31
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read target's status register.
*/
 
#ifndef __DEBUGGER_CMD_STATUS_H__
#define __DEBUGGER_CMD_STATUS_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdStatus : public ICommand {
public:
explicit CmdStatus(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_STATUS_H__
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Read target's status register.
*/
 
#ifndef __DEBUGGER_CMD_STATUS_H__
#define __DEBUGGER_CMD_STATUS_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdStatus : public ICommand {
public:
explicit CmdStatus(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_STATUS_H__
/cmd/cmd_symb.cpp
1,120 → 1,120
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Browse symbols command.
*/
 
#include "iservice.h"
#include "cmd_symb.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdSymb::CmdSymb(ITap *tap, ISocInfo *info)
: ICommand ("symb", tap, info) {
 
briefDescr_.make_string("Get symbols list");
detailedDescr_.make_string(
"Description:\n"
" Read symbols list. Command 'loadelf' must be applied first to\n"
" make available debug information.\n"
"Usage:\n"
" symb filter\n"
"Example:\n"
" symb\n"
" symb *main*\n");
}
 
bool CmdSymb::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("symb")
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdSymb::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() == 0) {
generateError(res, "Elf-service not found");
return;
}
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
IElfReader *elf = static_cast<IElfReader *>(
iserv->getInterface(IFACE_ELFREADER));
 
if (args->size() == 2 && (*args)[1].is_string()) {
AttributeType allSymb;
elf->getSymbols(&allSymb);
applyFilter((*args)[1].to_string(), &allSymb, res);
} else {
elf->getSymbols(res);
}
}
 
void CmdSymb::applyFilter(const char *filt, AttributeType *in,
AttributeType *out) {
const char *symbname;
out->make_list(0);
for (unsigned i = 0; i < in->size(); i++) {
AttributeType &item = (*in)[i];
symbname = item[Symbol_Name].to_string();
if (filt_pass(filt, symbname)) {
out->add_to_list(&item);
}
}
}
 
bool CmdSymb::filt_pass(const char *filt, const char *symbname) {
bool sequence;
const char *pf, *ps;
while ((*filt) && (*symbname)) {
if (filt[0] == '*') {
filt++;
pf = filt;
sequence = false;
if (pf[0] == '\0') {
return true;
}
while (symbname[0] != '\0') {
if (pf[0] == '\0') {
return true;
} else if (pf[0] == '*') {
return filt_pass(pf, symbname);
} else if (pf[0] == symbname[0]) {
pf++;
if (!sequence) {
sequence = true;
ps = symbname;
}
} else if (sequence) {
sequence = false;
pf = filt;
symbname = ps;
}
symbname++;
}
if ((pf[0] != 0) && (pf[0] != '*') && (pf[0] != '?')) {
sequence = false;
}
return sequence;
} else if (filt[0] == '?' || symbname[0] == filt[0]) {
filt++;
} else if (symbname[0] != filt[0]) {
return false;
}
 
symbname++;
}
return false;
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Browse symbols command.
*/
 
#include "iservice.h"
#include "cmd_symb.h"
#include "coreservices/ielfreader.h"
 
namespace debugger {
 
CmdSymb::CmdSymb(ITap *tap, ISocInfo *info)
: ICommand ("symb", tap, info) {
 
briefDescr_.make_string("Get symbols list");
detailedDescr_.make_string(
"Description:\n"
" Read symbols list. Command 'loadelf' must be applied first to\n"
" make available debug information.\n"
"Usage:\n"
" symb filter\n"
"Example:\n"
" symb\n"
" symb *main*\n");
}
 
bool CmdSymb::isValid(AttributeType *args) {
if ((*args)[0u].is_equal("symb")
&& (args->size() == 1 || args->size() == 2)) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdSymb::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
AttributeType lstServ;
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
if (lstServ.size() == 0) {
generateError(res, "Elf-service not found");
return;
}
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
IElfReader *elf = static_cast<IElfReader *>(
iserv->getInterface(IFACE_ELFREADER));
 
if (args->size() == 2 && (*args)[1].is_string()) {
AttributeType allSymb;
elf->getSymbols(&allSymb);
applyFilter((*args)[1].to_string(), &allSymb, res);
} else {
elf->getSymbols(res);
}
}
 
void CmdSymb::applyFilter(const char *filt, AttributeType *in,
AttributeType *out) {
const char *symbname;
out->make_list(0);
for (unsigned i = 0; i < in->size(); i++) {
AttributeType &item = (*in)[i];
symbname = item[Symbol_Name].to_string();
if (filt_pass(filt, symbname)) {
out->add_to_list(&item);
}
}
}
 
bool CmdSymb::filt_pass(const char *filt, const char *symbname) {
bool sequence;
const char *pf, *ps;
while ((*filt) && (*symbname)) {
if (filt[0] == '*') {
filt++;
pf = filt;
sequence = false;
if (pf[0] == '\0') {
return true;
}
while (symbname[0] != '\0') {
if (pf[0] == '\0') {
return true;
} else if (pf[0] == '*') {
return filt_pass(pf, symbname);
} else if (pf[0] == symbname[0]) {
pf++;
if (!sequence) {
sequence = true;
ps = symbname;
}
} else if (sequence) {
sequence = false;
pf = filt;
symbname = ps;
}
symbname++;
}
if ((pf[0] != 0) && (pf[0] != '*') && (pf[0] != '?')) {
sequence = false;
}
return sequence;
} else if (filt[0] == '?' || symbname[0] == filt[0]) {
filt++;
} else if (symbname[0] != filt[0]) {
return false;
}
 
symbname++;
}
return false;
}
 
} // namespace debugger
/cmd/cmd_symb.h
1,33 → 1,33
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Browse symbols command.
*/
 
#ifndef __DEBUGGER_CMD_SYMB_H__
#define __DEBUGGER_CMD_SYMB_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdSymb : public ICommand {
public:
explicit CmdSymb(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void applyFilter(const char *filt, AttributeType *in, AttributeType *out);
bool filt_pass(const char *filt, const char *symbname);
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_SYMB_H__
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Browse symbols command.
*/
 
#ifndef __DEBUGGER_CMD_SYMB_H__
#define __DEBUGGER_CMD_SYMB_H__
 
#include "api_core.h"
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdSymb : public ICommand {
public:
explicit CmdSymb(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
void applyFilter(const char *filt, AttributeType *in, AttributeType *out);
bool filt_pass(const char *filt, const char *symbname);
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_SYMB_H__
/cmd/cmd_write.cpp
1,65 → 1,65
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Write memory.
*/
 
#include "cmd_write.h"
 
namespace debugger {
 
CmdWrite::CmdWrite(ITap *tap, ISocInfo *info)
: ICommand ("write", tap, info) {
 
briefDescr_.make_string("Write memory");
detailedDescr_.make_string(
"Description:\n"
" Write memory.\n"
"Usage:\n"
" write <addr> <bytes> [value 64bits]\n"
"Example:\n"
" write 0xfffff004 4 0x20160323\n"
" write 0x10040000 16 [0xaabbccdd00112233, 0xaabbccdd00112233]\n");
}
 
bool CmdWrite::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 4) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdWrite::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
uint64_t addr = (*args)[1].to_uint64();
uint64_t val = (*args)[3].to_uint64();
unsigned bytes = static_cast<unsigned>((*args)[2].to_uint64());
 
/** aech value 8-bytes (64 bits) add 8 for bullet proofness: */
if (wrData_.size() < (bytes + 8)) {
wrData_.make_data(bytes + 8);
}
 
if ((*args)[3].is_integer()) {
reinterpret_cast<uint64_t *>(wrData_.data())[0] = val;
} else if ((*args)[3].is_list()) {
const AttributeType &lst = (*args)[3];
uint64_t *tmpbuf = reinterpret_cast<uint64_t *>(wrData_.data());
for (unsigned i = 0; i < lst.size(); i++) {
val = lst[i].to_uint64();
tmpbuf[i] = val;
}
} else {
generateError(res, "Write value must be i or [i*]");
return;
}
tap_->write(addr, bytes, wrData_.data());
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Write memory.
*/
 
#include "cmd_write.h"
 
namespace debugger {
 
CmdWrite::CmdWrite(ITap *tap, ISocInfo *info)
: ICommand ("write", tap, info) {
 
briefDescr_.make_string("Write memory");
detailedDescr_.make_string(
"Description:\n"
" Write memory.\n"
"Usage:\n"
" write <addr> <bytes> [value 64bits]\n"
"Example:\n"
" write 0xfffff004 4 0x20160323\n"
" write 0x10040000 16 [0xaabbccdd00112233, 0xaabbccdd00112233]\n");
}
 
bool CmdWrite::isValid(AttributeType *args) {
if ((*args)[0u].is_equal(cmdName_.to_string()) && args->size() == 4) {
return CMD_VALID;
}
return CMD_INVALID;
}
 
void CmdWrite::exec(AttributeType *args, AttributeType *res) {
res->make_nil();
if (!isValid(args)) {
generateError(res, "Wrong argument list");
return;
}
 
uint64_t addr = (*args)[1].to_uint64();
uint64_t val = (*args)[3].to_uint64();
unsigned bytes = static_cast<unsigned>((*args)[2].to_uint64());
 
/** aech value 8-bytes (64 bits) add 8 for bullet proofness: */
if (wrData_.size() < (bytes + 8)) {
wrData_.make_data(bytes + 8);
}
 
if ((*args)[3].is_integer()) {
reinterpret_cast<uint64_t *>(wrData_.data())[0] = val;
} else if ((*args)[3].is_list()) {
const AttributeType &lst = (*args)[3];
uint64_t *tmpbuf = reinterpret_cast<uint64_t *>(wrData_.data());
for (unsigned i = 0; i < lst.size(); i++) {
val = lst[i].to_uint64();
tmpbuf[i] = val;
}
} else {
generateError(res, "Write value must be i or [i*]");
return;
}
tap_->write(addr, bytes, wrData_.data());
}
 
} // namespace debugger
/cmd/cmd_write.h
1,30 → 1,30
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Write memory.
*/
 
#ifndef __DEBUGGER_CMD_WRITE_H__
#define __DEBUGGER_CMD_WRITE_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdWrite : public ICommand {
public:
explicit CmdWrite(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
AttributeType wrData_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_WRITE_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Write memory.
*/
 
#ifndef __DEBUGGER_CMD_WRITE_H__
#define __DEBUGGER_CMD_WRITE_H__
 
#include "api_core.h"
#include "coreservices/icommand.h"
 
namespace debugger {
 
class CmdWrite : public ICommand {
public:
explicit CmdWrite(ITap *tap, ISocInfo *info);
 
/** ICommand */
virtual bool isValid(AttributeType *args);
virtual void exec(AttributeType *args, AttributeType *res);
 
private:
AttributeType wrData_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_CMD_WRITE_H__
/cmdexec.cpp
1,285 → 1,285
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Command Executor implementation.
*/
 
#include <string.h>
#include "cmdexec.h"
#include "cmd/cmd_regs.h"
#include "cmd/cmd_reg.h"
#include "cmd/cmd_loadelf.h"
#include "cmd/cmd_log.h"
#include "cmd/cmd_isrunning.h"
#include "cmd/cmd_read.h"
#include "cmd/cmd_write.h"
#include "cmd/cmd_run.h"
#include "cmd/cmd_halt.h"
#include "cmd/cmd_csr.h"
#include "cmd/cmd_exit.h"
#include "cmd/cmd_memdump.h"
#include "cmd/cmd_br.h"
#include "cmd/cmd_cpi.h"
#include "cmd/cmd_status.h"
#include "cmd/cmd_reset.h"
#include "cmd/cmd_disas.h"
#include "cmd/cmd_busutil.h"
#include "cmd/cmd_symb.h"
#include "cmd/cmd_stack.h"
 
namespace debugger {
 
/** Class registration in the Core */
REGISTER_CLASS(CmdExecutor)
 
CmdExecutor::CmdExecutor(const char *name)
: IService(name) {
registerInterface(static_cast<ICmdExecutor *>(this));
registerAttribute("Tap", &tap_);
registerAttribute("SocInfo", &socInfo_);
 
//console_.make_list(0);
tap_.make_string("");
socInfo_.make_string("");
cmds_.make_list(0);
 
RISCV_mutex_init(&mutexExec_);
 
tmpbuf_ = new uint8_t[tmpbuf_size_ = 4096];
outbuf_ = new char[outbuf_size_ = 4096];
}
 
CmdExecutor::~CmdExecutor() {
RISCV_mutex_destroy(&mutexExec_);
delete [] tmpbuf_;
delete [] outbuf_;
for (unsigned i = 0; i < cmds_.size(); i++) {
delete cmds_[i].to_iface();
}
}
 
void CmdExecutor::postinitService() {
itap_ = static_cast<ITap *>
(RISCV_get_service_iface(tap_.to_string(), IFACE_TAP));
info_ = static_cast<ISocInfo *>
(RISCV_get_service_iface(socInfo_.to_string(),
IFACE_SOC_INFO));
 
// Core commands registration:
registerCommand(new CmdBr(itap_, info_));
registerCommand(new CmdBusUtil(itap_, info_));
registerCommand(new CmdCpi(itap_, info_));
registerCommand(new CmdCsr(itap_, info_));
registerCommand(new CmdDisas(itap_, info_));
registerCommand(new CmdExit(itap_, info_));
registerCommand(new CmdHalt(itap_, info_));
registerCommand(new CmdIsRunning(itap_, info_));
registerCommand(new CmdLoadElf(itap_, info_));
registerCommand(new CmdLog(itap_, info_));
registerCommand(new CmdMemDump(itap_, info_));
registerCommand(new CmdRead(itap_, info_));
registerCommand(new CmdRun(itap_, info_));
registerCommand(new CmdReg(itap_, info_));
registerCommand(new CmdRegs(itap_, info_));
registerCommand(new CmdReset(itap_, info_));
registerCommand(new CmdStack(itap_, info_));
registerCommand(new CmdStatus(itap_, info_));
registerCommand(new CmdSymb(itap_, info_));
registerCommand(new CmdWrite(itap_, info_));
}
 
void CmdExecutor::registerCommand(ICommand *icmd) {
AttributeType t1(icmd);
cmds_.add_to_list(&t1);
}
 
void CmdExecutor::unregisterCommand(ICommand *icmd) {
for (unsigned i = 0; i < cmds_.size(); i++) {
if (cmds_[i].to_iface() == icmd) {
cmds_.remove_from_list(i);
break;
}
}
}
 
void CmdExecutor::exec(const char *line, AttributeType *res, bool silent) {
RISCV_mutex_lock(&mutexExec_);
res->make_nil();
 
AttributeType cmd;
if (line[0] == '[' || line[0] == '}') {
cmd.from_config(line);
} else {
cmd.make_string(line);
}
 
AttributeType listArgs(Attr_List), *cmd_parsed;
if (cmd.is_string()) {
splitLine(const_cast<char *>(cmd.to_string()), &listArgs);
cmd_parsed = &listArgs;
} else {
cmd_parsed = &cmd;
}
processSimple(cmd_parsed, res);
 
RISCV_mutex_unlock(&mutexExec_);
 
/** Do not output any information into console in silent mode: */
if (silent) {
return;
}
//RISCV_printf0("%s", outbuf_);
}
 
void CmdExecutor::commands(const char *substr, AttributeType *res) {
if (!res->is_list()) {
res->make_list(0);
}
AttributeType item;
item.make_list(3);
for (unsigned i = 0; i < cmds_.size(); i++) {
ICommand *icmd = static_cast<ICommand *>(cmds_[i].to_iface());
if (strstr(icmd->cmdName(), substr)) {
item[0u].make_string(icmd->cmdName());
item[1].make_string(icmd->briefDescr());
item[2].make_string(icmd->detailedDescr());
res->add_to_list(&item);
}
}
}
 
void CmdExecutor::processSimple(AttributeType *cmd, AttributeType *res) {
outbuf_[outbuf_cnt_ = 0] = '\0';
if (cmd->size() == 0) {
return;
}
 
ICommand *icmd;
if (!(*cmd)[0u].is_string()) {
RISCV_error("Wrong command format", NULL);
return;
}
 
if ((*cmd)[0u].is_equal("help")) {
if (cmd->size() == 1) {
RISCV_printf0("** List of supported commands: **", NULL);
for (unsigned i = 0; i < cmds_.size(); i++) {
icmd = static_cast<ICommand *>(cmds_[i].to_iface());
RISCV_printf0("%13s - %s",
icmd->cmdName(), icmd->briefDescr());
}
} else {
const char *helpcmd = (*cmd)[1].to_string();
icmd = getICommand(helpcmd);
if (icmd) {
RISCV_printf0("\n%s", icmd->detailedDescr());
} else {
RISCV_error("Command '%s' not found", helpcmd);
}
}
return;
}
 
AttributeType u;
icmd = getICommand(cmd);
if (!icmd) {
RISCV_error("Command '%s' not found. Use 'help' to list commands",
(*cmd)[0u].to_string());
return;
}
icmd->exec(cmd, res);
 
if (cmdIsError(res)) {
RISCV_error("Command '%s' error: '%s'",
(*res)[1].to_string(), (*res)[2].to_string());
}
}
 
bool CmdExecutor::cmdIsError(AttributeType *res) {
if (!res->is_list() || res->size() != 3) {
return false;
}
if (!(*res)[0u].is_string()) {
return false;
}
return (*res)[0u].is_equal("ERROR");
}
 
ICommand *CmdExecutor::getICommand(AttributeType *args) {
ICommand *ret = 0;
for (unsigned i = 0; i < cmds_.size(); i++) {
ret = static_cast<ICommand *>(cmds_[i].to_iface());
if (ret && (ret->isValid(args) == CMD_VALID)) {
return ret;
}
}
return 0;
}
 
ICommand *CmdExecutor::getICommand(const char *name) {
ICommand *ret = 0;
for (unsigned i = 0; i < cmds_.size(); i++) {
ret = static_cast<ICommand *>(cmds_[i].to_iface());
if (ret && strcmp(ret->cmdName(), name) == 0) {
return ret;
}
}
return 0;
}
 
void CmdExecutor::splitLine(char *str, AttributeType *listArgs) {
char *end = str;
bool last = false;
bool inside_string = false;
char string_marker;
while (*str) {
if (*end == '\0') {
last = true;
} else if (*end == ' ' && !inside_string) {
*end = '\0';
while (*(end + 1) == ' ') {
*(++end) = '\0';
}
} else if (!inside_string && (*end == '"' || *end == '\'')) {
inside_string = true;
string_marker = *end;
} else if (inside_string && string_marker == *end) {
inside_string = false;
}
 
if (*end == '\0') {
AttributeType item;
if ((str[0] >= '0' && str[0] <= '9')
|| (str[0] == '[') || (str[0] == '"') || (str[0] == '\'')
|| (str[0] == '{') || (str[0] == '(')) {
item.from_config(str);
} else {
item.make_string(str);
}
listArgs->add_to_list(&item);
if (!last) {
splitLine(end + 1, listArgs);
}
break;
}
++end;
}
}
 
int CmdExecutor::outf(const char *fmt, ...) {
if (outbuf_cnt_ > (outbuf_size_ - 128)) {
char *t = new char [2*outbuf_size_];
memcpy(t, outbuf_, outbuf_size_);
delete [] outbuf_;
outbuf_size_ *= 2;
outbuf_ = t;
}
va_list arg;
va_start(arg, fmt);
outbuf_cnt_ += vsprintf(&outbuf_[outbuf_cnt_], fmt, arg);
va_end(arg);
return outbuf_cnt_;
}
 
} // namespace debugger
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Command Executor implementation.
*/
 
#include <string.h>
#include "cmdexec.h"
#include "cmd/cmd_regs.h"
#include "cmd/cmd_reg.h"
#include "cmd/cmd_loadelf.h"
#include "cmd/cmd_log.h"
#include "cmd/cmd_isrunning.h"
#include "cmd/cmd_read.h"
#include "cmd/cmd_write.h"
#include "cmd/cmd_run.h"
#include "cmd/cmd_halt.h"
#include "cmd/cmd_csr.h"
#include "cmd/cmd_exit.h"
#include "cmd/cmd_memdump.h"
#include "cmd/cmd_br.h"
#include "cmd/cmd_cpi.h"
#include "cmd/cmd_status.h"
#include "cmd/cmd_reset.h"
#include "cmd/cmd_disas.h"
#include "cmd/cmd_busutil.h"
#include "cmd/cmd_symb.h"
#include "cmd/cmd_stack.h"
 
namespace debugger {
 
/** Class registration in the Core */
REGISTER_CLASS(CmdExecutor)
 
CmdExecutor::CmdExecutor(const char *name)
: IService(name) {
registerInterface(static_cast<ICmdExecutor *>(this));
registerAttribute("Tap", &tap_);
registerAttribute("SocInfo", &socInfo_);
 
//console_.make_list(0);
tap_.make_string("");
socInfo_.make_string("");
cmds_.make_list(0);
 
RISCV_mutex_init(&mutexExec_);
 
tmpbuf_ = new uint8_t[tmpbuf_size_ = 4096];
outbuf_ = new char[outbuf_size_ = 4096];
}
 
CmdExecutor::~CmdExecutor() {
RISCV_mutex_destroy(&mutexExec_);
delete [] tmpbuf_;
delete [] outbuf_;
for (unsigned i = 0; i < cmds_.size(); i++) {
delete cmds_[i].to_iface();
}
}
 
void CmdExecutor::postinitService() {
itap_ = static_cast<ITap *>
(RISCV_get_service_iface(tap_.to_string(), IFACE_TAP));
info_ = static_cast<ISocInfo *>
(RISCV_get_service_iface(socInfo_.to_string(),
IFACE_SOC_INFO));
 
// Core commands registration:
registerCommand(new CmdBr(itap_, info_));
registerCommand(new CmdBusUtil(itap_, info_));
registerCommand(new CmdCpi(itap_, info_));
registerCommand(new CmdCsr(itap_, info_));
registerCommand(new CmdDisas(itap_, info_));
registerCommand(new CmdExit(itap_, info_));
registerCommand(new CmdHalt(itap_, info_));
registerCommand(new CmdIsRunning(itap_, info_));
registerCommand(new CmdLoadElf(itap_, info_));
registerCommand(new CmdLog(itap_, info_));
registerCommand(new CmdMemDump(itap_, info_));
registerCommand(new CmdRead(itap_, info_));
registerCommand(new CmdRun(itap_, info_));
registerCommand(new CmdReg(itap_, info_));
registerCommand(new CmdRegs(itap_, info_));
registerCommand(new CmdReset(itap_, info_));
registerCommand(new CmdStack(itap_, info_));
registerCommand(new CmdStatus(itap_, info_));
registerCommand(new CmdSymb(itap_, info_));
registerCommand(new CmdWrite(itap_, info_));
}
 
void CmdExecutor::registerCommand(ICommand *icmd) {
AttributeType t1(icmd);
cmds_.add_to_list(&t1);
}
 
void CmdExecutor::unregisterCommand(ICommand *icmd) {
for (unsigned i = 0; i < cmds_.size(); i++) {
if (cmds_[i].to_iface() == icmd) {
cmds_.remove_from_list(i);
break;
}
}
}
 
void CmdExecutor::exec(const char *line, AttributeType *res, bool silent) {
RISCV_mutex_lock(&mutexExec_);
res->make_nil();
 
AttributeType cmd;
if (line[0] == '[' || line[0] == '}') {
cmd.from_config(line);
} else {
cmd.make_string(line);
}
 
AttributeType listArgs(Attr_List), *cmd_parsed;
if (cmd.is_string()) {
splitLine(const_cast<char *>(cmd.to_string()), &listArgs);
cmd_parsed = &listArgs;
} else {
cmd_parsed = &cmd;
}
processSimple(cmd_parsed, res);
 
RISCV_mutex_unlock(&mutexExec_);
 
/** Do not output any information into console in silent mode: */
if (silent) {
return;
}
//RISCV_printf0("%s", outbuf_);
}
 
void CmdExecutor::commands(const char *substr, AttributeType *res) {
if (!res->is_list()) {
res->make_list(0);
}
AttributeType item;
item.make_list(3);
for (unsigned i = 0; i < cmds_.size(); i++) {
ICommand *icmd = static_cast<ICommand *>(cmds_[i].to_iface());
if (strstr(icmd->cmdName(), substr)) {
item[0u].make_string(icmd->cmdName());
item[1].make_string(icmd->briefDescr());
item[2].make_string(icmd->detailedDescr());
res->add_to_list(&item);
}
}
}
 
void CmdExecutor::processSimple(AttributeType *cmd, AttributeType *res) {
outbuf_[outbuf_cnt_ = 0] = '\0';
if (cmd->size() == 0) {
return;
}
 
ICommand *icmd;
if (!(*cmd)[0u].is_string()) {
RISCV_error("Wrong command format", NULL);
return;
}
 
if ((*cmd)[0u].is_equal("help")) {
if (cmd->size() == 1) {
RISCV_printf0("** List of supported commands: **", NULL);
for (unsigned i = 0; i < cmds_.size(); i++) {
icmd = static_cast<ICommand *>(cmds_[i].to_iface());
RISCV_printf0("%13s - %s",
icmd->cmdName(), icmd->briefDescr());
}
} else {
const char *helpcmd = (*cmd)[1].to_string();
icmd = getICommand(helpcmd);
if (icmd) {
RISCV_printf0("\n%s", icmd->detailedDescr());
} else {
RISCV_error("Command '%s' not found", helpcmd);
}
}
return;
}
 
AttributeType u;
icmd = getICommand(cmd);
if (!icmd) {
RISCV_error("Command '%s' not found. Use 'help' to list commands",
(*cmd)[0u].to_string());
return;
}
icmd->exec(cmd, res);
 
if (cmdIsError(res)) {
RISCV_error("Command '%s' error: '%s'",
(*res)[1].to_string(), (*res)[2].to_string());
}
}
 
bool CmdExecutor::cmdIsError(AttributeType *res) {
if (!res->is_list() || res->size() != 3) {
return false;
}
if (!(*res)[0u].is_string()) {
return false;
}
return (*res)[0u].is_equal("ERROR");
}
 
ICommand *CmdExecutor::getICommand(AttributeType *args) {
ICommand *ret = 0;
for (unsigned i = 0; i < cmds_.size(); i++) {
ret = static_cast<ICommand *>(cmds_[i].to_iface());
if (ret && (ret->isValid(args) == CMD_VALID)) {
return ret;
}
}
return 0;
}
 
ICommand *CmdExecutor::getICommand(const char *name) {
ICommand *ret = 0;
for (unsigned i = 0; i < cmds_.size(); i++) {
ret = static_cast<ICommand *>(cmds_[i].to_iface());
if (ret && strcmp(ret->cmdName(), name) == 0) {
return ret;
}
}
return 0;
}
 
void CmdExecutor::splitLine(char *str, AttributeType *listArgs) {
char *end = str;
bool last = false;
bool inside_string = false;
char string_marker;
while (*str) {
if (*end == '\0') {
last = true;
} else if (*end == ' ' && !inside_string) {
*end = '\0';
while (*(end + 1) == ' ') {
*(++end) = '\0';
}
} else if (!inside_string && (*end == '"' || *end == '\'')) {
inside_string = true;
string_marker = *end;
} else if (inside_string && string_marker == *end) {
inside_string = false;
}
 
if (*end == '\0') {
AttributeType item;
if ((str[0] >= '0' && str[0] <= '9')
|| (str[0] == '[') || (str[0] == '"') || (str[0] == '\'')
|| (str[0] == '{') || (str[0] == '(')) {
item.from_config(str);
} else {
item.make_string(str);
}
listArgs->add_to_list(&item);
if (!last) {
splitLine(end + 1, listArgs);
}
break;
}
++end;
}
}
 
int CmdExecutor::outf(const char *fmt, ...) {
if (outbuf_cnt_ > (outbuf_size_ - 128)) {
char *t = new char [2*outbuf_size_];
memcpy(t, outbuf_, outbuf_size_);
delete [] outbuf_;
outbuf_size_ *= 2;
outbuf_ = t;
}
va_list arg;
va_start(arg, fmt);
outbuf_cnt_ += vsprintf(&outbuf_[outbuf_cnt_], fmt, arg);
va_end(arg);
return outbuf_cnt_;
}
 
} // namespace debugger
/cmdexec.h
1,70 → 1,70
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Command Executor declaration.
*/
 
#ifndef __DEBUGGER_CMDEXECUTOR_H__
#define __DEBUGGER_CMDEXECUTOR_H__
 
#include "iclass.h"
#include "iservice.h"
#include "coreservices/icmdexec.h"
#include "coreservices/itap.h"
#include "coreservices/iautocomplete.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include <string>
#include <stdarg.h>
 
namespace debugger {
 
class CmdExecutor : public IService,
public ICmdExecutor {
public:
explicit CmdExecutor(const char *name);
virtual ~CmdExecutor();
 
/** IService interface */
virtual void postinitService();
 
/** ICmdExecutor */
virtual void registerCommand(ICommand *icmd);
virtual void unregisterCommand(ICommand *icmd);
virtual void exec(const char *line, AttributeType *res, bool silent);
virtual void commands(const char *substr, AttributeType *res);
 
private:
void processSimple(AttributeType *cmd, AttributeType *res);
void processScript(AttributeType *cmd, AttributeType *res);
void splitLine(char *str, AttributeType *listArgs);
 
int outf(const char *fmt, ...);
bool cmdIsError(AttributeType *res);
ICommand *getICommand(AttributeType *args);
ICommand *getICommand(const char *name);
 
private:
AttributeType tap_;
AttributeType socInfo_;
AttributeType cmds_;
 
ITap *itap_;
ISocInfo *info_;
 
mutex_def mutexExec_;
 
char cmdbuf_[4096];
char *outbuf_;
int outbuf_size_;
int outbuf_cnt_;
uint8_t *tmpbuf_;
int tmpbuf_size_;
};
 
DECLARE_CLASS(CmdExecutor)
 
} // namespace debugger
 
#endif // __DEBUGGER_CMDEXECUTOR_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Command Executor declaration.
*/
 
#ifndef __DEBUGGER_CMDEXECUTOR_H__
#define __DEBUGGER_CMDEXECUTOR_H__
 
#include "iclass.h"
#include "iservice.h"
#include "coreservices/icmdexec.h"
#include "coreservices/itap.h"
#include "coreservices/iautocomplete.h"
#include "coreservices/isocinfo.h"
#include "coreservices/icommand.h"
#include <string>
#include <stdarg.h>
 
namespace debugger {
 
class CmdExecutor : public IService,
public ICmdExecutor {
public:
explicit CmdExecutor(const char *name);
virtual ~CmdExecutor();
 
/** IService interface */
virtual void postinitService();
 
/** ICmdExecutor */
virtual void registerCommand(ICommand *icmd);
virtual void unregisterCommand(ICommand *icmd);
virtual void exec(const char *line, AttributeType *res, bool silent);
virtual void commands(const char *substr, AttributeType *res);
 
private:
void processSimple(AttributeType *cmd, AttributeType *res);
void processScript(AttributeType *cmd, AttributeType *res);
void splitLine(char *str, AttributeType *listArgs);
 
int outf(const char *fmt, ...);
bool cmdIsError(AttributeType *res);
ICommand *getICommand(AttributeType *args);
ICommand *getICommand(const char *name);
 
private:
AttributeType tap_;
AttributeType socInfo_;
AttributeType cmds_;
 
ITap *itap_;
ISocInfo *info_;
 
mutex_def mutexExec_;
 
char cmdbuf_[4096];
char *outbuf_;
int outbuf_size_;
int outbuf_cnt_;
uint8_t *tmpbuf_;
int tmpbuf_size_;
};
 
DECLARE_CLASS(CmdExecutor)
 
} // namespace debugger
 
#endif // __DEBUGGER_CMDEXECUTOR_H__

powered by: WebSVN 2.1.0

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