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__ |