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/socsim_plugin
- from Rev 2 to Rev 4
- ↔ Reverse comparison
Rev 2 → Rev 4
/dsu.cpp
File deleted
/greth.cpp
File deleted
/dsu.h
File deleted
/greth.h
File deleted
/boardsim.cpp
1,21 → 1,21
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the FPGA board with Ethernet UDP/EDCL interface. |
*/ |
|
#include "api_core.h" |
#include "boardsim.h" |
|
namespace debugger { |
|
BoardSim::BoardSim(const char *name) : IService(name) { |
registerInterface(static_cast<IBoardSim *>(this)); |
} |
|
void BoardSim::postinitService() { |
} |
|
} // namespace debugger |
|
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the FPGA board with Ethernet UDP/EDCL interface. |
*/ |
|
#include "api_core.h" |
#include "boardsim.h" |
|
namespace debugger { |
|
BoardSim::BoardSim(const char *name) : IService(name) { |
registerInterface(static_cast<IBoardSim *>(this)); |
} |
|
void BoardSim::postinitService() { |
} |
|
} // namespace debugger |
|
/boardsim.h
1,35 → 1,35
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the Hardware interface. |
*/ |
|
#ifndef __DEBUGGER_BOARDSIM_H__ |
#define __DEBUGGER_BOARDSIM_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "iboardsim.h" |
|
namespace debugger { |
|
class BoardSim : public IService, |
public IBoardSim { |
public: |
BoardSim(const char *name); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** @name IBoardSim interface */ |
virtual void getInfo(AttributeType *attr) {} |
|
private: |
}; |
|
DECLARE_CLASS(BoardSim) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_BOARDSIM_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the Hardware interface. |
*/ |
|
#ifndef __DEBUGGER_BOARDSIM_H__ |
#define __DEBUGGER_BOARDSIM_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "iboardsim.h" |
|
namespace debugger { |
|
class BoardSim : public IService, |
public IBoardSim { |
public: |
BoardSim(const char *name); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** @name IBoardSim interface */ |
virtual void getInfo(AttributeType *attr) {} |
|
private: |
}; |
|
DECLARE_CLASS(BoardSim) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_BOARDSIM_H__ |
/fifo.h
1,69 → 1,69
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief FIFO implementation. |
*/ |
|
#ifndef __DEBUGGER_FIFO_H__ |
#define __DEBUGGER_FIFO_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
template<class T> class TFifo { |
public: |
TFifo(int sz) { |
arr_ = new T[size_ = sz]; |
prd_ = &arr_[0]; |
pwr_ = &arr_[1]; |
} |
~TFifo() { |
delete [] arr_; |
} |
bool isFull() { |
return pwr_ == prd_; |
} |
bool isEmpty() { |
if (pwr_ == (prd_ + 1)) { |
return true; |
} |
if ((prd_ - pwr_ + 1) == size_) { |
return true; |
} |
return false; |
} |
void get(T *out) { |
if (isEmpty()) { |
return; |
} |
if (prd_ >= &arr_[size_ - 1]) { |
*out = arr_[0]; |
prd_ = arr_; |
} else { |
*out = prd_[1]; |
prd_++; |
} |
} |
void put(T *in) { |
if (isFull()) { |
return; |
} |
*pwr_ = *in; |
if (pwr_ >= &arr_[size_ - 1]) { |
pwr_ = arr_; |
} else { |
pwr_++; |
} |
} |
private: |
T *arr_; |
T *prd_; |
T *pwr_; |
int size_; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_FIFO_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief FIFO implementation. |
*/ |
|
#ifndef __DEBUGGER_FIFO_H__ |
#define __DEBUGGER_FIFO_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
template<class T> class TFifo { |
public: |
TFifo(int sz) { |
arr_ = new T[size_ = sz]; |
prd_ = &arr_[0]; |
pwr_ = &arr_[1]; |
} |
~TFifo() { |
delete [] arr_; |
} |
bool isFull() { |
return pwr_ == prd_; |
} |
bool isEmpty() { |
if (pwr_ == (prd_ + 1)) { |
return true; |
} |
if ((prd_ - pwr_ + 1) == size_) { |
return true; |
} |
return false; |
} |
void get(T *out) { |
if (isEmpty()) { |
return; |
} |
if (prd_ >= &arr_[size_ - 1]) { |
*out = arr_[0]; |
prd_ = arr_; |
} else { |
*out = prd_[1]; |
prd_++; |
} |
} |
void put(T *in) { |
if (isFull()) { |
return; |
} |
*pwr_ = *in; |
if (pwr_ >= &arr_[size_ - 1]) { |
pwr_ = arr_; |
} else { |
pwr_++; |
} |
} |
private: |
T *arr_; |
T *prd_; |
T *pwr_; |
int size_; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_FIFO_H__ |
/fsev2.cpp
1,55 → 1,51
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Fast Search Engnine (FSE) black-box model. |
*/ |
|
#include "api_core.h" |
#include "fsev2.h" |
|
namespace debugger { |
|
static const uint32_t FSE2_CONTROL_ENA = (1 << 31); // 0=disable; 1=enable |
static const uint32_t FSE2_CONTROL_ADC = (1 << 30); // 0=bin offset; 1=sign/magn |
static const uint32_t FSE2_STATE_NXT_DOPLER = (1 << 21); |
static const uint32_t FSE2_STATE_PROCESSING = (1 << 20); |
static const uint32_t FSE2_STATE_SELCHAN = (1 << 19); |
static const uint32_t FSE2_STATE_WRITING = (1 << 18); |
static const uint32_t FSE2_STATE_WAIT_MS = (1 << 17); |
static const uint32_t FSE2_STATE_IDLE = (1 << 16); |
|
FseV2::FseV2(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.hw_id = (16 << 16) | 5; // 16 msec accum, 5=id |
for (int i = 0; i < FSE2_CHAN_MAX; i++) { |
regs_.chan[i].dopler = 1000 << 4; |
regs_.chan[i].noise = 1872 << 12; |
regs_.chan[i].ind = 100 + i; |
} |
// Check float comparision with threshold (=2.1*noise): |
regs_.chan[14].max = static_cast<uint32_t>(1872.0 * 2.11); |
regs_.chan[15].max = static_cast<uint32_t>(1872.0 * 2.09); |
} |
|
void FseV2::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
memcpy(&reinterpret_cast<uint8_t *>(®s_)[off], trans->wpayload.b8, |
trans->xsize); |
} else { |
memcpy(trans->rpayload.b8, &reinterpret_cast<uint8_t *>(®s_)[off], |
trans->xsize); |
} |
} |
|
} // namespace debugger |
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Fast Search Engnine (FSE) black-box model. |
*/ |
|
#include "api_core.h" |
#include "fsev2.h" |
|
namespace debugger { |
|
static const uint32_t FSE2_CONTROL_ENA = (1 << 31); // 0=disable; 1=enable |
static const uint32_t FSE2_CONTROL_ADC = (1 << 30); // 0=bin offset; 1=sign/magn |
static const uint32_t FSE2_STATE_NXT_DOPLER = (1 << 21); |
static const uint32_t FSE2_STATE_PROCESSING = (1 << 20); |
static const uint32_t FSE2_STATE_SELCHAN = (1 << 19); |
static const uint32_t FSE2_STATE_WRITING = (1 << 18); |
static const uint32_t FSE2_STATE_WAIT_MS = (1 << 17); |
static const uint32_t FSE2_STATE_IDLE = (1 << 16); |
|
FseV2::FseV2(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.hw_id = (16 << 16) | 5; // 16 msec accum, 5=id |
for (int i = 0; i < FSE2_CHAN_MAX; i++) { |
regs_.chan[i].dopler = 1000 << 4; |
regs_.chan[i].noise = 1872 << 12; |
regs_.chan[i].ind = 100 + i; |
} |
// Check float comparision with threshold (=2.1*noise): |
regs_.chan[14].max = static_cast<uint32_t>(1872.0 * 2.11); |
regs_.chan[15].max = static_cast<uint32_t>(1872.0 * 2.09); |
} |
|
ETransStatus FseV2::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
memcpy(&reinterpret_cast<uint8_t *>(®s_)[off], trans->wpayload.b8, |
trans->xsize); |
} else { |
memcpy(trans->rpayload.b8, &reinterpret_cast<uint8_t *>(®s_)[off], |
trans->xsize); |
} |
return TRANS_OK; |
} |
|
} // namespace debugger |
/fsev2.h
1,67 → 1,57
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Fast Search Engnine (FSE) black-box model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
|
namespace debugger { |
|
class FseV2 : public IService, |
public IMemoryOperation { |
public: |
FseV2(const char *name); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
|
static const int FSE2_CHAN_MAX = 32; |
|
struct fsev2_chan_fields { |
volatile uint32_t common;//prn, acc_ms, carr_steps, coh_ena |
volatile int32_t carr_nco_f0; |
volatile int32_t carr_nco_dlt; |
volatile int32_t carr_nco_letter; |
volatile uint32_t max; |
volatile uint32_t ind; |
volatile uint32_t noise; |
volatile int32_t dopler; |
}; |
|
struct fsev2_map { |
fsev2_chan_fields chan[FSE2_CHAN_MAX]; |
|
volatile uint32_t hw_id; // msec ram capacity and hw_id |
volatile uint32_t control; |
volatile uint32_t ms_marker; |
volatile uint32_t carr_nco_th; |
volatile uint32_t code_nco_th; |
volatile int32_t carr_nco_if; |
volatile uint32_t code_nco; |
uint32_t reserved; |
} regs_; |
}; |
|
DECLARE_CLASS(FseV2) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Fast Search Engnine (FSE) black-box model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
|
namespace debugger { |
|
class FseV2 : public IService, |
public IMemoryOperation { |
public: |
FseV2(const char *name); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
private: |
static const int FSE2_CHAN_MAX = 32; |
|
struct fsev2_chan_fields { |
volatile uint32_t common;//prn, acc_ms, carr_steps, coh_ena |
volatile int32_t carr_nco_f0; |
volatile int32_t carr_nco_dlt; |
volatile int32_t carr_nco_letter; |
volatile uint32_t max; |
volatile uint32_t ind; |
volatile uint32_t noise; |
volatile int32_t dopler; |
}; |
|
struct fsev2_map { |
fsev2_chan_fields chan[FSE2_CHAN_MAX]; |
|
volatile uint32_t hw_id; // msec ram capacity and hw_id |
volatile uint32_t control; |
volatile uint32_t ms_marker; |
volatile uint32_t carr_nco_th; |
volatile uint32_t code_nco_th; |
volatile int32_t carr_nco_if; |
volatile uint32_t code_nco; |
uint32_t reserved; |
} regs_; |
}; |
|
DECLARE_CLASS(FseV2) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_FSEV2_H__ |
/gnss_stub.cpp
1,89 → 1,83
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GNSS stub module functional model. |
*/ |
|
#include "api_core.h" |
#include "gnss_stub.h" |
|
namespace debugger { |
|
GNSSStub::GNSSStub(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<IClockListener *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("IrqLine", &irqLine_); |
registerAttribute("IrqControl", &irqctrl_); |
registerAttribute("ClkSource", &clksrc_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
irqLine_.make_uint64(0); |
irqctrl_.make_string(""); |
clksrc_.make_string(""); |
|
memset(®s_, 0, sizeof(regs_)); |
|
regs_.misc.GenericChanCfg = 12; // [4:0] gps |
regs_.misc.GenericChanCfg |= 12 << 5; // [8:5] glo |
regs_.misc.GenericChanCfg |= 2 << 9; // [10:9] sbas |
regs_.misc.GenericChanCfg |= 6 << 11; // [14:11] gal |
} |
|
GNSSStub::~GNSSStub() { |
} |
|
void GNSSStub::postinitService() { |
iclk_ = static_cast<IClock *>( |
RISCV_get_service_iface(clksrc_.to_string(), IFACE_CLOCK)); |
if (!iclk_) { |
RISCV_error("Can't find IClock interface %s", clksrc_.to_string()); |
} |
|
iwire_ = static_cast<IWire *>( |
RISCV_get_service_iface(irqctrl_.to_string(), IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_.to_string()); |
} |
} |
|
void GNSSStub::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (((trans->wstrb >> 4*i) & 0xf) == 0) { |
continue; |
} |
if (regs_.tmr.rw_MsLength == 0 && trans->wpayload.b32[i] != 0) { |
iclk_->registerStepCallback( |
static_cast<IClockListener *>(this), |
iclk_->getStepCounter() + trans->wpayload.b32[i]); |
} |
regs_.tmr.rw_MsLength = trans->wpayload.b32[i]; |
if ((off + 4*i) == OFFSET(®s_.tmr.rw_MsLength)) { |
RISCV_info("Set rw_MsLength = %d", regs_.tmr.rw_MsLength); |
} |
} |
} else { |
uint8_t *m = reinterpret_cast<uint8_t *>(®s_); |
memcpy(trans->rpayload.b8, &m[off], trans->xsize); |
} |
} |
|
void GNSSStub::stepCallback(uint64_t t) { |
iwire_->raiseLine(irqLine_.to_int()); |
if (regs_.tmr.rw_MsLength) { |
regs_.tmr.rw_tow++; |
regs_.tmr.rw_tod++; |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), |
t + regs_.tmr.rw_MsLength); |
} |
} |
|
} // namespace debugger |
|
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GNSS stub module functional model. |
*/ |
|
#include "api_core.h" |
#include "gnss_stub.h" |
|
namespace debugger { |
|
GNSSStub::GNSSStub(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<IClockListener *>(this)); |
registerAttribute("IrqControl", &irqctrl_); |
registerAttribute("ClkSource", &clksrc_); |
|
memset(®s_, 0, sizeof(regs_)); |
|
regs_.misc.GenericChanCfg = 12; // [4:0] gps |
regs_.misc.GenericChanCfg |= 12 << 5; // [8:5] glo |
regs_.misc.GenericChanCfg |= 2 << 9; // [10:9] sbas |
regs_.misc.GenericChanCfg |= 6 << 11; // [14:11] gal |
} |
|
GNSSStub::~GNSSStub() { |
} |
|
void GNSSStub::postinitService() { |
iclk_ = static_cast<IClock *>( |
RISCV_get_service_iface(clksrc_.to_string(), IFACE_CLOCK)); |
if (!iclk_) { |
RISCV_error("Can't find IClock interface %s", clksrc_.to_string()); |
} |
|
iwire_ = static_cast<IWire *>( |
RISCV_get_service_port_iface(irqctrl_[0u].to_string(), |
irqctrl_[1].to_string(), |
IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_[0u].to_string()); |
} |
} |
|
ETransStatus GNSSStub::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (((trans->wstrb >> 4*i) & 0xf) == 0) { |
continue; |
} |
if (regs_.tmr.rw_MsLength == 0 && trans->wpayload.b32[i] != 0) { |
iclk_->registerStepCallback( |
static_cast<IClockListener *>(this), |
iclk_->getStepCounter() + trans->wpayload.b32[i]); |
} |
regs_.tmr.rw_MsLength = trans->wpayload.b32[i]; |
if ((off + 4*i) == OFFSET(®s_.tmr.rw_MsLength)) { |
RISCV_info("Set rw_MsLength = %d", regs_.tmr.rw_MsLength); |
} |
} |
} else { |
uint8_t *m = reinterpret_cast<uint8_t *>(®s_); |
memcpy(trans->rpayload.b8, &m[off], trans->xsize); |
} |
return TRANS_OK; |
} |
|
void GNSSStub::stepCallback(uint64_t t) { |
iwire_->raiseLine(); |
if (regs_.tmr.rw_MsLength) { |
regs_.tmr.rw_tow++; |
regs_.tmr.rw_tod++; |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), |
t + regs_.tmr.rw_MsLength); |
} |
} |
|
} // namespace debugger |
|
/gnss_stub.h
1,84 → 1,74
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GNSS stub module functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iclklistener.h" |
#include "coreservices/iclock.h" |
#include "coreservices/iwire.h" |
|
namespace debugger { |
|
class GNSSStub : public IService, |
public IMemoryOperation, |
public IClockListener { |
public: |
GNSSStub(const char *name); |
~GNSSStub(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
/** IClockListener */ |
virtual void stepCallback(uint64_t t); |
|
private: |
uint64_t OFFSET(void *addr) { |
return reinterpret_cast<uint64_t>(addr) |
- reinterpret_cast<uint64_t>(®s_); |
} |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType irqLine_; |
AttributeType irqctrl_; |
AttributeType clksrc_; |
IWire *iwire_; |
IClock *iclk_; |
|
typedef struct MiscType { |
volatile uint32_t Date; |
volatile uint32_t GenericChanCfg; |
uint64_t hide[7]; |
} MiscType; |
|
typedef struct TimerType { |
uint32_t rw_MsLength; |
uint32_t r_MsCnt; |
int32_t rw_tow; |
int32_t rw_tod; |
uint32_t unused[12]; |
} TimerType; |
|
struct gnss_map { |
MiscType misc; |
TimerType tmr; |
uint64_t noise[8]; |
uint64_t chan[256*8]; |
} regs_; |
}; |
|
DECLARE_CLASS(GNSSStub) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GNSS stub module functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iclklistener.h" |
#include "coreservices/iclock.h" |
#include "coreservices/iwire.h" |
|
namespace debugger { |
|
class GNSSStub : public IService, |
public IMemoryOperation, |
public IClockListener { |
public: |
GNSSStub(const char *name); |
~GNSSStub(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
/** IClockListener */ |
virtual void stepCallback(uint64_t t); |
|
private: |
uint64_t OFFSET(void *addr) { |
return reinterpret_cast<uint64_t>(addr) |
- reinterpret_cast<uint64_t>(®s_); |
} |
|
private: |
AttributeType irqctrl_; |
AttributeType clksrc_; |
IWire *iwire_; |
IClock *iclk_; |
|
typedef struct MiscType { |
volatile uint32_t Date; |
volatile uint32_t GenericChanCfg; |
uint64_t hide[7]; |
} MiscType; |
|
typedef struct TimerType { |
uint32_t rw_MsLength; |
uint32_t r_MsCnt; |
int32_t rw_tow; |
int32_t rw_tod; |
uint32_t unused[12]; |
} TimerType; |
|
struct gnss_map { |
MiscType misc; |
TimerType tmr; |
uint64_t noise[8]; |
uint64_t chan[256*8]; |
} regs_; |
}; |
|
DECLARE_CLASS(GNSSStub) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GNSS_STUB_H__ |
/gpio.cpp
1,82 → 1,66
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GPIO functional model. |
*/ |
|
#include "api_core.h" |
#include "gpio.h" |
#include "coreservices/isignallistener.h" |
|
namespace debugger { |
|
GPIO::GPIO(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<ISignal *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("DIP", &dip_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
dip_.make_uint64(0); |
|
listOfListerners_.make_list(0); |
|
memset(®s_, 0, sizeof(regs_)); |
} |
|
GPIO::~GPIO() { |
} |
|
void GPIO::postinitService() { |
regs_.dip = static_cast<uint32_t>(dip_.to_uint64()); |
} |
|
void GPIO::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
uint32_t *mem_ = reinterpret_cast<uint32_t *>(®s_); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (trans->wstrb & (0xf << 4*i)) { |
mem_[off + i] = trans->wpayload.b32[i]; |
} |
|
if (off + i == (reinterpret_cast<uint64_t>(®s_.led) |
- reinterpret_cast<uint64_t>(®s_))) { |
ISignalListener *ilistener; |
for (unsigned n = 0; n < listOfListerners_.size(); n++) { |
ilistener = static_cast<ISignalListener *>( |
listOfListerners_[n].to_iface()); |
ilistener->updateSignal(0, 8, regs_.led & 0xFF); |
} |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
trans->rpayload.b32[i] = mem_[i + off]; |
} |
} |
} |
|
void GPIO::setLevel(int start, int width, uint64_t value) { |
uint64_t t = value >> start; |
uint64_t msk = (1LL << width) - 1; |
uint64_t prev = dip_.to_uint64() & ~(msk << start); |
t &= msk; |
dip_.make_uint64(prev | (t << start)); |
RISCV_info("set level pins[%d:%d] <= %" RV_PRI64 "x", start - 1, width, t); |
} |
|
void GPIO::registerSignalListener(IFace *listener) { |
AttributeType t(listener); |
listOfListerners_.add_to_list(&t); |
} |
|
void GPIO::unregisterSignalListener(IFace *listener) { |
} |
|
} // namespace debugger |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GPIO functional model. |
*/ |
|
#include "api_core.h" |
#include "gpio.h" |
|
namespace debugger { |
|
GPIO::GPIO(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<IWire *>(this)); |
registerAttribute("DIP", &dip_); |
|
memset(®s_, 0, sizeof(regs_)); |
} |
|
GPIO::~GPIO() { |
} |
|
void GPIO::postinitService() { |
regs_.dip = static_cast<uint32_t>(dip_.to_uint64()); |
} |
|
ETransStatus GPIO::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
uint32_t *mem_ = reinterpret_cast<uint32_t *>(®s_); |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (trans->wstrb & (0xf << 4*i)) { |
mem_[off + i] = trans->wpayload.b32[i]; |
} |
|
if (off + i == (reinterpret_cast<uint64_t>(®s_.led) |
- reinterpret_cast<uint64_t>(®s_))) { |
/*ISignalListener *ilistener; |
for (unsigned n = 0; n < listOfListerners_.size(); n++) { |
ilistener = static_cast<ISignalListener *>( |
listOfListerners_[n].to_iface()); |
ilistener->updateSignal(0, 8, regs_.led & 0xFF); |
}*/ |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
trans->rpayload.b32[i] = mem_[i + off]; |
} |
} |
return TRANS_OK; |
} |
|
/*void GPIO::setLevel(int start, int width, uint64_t value) { |
uint64_t t = value >> start; |
uint64_t msk = (1LL << width) - 1; |
uint64_t prev = dip_.to_uint64() & ~(msk << start); |
t &= msk; |
dip_.make_uint64(prev | (t << start)); |
RISCV_info("set level pins[%d:%d] <= %" RV_PRI64 "x", start - 1, width, t); |
}*/ |
|
} // namespace debugger |
/gpio.h
1,65 → 1,55
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GPIO functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/isignal.h" |
|
namespace debugger { |
|
class GPIO : public IService, |
public IMemoryOperation, |
public ISignal { |
public: |
GPIO(const char *name); |
~GPIO(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
/** ISignal interface */ |
virtual void setLevel(int start, int width, uint64_t value); |
virtual void registerSignalListener(IFace *listener); |
virtual void unregisterSignalListener(IFace *listener); |
|
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType dip_; |
AttributeType listOfListerners_; |
|
struct gpio_map { |
volatile uint32_t led; |
volatile uint32_t dip; |
volatile uint32_t reg2; |
volatile uint32_t reg3; |
volatile uint32_t led_period; |
volatile uint32_t reg5; |
volatile uint32_t reg6; |
} regs_; |
}; |
|
DECLARE_CLASS(GPIO) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief GPIO functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iwire.h" |
|
namespace debugger { |
|
class GPIO : public IService, |
public IMemoryOperation, |
public IWire { |
public: |
GPIO(const char *name); |
~GPIO(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
/** IWire interface */ |
virtual void raiseLine() {} |
virtual void lowerLine() {} |
virtual void setLevel(bool level) {} |
virtual bool getLevel() { return 0; } |
|
private: |
AttributeType dip_; |
|
struct gpio_map { |
volatile uint32_t led; |
volatile uint32_t dip; |
volatile uint32_t reg2; |
volatile uint32_t reg3; |
volatile uint32_t led_period; |
volatile uint32_t reg5; |
volatile uint32_t reg6; |
} regs_; |
}; |
|
DECLARE_CLASS(GPIO) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GPIO_H__ |
/gptimers.cpp
1,136 → 1,131
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief General Purpose Timers model. |
*/ |
|
#include "api_core.h" |
#include "gptimers.h" |
|
namespace debugger { |
|
GPTimers::GPTimers(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("IrqLine", &irqLine_); |
registerAttribute("IrqControl", &irqctrl_); |
registerAttribute("ClkSource", &clksrc_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
irqLine_.make_uint64(0); |
irqctrl_.make_string(""); |
clksrc_.make_string(""); |
|
|
memset(®s_, 0, sizeof(regs_)); |
} |
|
GPTimers::~GPTimers() { |
} |
|
void GPTimers::postinitService() { |
iclk_ = static_cast<IClock *>( |
RISCV_get_service_iface(clksrc_.to_string(), IFACE_CLOCK)); |
if (!iclk_) { |
RISCV_error("Can't find IClock interface %s", clksrc_.to_string()); |
} |
|
iwire_ = static_cast<IWire *>( |
RISCV_get_service_iface(irqctrl_.to_string(), IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_.to_string()); |
} |
} |
|
void GPTimers::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case 0: |
break; |
case 1: |
break; |
case 2: |
regs_.pending = trans->wpayload.b32[i]; |
RISCV_info("Set pending = %08x", trans->wpayload.b32[i]); |
break; |
case 16 + 0: |
regs_.timer[0].control = trans->wpayload.b32[i]; |
if (regs_.timer[0].control & TIMER_CONTROL_ENA) { |
iclk_->registerStepCallback( |
static_cast<IClockListener *>(this), |
iclk_->getStepCounter() + regs_.timer[0].init_value); |
} |
RISCV_info("Set [0].control = %08x", trans->wpayload.b32[i]); |
break; |
case 16 + 2: |
regs_.timer[0].cur_value &= ~0xFFFFFFFFLL; |
regs_.timer[0].cur_value |= trans->wpayload.b32[i]; |
RISCV_info("Set cur_value[31:0] = %x", trans->wpayload.b32[i]); |
break; |
case 16 + 3: |
regs_.timer[0].cur_value &= ~0xFFFFFFFF00000000LL; |
regs_.timer[0].cur_value |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set cur_value[63:32] = %x", |
trans->wpayload.b32[i]); |
break; |
case 16 + 4: |
regs_.timer[0].init_value &= ~0xFFFFFFFFLL; |
regs_.timer[0].init_value |= trans->wpayload.b32[i]; |
RISCV_info("Set init_value[31:0] = %x", |
trans->wpayload.b32[i]); |
break; |
case 16 + 5: |
regs_.timer[0].init_value &= ~0xFFFFFFFF00000000LL; |
regs_.timer[0].init_value |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set init_value[63:32] = %x", |
trans->wpayload.b32[i]); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
regs_.highcnt = iclk_->getStepCounter(); |
trans->rpayload.b32[i] = static_cast<uint32_t>(regs_.highcnt); |
break; |
case 1: |
regs_.highcnt = iclk_->getStepCounter(); |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.highcnt >> 32); |
break; |
case 16 + 0: |
trans->rpayload.b32[i] = regs_.timer[0].control; |
RISCV_info("Get [0].control = %08x", trans->rpayload.b32[i]); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
} |
|
void GPTimers::stepCallback(uint64_t t) { |
iwire_->raiseLine(irqLine_.to_int()); |
if (regs_.timer[0].control & TIMER_CONTROL_ENA) { |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), |
t + regs_.timer[0].init_value); |
} |
} |
|
|
} // namespace debugger |
|
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief General Purpose Timers model. |
*/ |
|
#include "api_core.h" |
#include "gptimers.h" |
|
namespace debugger { |
|
GPTimers::GPTimers(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("IrqControl", &irqctrl_); |
registerAttribute("ClkSource", &clksrc_); |
|
memset(®s_, 0, sizeof(regs_)); |
dbg_irq_cnt_ = 0; |
} |
|
GPTimers::~GPTimers() { |
} |
|
void GPTimers::postinitService() { |
iclk_ = static_cast<IClock *>( |
RISCV_get_service_iface(clksrc_.to_string(), IFACE_CLOCK)); |
if (!iclk_) { |
RISCV_error("Can't find IClock interface %s", clksrc_.to_string()); |
} |
|
iwire_ = static_cast<IWire *>( |
RISCV_get_service_port_iface(irqctrl_[0u].to_string(), |
irqctrl_[1].to_string(), |
IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_[0u].to_string()); |
} |
} |
|
ETransStatus GPTimers::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case 0: |
break; |
case 1: |
break; |
case 2: |
regs_.pending = trans->wpayload.b32[i]; |
RISCV_info("Set pending = %08x", trans->wpayload.b32[i]); |
break; |
case 16 + 0: |
regs_.timer[0].control = trans->wpayload.b32[i]; |
if (regs_.timer[0].control & TIMER_CONTROL_ENA) { |
iclk_->registerStepCallback( |
static_cast<IClockListener *>(this), |
iclk_->getStepCounter() + regs_.timer[0].init_value); |
} |
RISCV_info("Set [0].control = %08x", trans->wpayload.b32[i]); |
break; |
case 16 + 2: |
regs_.timer[0].cur_value &= ~0xFFFFFFFFLL; |
regs_.timer[0].cur_value |= trans->wpayload.b32[i]; |
RISCV_info("Set cur_value[31:0] = %x", trans->wpayload.b32[i]); |
break; |
case 16 + 3: |
regs_.timer[0].cur_value &= ~0xFFFFFFFF00000000LL; |
regs_.timer[0].cur_value |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set cur_value[63:32] = %x", |
trans->wpayload.b32[i]); |
break; |
case 16 + 4: |
regs_.timer[0].init_value &= ~0xFFFFFFFFLL; |
regs_.timer[0].init_value |= trans->wpayload.b32[i]; |
RISCV_info("Set init_value[31:0] = %x", |
trans->wpayload.b32[i]); |
break; |
case 16 + 5: |
regs_.timer[0].init_value &= ~0xFFFFFFFF00000000LL; |
regs_.timer[0].init_value |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set init_value[63:32] = %x", |
trans->wpayload.b32[i]); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
regs_.highcnt = iclk_->getStepCounter(); |
trans->rpayload.b32[i] = static_cast<uint32_t>(regs_.highcnt); |
break; |
case 1: |
regs_.highcnt = iclk_->getStepCounter(); |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.highcnt >> 32); |
break; |
case 16 + 0: |
trans->rpayload.b32[i] = regs_.timer[0].control; |
RISCV_info("Get [0].control = %08x", trans->rpayload.b32[i]); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
return TRANS_OK; |
} |
|
void GPTimers::stepCallback(uint64_t t) { |
iwire_->raiseLine(); |
RISCV_info("Raise interrupt cnt=%d", dbg_irq_cnt_++); |
if (regs_.timer[0].control & TIMER_CONTROL_ENA) { |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), |
t + regs_.timer[0].init_value); |
} |
} |
|
|
} // namespace debugger |
|
/gptimers.h
1,71 → 1,63
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief General Purpose Timers model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iclklistener.h" |
#include "coreservices/iclock.h" |
#include "coreservices/iwire.h" |
|
namespace debugger { |
|
class GPTimers : public IService, |
public IMemoryOperation, |
public IClockListener { |
public: |
GPTimers(const char *name); |
~GPTimers(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
/** IClockListener */ |
virtual void stepCallback(uint64_t t); |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType irqLine_; |
AttributeType irqctrl_; |
AttributeType clksrc_; |
IWire *iwire_; |
IClock *iclk_; |
|
static const uint32_t TIMER_CONTROL_ENA = 1<<0; |
struct gptimers_map { |
uint64_t highcnt; |
uint32_t pending; |
uint32_t rsvr[13]; |
typedef struct gptimer_type { |
volatile uint32_t control; |
volatile uint32_t rsv1; |
volatile uint64_t cur_value; |
volatile uint64_t init_value; |
} gptimer_type; |
gptimer_type timer[2]; |
} regs_; |
}; |
|
DECLARE_CLASS(GPTimers) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief General Purpose Timers model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iclklistener.h" |
#include "coreservices/iclock.h" |
#include "coreservices/iwire.h" |
|
namespace debugger { |
|
class GPTimers : public IService, |
public IMemoryOperation, |
public IClockListener { |
public: |
GPTimers(const char *name); |
~GPTimers(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
/** IClockListener */ |
virtual void stepCallback(uint64_t t); |
|
private: |
AttributeType irqctrl_; |
AttributeType clksrc_; |
IWire *iwire_; |
IClock *iclk_; |
|
static const uint32_t TIMER_CONTROL_ENA = 1<<0; |
struct gptimers_map { |
uint64_t highcnt; |
uint32_t pending; |
uint32_t rsvr[13]; |
typedef struct gptimer_type { |
volatile uint32_t control; |
volatile uint32_t rsv1; |
volatile uint64_t cur_value; |
volatile uint64_t init_value; |
} gptimer_type; |
gptimer_type timer[2]; |
} regs_; |
|
int dbg_irq_cnt_; |
}; |
|
DECLARE_CLASS(GPTimers) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_GPTIMERS_H__ |
/iboardsim.h
1,38 → 1,38
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the FPGA board with Ethernet UDP/EDCL interface. |
*/ |
|
#ifndef __DEBUGGER_IBOARD_SIM_H__ |
#define __DEBUGGER_IBOARD_SIM_H__ |
|
#include "iface.h" |
#include "attribute.h" |
|
namespace debugger { |
|
static const char *const IFACE_BOARDSIM = "IBoardSim"; |
|
class IBoardSim : public IFace { |
public: |
IBoardSim() : IFace(IFACE_BOARDSIM) {} |
|
virtual const char *getBrief() { |
return "FPGA development board simulator interface"; |
} |
|
virtual const char *getDetail() { |
return "This interface declares functionality of the emulator of the " |
"real hardware. Such emulator allows to develop network " |
"interfaces (UDP/EDCL) without connection to the FPGA that " |
"significantly simplify debugging."; |
} |
|
virtual void getInfo(AttributeType *attr) =0; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_IBOARD_SIM_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Simulator of the FPGA board with Ethernet UDP/EDCL interface. |
*/ |
|
#ifndef __DEBUGGER_IBOARD_SIM_H__ |
#define __DEBUGGER_IBOARD_SIM_H__ |
|
#include "iface.h" |
#include "attribute.h" |
|
namespace debugger { |
|
static const char *const IFACE_BOARDSIM = "IBoardSim"; |
|
class IBoardSim : public IFace { |
public: |
IBoardSim() : IFace(IFACE_BOARDSIM) {} |
|
virtual const char *getBrief() { |
return "FPGA development board simulator interface"; |
} |
|
virtual const char *getDetail() { |
return "This interface declares functionality of the emulator of the " |
"real hardware. Such emulator allows to develop network " |
"interfaces (UDP/EDCL) without connection to the FPGA that " |
"significantly simplify debugging."; |
} |
|
virtual void getInfo(AttributeType *attr) =0; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_IBOARD_SIM_H__ |
/irqctrl.cpp
1,217 → 1,251
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Interrupt controller functional model. |
*/ |
|
#include "api_core.h" |
#include "irqctrl.h" |
|
namespace debugger { |
|
IrqController::IrqController(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<IWire *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("CPU", &cpu_); |
registerAttribute("CSR_MIPI", &mipi_); |
registerAttribute("IrqTotal", &irqTotal_); |
|
baseAddress_.make_uint64(0); |
mipi_.make_uint64(0x783); |
length_.make_uint64(0); |
cpu_.make_string(""); |
irqTotal_.make_uint64(4); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.irq_mask = ~0; |
regs_.irq_lock = 1; |
irq_wait_unlock = 0; |
} |
|
IrqController::~IrqController() { |
} |
|
void IrqController::postinitService() { |
icpu_ = static_cast<ICpuRiscV *>( |
RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_RISCV)); |
if (!icpu_) { |
RISCV_error("Can't find ICpuRiscV interface %s", cpu_.to_string()); |
} |
} |
|
void IrqController::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
uint32_t t1; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (((trans->wstrb >> 4*i) & 0xFF) == 0) { |
continue; |
} |
|
switch (off + i) { |
case 0: |
regs_.irq_mask = trans->wpayload.b32[i]; |
RISCV_info("Set irq_mask = %08x", trans->wpayload.b32[i]); |
break; |
case 1: |
regs_.irq_pending = trans->wpayload.b32[i]; |
RISCV_info("Set irq_pending = %08x", trans->wpayload.b32[i]); |
break; |
case 2: |
t1 = regs_.irq_pending; |
regs_.irq_pending &= ~trans->wpayload.b32[i]; |
if (t1 && !regs_.irq_pending) { |
icpu_->lowerSignal(CPU_SIGNAL_EXT_IRQ); |
} |
RISCV_info("Set irq_clear = %08x", trans->wpayload.b32[i]); |
break; |
case 3: |
regs_.irq_pending |= trans->wpayload.b32[i]; |
RISCV_info("Set irq_rise = %08x", trans->wpayload.b32[i]); |
break; |
case 4: |
regs_.isr_table &= ~0xFFFFFFFFLL; |
regs_.isr_table |= trans->wpayload.b32[i]; |
RISCV_info("Set irq_handler[31:0] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 5: |
regs_.isr_table &= ~0xFFFFFFFF00000000LL; |
regs_.isr_table |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set irq_handler[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 6: |
regs_.dbg_cause &= ~0xFFFFFFFFLL; |
regs_.dbg_cause |= trans->wpayload.b32[i]; |
RISCV_info("Set dbg_cause[31:0] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 7: |
regs_.dbg_cause &= ~0xFFFFFFFF00000000LL; |
regs_.dbg_cause |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set dbg_cause[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 8: |
regs_.dbg_epc &= ~0xFFFFFFFFLL; |
regs_.dbg_epc |= trans->wpayload.b32[i]; |
RISCV_info("Set dbg_epc[31:0] = %08x", trans->wpayload.b32[i]); |
break; |
case 9: |
regs_.dbg_epc &= ~0xFFFFFFFF00000000LL; |
regs_.dbg_epc |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set dbg_epc[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 10: |
regs_.irq_lock = trans->wpayload.b32[i]; |
RISCV_info("Set irq_ena = %08x", trans->wpayload.b32[i]); |
if (regs_.irq_lock == 0 && (regs_.irq_pending ||irq_wait_unlock)) { |
regs_.irq_pending |= irq_wait_unlock; |
icpu_->raiseSignal(CPU_SIGNAL_EXT_IRQ); |
irq_wait_unlock = 0; |
} else if (regs_.irq_lock == 1 && regs_.irq_pending) { |
icpu_->lowerSignal(CPU_SIGNAL_EXT_IRQ); |
} |
break; |
case 11: |
regs_.irq_cause_idx = trans->wpayload.b32[i]; |
RISCV_info("Set irq_cause_idx = %08x", trans->wpayload.b32[i]); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
trans->rpayload.b32[i] = regs_.irq_mask; |
RISCV_info("Get irq_mask = %08x", trans->rpayload.b32[i]); |
break; |
case 1: |
trans->rpayload.b32[i] = regs_.irq_pending; |
RISCV_info("Get irq_pending = %08x", trans->rpayload.b32[i]); |
break; |
case 2: |
trans->rpayload.b32[i] = 0; |
RISCV_info("Get irq_clear = %08x", trans->rpayload.b32[i]); |
break; |
case 3: |
trans->rpayload.b32[i] = 0; |
RISCV_info("Get irq_rise = %08x", trans->rpayload.b32[i]); |
break; |
case 4: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.isr_table); |
RISCV_info("Get irq_handler[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 5: |
trans->rpayload.b32[i] |
= static_cast<uint32_t>(regs_.isr_table >> 32); |
RISCV_info("Get irq_handler[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 6: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_cause); |
RISCV_info("Get dbg_cause[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 7: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_cause >> 32); |
RISCV_info("Get dbg_cause[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 8: |
trans->rpayload.b32[i] = static_cast<uint32_t>(regs_.dbg_epc); |
RISCV_info("Get dbg_epc[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 9: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_epc >> 32); |
RISCV_info("Get dbg_epc[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 10: |
trans->rpayload.b32[i] = regs_.irq_lock; |
RISCV_info("Get irq_ena = %08x", |
trans->rpayload.b32[i]); |
break; |
case 11: |
trans->rpayload.b32[i] = regs_.irq_cause_idx; |
RISCV_info("Get irq_cause_idx = %08x", |
trans->rpayload.b32[i]); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
} |
|
void IrqController::raiseLine(int idx) { |
if (regs_.irq_lock) { |
irq_wait_unlock |= (~regs_.irq_mask & (1 << idx)); |
return; |
} |
if ((regs_.irq_mask & (0x1 << idx)) == 0) { |
regs_.irq_pending |= (0x1 << idx); |
icpu_->raiseSignal(CPU_SIGNAL_EXT_IRQ); // PLIC interrupt (external) |
RISCV_info("Raise interrupt", NULL); |
} |
} |
|
} // namespace debugger |
|
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Interrupt controller functional model. |
*/ |
|
#include "api_core.h" |
#include "irqctrl.h" |
#include <riscv-isa.h> |
#include "coreservices/icpuriscv.h" |
|
namespace debugger { |
|
IrqPort::IrqPort(IService *parent, const char *portname, int idx) { |
parent_ = parent; |
parent->registerPortInterface(portname, static_cast<IWire *>(this)); |
idx_ = idx; |
level_ = false; |
}; |
|
void IrqPort::raiseLine() { |
level_ = true; |
static_cast<IrqController *>(parent_)->requestInterrupt(idx_); |
} |
|
void IrqPort::setLevel(bool level) { |
if (!level_ && level) { |
raiseLine(); |
} else if (level_ && !level) { |
lowerLine(); |
} |
} |
|
IrqController::IrqController(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<IClockListener *>(this)); |
registerAttribute("CPU", &cpu_); |
registerAttribute("CSR_MIPI", &mipi_); |
registerAttribute("IrqTotal", &irqTotal_); |
|
char portname[256]; |
for (int i = 1; i < IRQ_MAX; i++) { |
RISCV_sprintf(portname, sizeof(portname), "irq%d", i); |
irqlines_[i] = new IrqPort(this, portname, i); |
} |
|
mipi_.make_uint64(0x783); |
cpu_.make_string(""); |
irqTotal_.make_uint64(4); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.irq_mask = ~0; |
regs_.irq_lock = 1; |
} |
|
IrqController::~IrqController() { |
} |
|
void IrqController::postinitService() { |
iclk_ = static_cast<IClock *>( |
RISCV_get_service_iface(cpu_.to_string(), IFACE_CLOCK)); |
if (!iclk_) { |
RISCV_error("Can't find IClock interface %s", cpu_.to_string()); |
return; |
} |
|
icpu_ = static_cast<ICpuGeneric *>( |
RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_GENERIC)); |
if (!icpu_) { |
RISCV_error("Can't find ICpuRiscV interface %s", cpu_.to_string()); |
return; |
} |
uint64_t t = iclk_->getStepCounter(); |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1); |
} |
|
ETransStatus IrqController::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
uint32_t t1; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if (((trans->wstrb >> 4*i) & 0xFF) == 0) { |
continue; |
} |
|
switch (off + i) { |
case 0: |
regs_.irq_mask = trans->wpayload.b32[i]; |
RISCV_info("Set irq_mask = %08x", trans->wpayload.b32[i]); |
break; |
case 1: |
regs_.irq_pending = trans->wpayload.b32[i]; |
RISCV_info("Set irq_pending = %08x", trans->wpayload.b32[i]); |
break; |
case 2: |
t1 = regs_.irq_pending; |
regs_.irq_pending &= ~trans->wpayload.b32[i]; |
if (t1 && !regs_.irq_pending) { |
icpu_->lowerSignal(INTERRUPT_MExternal); |
} |
RISCV_info("Set irq_clear = %08x", trans->wpayload.b32[i]); |
break; |
case 3: |
regs_.irq_pending |= trans->wpayload.b32[i]; |
RISCV_info("Set irq_rise = %08x", trans->wpayload.b32[i]); |
break; |
case 4: |
regs_.isr_table &= ~0xFFFFFFFFLL; |
regs_.isr_table |= trans->wpayload.b32[i]; |
RISCV_info("Set irq_handler[31:0] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 5: |
regs_.isr_table &= ~0xFFFFFFFF00000000LL; |
regs_.isr_table |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set irq_handler[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 6: |
regs_.dbg_cause &= ~0xFFFFFFFFLL; |
regs_.dbg_cause |= trans->wpayload.b32[i]; |
RISCV_info("Set dbg_cause[31:0] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 7: |
regs_.dbg_cause &= ~0xFFFFFFFF00000000LL; |
regs_.dbg_cause |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set dbg_cause[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 8: |
regs_.dbg_epc &= ~0xFFFFFFFFLL; |
regs_.dbg_epc |= trans->wpayload.b32[i]; |
RISCV_info("Set dbg_epc[31:0] = %08x", trans->wpayload.b32[i]); |
break; |
case 9: |
regs_.dbg_epc &= ~0xFFFFFFFF00000000LL; |
regs_.dbg_epc |= |
(static_cast<uint64_t>(trans->wpayload.b32[i]) << 32); |
RISCV_info("Set dbg_epc[63:32] = %08x", |
trans->wpayload.b32[i]); |
break; |
case 10: |
regs_.irq_lock = trans->wpayload.b32[i]; |
RISCV_info("Set irq_ena = %08x", trans->wpayload.b32[i]); |
if (regs_.irq_lock == 0 && regs_.irq_pending) { |
icpu_->lowerSignal(INTERRUPT_MExternal); |
} |
break; |
case 11: |
regs_.irq_cause_idx = trans->wpayload.b32[i]; |
RISCV_info("Set irq_cause_idx = %08x", trans->wpayload.b32[i]); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
trans->rpayload.b32[i] = regs_.irq_mask; |
RISCV_info("Get irq_mask = %08x", trans->rpayload.b32[i]); |
break; |
case 1: |
trans->rpayload.b32[i] = regs_.irq_pending; |
RISCV_info("Get irq_pending = %08x", trans->rpayload.b32[i]); |
break; |
case 2: |
trans->rpayload.b32[i] = 0; |
RISCV_info("Get irq_clear = %08x", trans->rpayload.b32[i]); |
break; |
case 3: |
trans->rpayload.b32[i] = 0; |
RISCV_info("Get irq_rise = %08x", trans->rpayload.b32[i]); |
break; |
case 4: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.isr_table); |
RISCV_info("Get irq_handler[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 5: |
trans->rpayload.b32[i] |
= static_cast<uint32_t>(regs_.isr_table >> 32); |
RISCV_info("Get irq_handler[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 6: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_cause); |
RISCV_info("Get dbg_cause[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 7: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_cause >> 32); |
RISCV_info("Get dbg_cause[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 8: |
trans->rpayload.b32[i] = static_cast<uint32_t>(regs_.dbg_epc); |
RISCV_info("Get dbg_epc[31:0] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 9: |
trans->rpayload.b32[i] = |
static_cast<uint32_t>(regs_.dbg_epc >> 32); |
RISCV_info("Get dbg_epc[63:32] = %08x", |
trans->rpayload.b32[i]); |
break; |
case 10: |
trans->rpayload.b32[i] = regs_.irq_lock; |
RISCV_info("Get irq_ena = %08x", |
trans->rpayload.b32[i]); |
break; |
case 11: |
trans->rpayload.b32[i] = regs_.irq_cause_idx; |
RISCV_info("Get irq_cause_idx = %08x", |
trans->rpayload.b32[i]); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
return TRANS_OK; |
} |
|
void IrqController::stepCallback(uint64_t t) { |
iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1); |
if (regs_.irq_lock == 1) { |
return; |
} |
if (~regs_.irq_mask & regs_.irq_pending) { |
icpu_->raiseSignal(INTERRUPT_MExternal); // PLIC interrupt (external) |
RISCV_debug("Raise interrupt", NULL); |
} |
} |
|
void IrqController::requestInterrupt(int idx) { |
regs_.irq_pending |= (0x1 << idx); |
RISCV_info("request Interrupt %d", idx); |
} |
|
} // namespace debugger |
|
/irqctrl.h
1,70 → 1,81
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Interrupt controller functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iwire.h" |
#include "coreservices/icpuriscv.h" |
|
namespace debugger { |
|
class IrqController : public IService, |
public IMemoryOperation, |
public IWire { |
public: |
IrqController(const char *name); |
~IrqController(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *payload); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
/** IWire */ |
virtual void raiseLine(int idx); |
virtual void lowerLine() {} |
virtual void setLevel(bool level) {} |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType mipi_; |
AttributeType irqTotal_; |
AttributeType cpu_; |
ICpuRiscV *icpu_; |
|
struct irqctrl_map { |
uint32_t irq_mask; // 0x00: [RW] 1=disable; 0=enable |
uint32_t irq_pending; // 0x04: [RW] |
uint32_t irq_clear; // 0x08: [WO] |
uint32_t irq_rise; // 0x0c: [WO] |
uint64_t isr_table; // 0x10: [RW] |
uint64_t dbg_cause; // 0x18: [RW] |
uint64_t dbg_epc; // 0x20: [RW] |
uint32_t irq_lock; // 0x28: [RW] |
uint32_t irq_cause_idx; // 0x2c: [RW] |
} regs_; |
uint32_t irq_wait_unlock; |
}; |
|
DECLARE_CLASS(IrqController) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Interrupt controller functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
|
#include <iclass.h> |
#include <iservice.h> |
#include "coreservices/iclock.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iwire.h" |
#include "coreservices/icpugen.h" |
|
namespace debugger { |
|
class IrqPort : public IWire { |
public: |
IrqPort(IService *parent, const char *portname, int idx); |
|
/** IWire interface */ |
virtual void raiseLine(); |
virtual void lowerLine() { level_ = false; } |
virtual void setLevel(bool level); |
virtual bool getLevel() { return level_; } |
|
protected: |
IService *parent_; |
int idx_; |
bool level_; |
}; |
|
class IrqController : public IService, |
public IMemoryOperation, |
public IClockListener { |
public: |
IrqController(const char *name); |
~IrqController(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *payload); |
|
/** IClockListener interface */ |
virtual void stepCallback(uint64_t t); |
|
/** Controller specific methods visible for ports */ |
void requestInterrupt(int idx); |
|
private: |
AttributeType mipi_; |
AttributeType irqTotal_; |
AttributeType cpu_; |
ICpuGeneric *icpu_; |
IClock *iclk_; |
static const int IRQ_MAX = 32; |
IrqPort *irqlines_[IRQ_MAX]; |
|
struct irqctrl_map { |
uint32_t irq_mask; // 0x00: [RW] 1=disable; 0=enable |
uint32_t irq_pending; // 0x04: [RW] |
uint32_t irq_clear; // 0x08: [WO] |
uint32_t irq_rise; // 0x0c: [WO] |
uint64_t isr_table; // 0x10: [RW] |
uint64_t dbg_cause; // 0x18: [RW] |
uint64_t dbg_epc; // 0x20: [RW] |
uint32_t irq_lock; // 0x28: [RW] |
uint32_t irq_cause_idx; // 0x2c: [RW] |
} regs_; |
}; |
|
DECLARE_CLASS(IrqController) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_IRQCTRL_H__ |
/plugin_init.cpp
1,34 → 1,40
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plugin library initialization method. |
*/ |
|
#include "boardsim.h" |
#include "gpio.h" |
#include "uart.h" |
#include "pnp.h" |
#include "irqctrl.h" |
#include "gnss_stub.h" |
#include "gptimers.h" |
#include "dsu.h" |
#include "rfctrl.h" |
#include "fsev2.h" |
|
namespace debugger { |
|
extern "C" void plugin_init(void) { |
REGISTER_CLASS_IDX(BoardSim, 1); |
REGISTER_CLASS_IDX(GPIO, 3); |
REGISTER_CLASS_IDX(UART, 4); |
REGISTER_CLASS_IDX(PNP, 5); |
REGISTER_CLASS_IDX(IrqController, 6); |
REGISTER_CLASS_IDX(GNSSStub, 7); |
REGISTER_CLASS_IDX(DSU, 8); |
REGISTER_CLASS_IDX(GPTimers, 9); |
REGISTER_CLASS_IDX(RfController, 10); |
REGISTER_CLASS_IDX(FseV2, 11); |
} |
|
} // namespace debugger |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plugin library initialization method. |
*/ |
|
#include "boardsim.h" |
#include "gpio.h" |
#include "uart.h" |
#include "pnp.h" |
#include "irqctrl.h" |
#include "gnss_stub.h" |
#include "gptimers.h" |
#include "rfctrl.h" |
#include "fsev2.h" |
#include "uartmst.h" |
#include "hardreset.h" |
#include "debug/dsu.h" |
#include "debug/greth.h" |
|
namespace debugger { |
|
extern "C" void plugin_init(void) { |
REGISTER_CLASS_IDX(BoardSim, 1); |
REGISTER_CLASS_IDX(GPIO, 3); |
REGISTER_CLASS_IDX(UART, 4); |
REGISTER_CLASS_IDX(PNP, 5); |
REGISTER_CLASS_IDX(IrqController, 6); |
REGISTER_CLASS_IDX(GNSSStub, 7); |
REGISTER_CLASS_IDX(DSU, 8); |
REGISTER_CLASS_IDX(GPTimers, 9); |
REGISTER_CLASS_IDX(RfController, 10); |
REGISTER_CLASS_IDX(FseV2, 11); |
REGISTER_CLASS_IDX(UartMst, 12); |
REGISTER_CLASS_IDX(Greth, 13); |
REGISTER_CLASS_IDX(HardReset, 14); |
} |
|
} // namespace debugger |
/pnp.cpp
1,104 → 1,101
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plug'n'Play device functional model. |
*/ |
|
#include "api_core.h" |
#include "pnp.h" |
#include "types_amba.h" |
|
namespace debugger { |
|
PNP::PNP(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("Tech", &tech_); |
registerAttribute("AdcDetector", &adc_detector_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
tech_.make_uint64(0); |
adc_detector_.make_uint64(0); |
|
memset(®s_, 0, sizeof(regs_)); |
iter_.buf = regs_.cfg_table; |
regs_.hwid = 0x20170313; |
regs_.fwid = 0xdeadcafe; |
regs_.tech.bits.tech = TECH_INFERRED; |
regs_.tech.bits.mst_total = 0; |
regs_.tech.bits.slv_total = 0; |
|
addMaster(0, VENDOR_GNSSSENSOR, RISCV_RIVER_CPU); |
addMaster(1, VENDOR_GNSSSENSOR, MST_DID_EMPTY); |
addMaster(2, VENDOR_GNSSSENSOR, GAISLER_ETH_MAC_MASTER); |
addMaster(3, VENDOR_GNSSSENSOR, GAISLER_ETH_EDCL_MASTER); |
|
addSlave(0, 8*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_BOOTROM); |
addSlave(0x00100000, 256*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_FWIMAGE); |
addSlave(0x10000000, 512*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_SRAM); |
addSlave(0x80000000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_GPIO); |
addSlave(0x80001000, 4*1024, 1, VENDOR_GNSSSENSOR, GNSSSENSOR_UART); |
addSlave(0x80002000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_IRQCTRL); |
addSlave(0x80003000, 4*1024, 5, VENDOR_GNSSSENSOR, GNSSSENSOR_ENGINE_STUB); |
addSlave(0x80004000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_RF_CONTROL); |
addSlave(0x80005000, 4*1024, 3, VENDOR_GNSSSENSOR, GNSSSENSOR_GPTIMERS); |
addSlave(0x80006000, 4*1024, 2, VENDOR_GNSSSENSOR, GNSSSENSOR_ETHMAC); |
addSlave(0x80007000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_DSU); |
addSlave(0x80008000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_FSE_V2_GPS); |
addSlave(0xfffff000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_PNP); |
} |
|
PNP::~PNP() { |
} |
|
void PNP::addMaster(unsigned idx, unsigned vid, unsigned did) { |
regs_.tech.bits.mst_total++; |
iter_.item->mst.vid = vid; |
iter_.item->mst.did = did; |
iter_.item->mst.descr.bits.descrtype = PNP_CFG_TYPE_MASTER; |
iter_.item->mst.descr.bits.descrsize = sizeof(MasterConfigType); |
iter_.buf += sizeof(MasterConfigType); |
} |
|
void PNP::addSlave(uint64_t addr, uint64_t size, unsigned irq, unsigned vid, unsigned did) { |
regs_.tech.bits.slv_total++; |
iter_.item->slv.vid = vid; |
iter_.item->slv.did = did; |
iter_.item->slv.descr.bits.descrtype = PNP_CFG_TYPE_SLAVE; |
iter_.item->slv.descr.bits.descrsize = sizeof(SlaveConfigType); |
iter_.item->slv.descr.bits.bar_total = 1; |
iter_.item->slv.descr.bits.irq_idx = irq; |
iter_.item->slv.xaddr = static_cast<uint32_t>(addr); |
iter_.item->slv.xmask = static_cast<uint32_t>(~(size - 1)); |
iter_.buf += sizeof(SlaveConfigType); |
} |
|
void PNP::postinitService() { |
regs_.tech.bits.tech = static_cast<uint8_t>(tech_.to_uint64()); |
regs_.tech.bits.adc_detect = |
static_cast<uint8_t>(adc_detector_.to_uint64()); |
} |
|
void PNP::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
uint8_t *mem_ = reinterpret_cast<uint8_t *>(®s_); |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize; i++) { |
if ((trans->wstrb & (1 << i)) == 0) { |
continue; |
} |
mem_[off + i] = trans->wpayload.b8[i]; |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize; i++) { |
trans->rpayload.b8[i] = mem_[off + i]; |
} |
} |
} |
|
} // namespace debugger |
|
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plug'n'Play device functional model. |
*/ |
|
#include "api_core.h" |
#include "pnp.h" |
#include "types_amba.h" |
|
namespace debugger { |
|
PNP::PNP(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("Tech", &tech_); |
registerAttribute("AdcDetector", &adc_detector_); |
|
tech_.make_uint64(0); |
adc_detector_.make_uint64(0); |
|
memset(®s_, 0, sizeof(regs_)); |
iter_.buf = regs_.cfg_table; |
regs_.hwid = 0x20170313; |
regs_.fwid = 0xdeadcafe; |
regs_.tech.bits.tech = TECH_INFERRED; |
regs_.tech.bits.mst_total = 0; |
regs_.tech.bits.slv_total = 0; |
|
addMaster(0, VENDOR_GNSSSENSOR, RISCV_RIVER_CPU); |
addMaster(1, VENDOR_GNSSSENSOR, MST_DID_EMPTY); |
addMaster(2, VENDOR_GNSSSENSOR, GAISLER_ETH_MAC_MASTER); |
addMaster(3, VENDOR_GNSSSENSOR, GAISLER_ETH_EDCL_MASTER); |
|
addSlave(0, 8*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_BOOTROM); |
addSlave(0x00100000, 256*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_FWIMAGE); |
addSlave(0x10000000, 512*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_SRAM); |
addSlave(0x80000000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_GPIO); |
addSlave(0x80001000, 4*1024, 1, VENDOR_GNSSSENSOR, GNSSSENSOR_UART); |
addSlave(0x80002000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_IRQCTRL); |
addSlave(0x80003000, 4*1024, 5, VENDOR_GNSSSENSOR, GNSSSENSOR_ENGINE_STUB); |
addSlave(0x80004000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_RF_CONTROL); |
addSlave(0x80005000, 4*1024, 3, VENDOR_GNSSSENSOR, GNSSSENSOR_GPTIMERS); |
addSlave(0x80006000, 4*1024, 2, VENDOR_GNSSSENSOR, GNSSSENSOR_ETHMAC); |
addSlave(0x80007000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_DSU); |
addSlave(0x80008000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_FSE_V2_GPS); |
addSlave(0xfffff000, 4*1024, 0, VENDOR_GNSSSENSOR, GNSSSENSOR_PNP); |
} |
|
PNP::~PNP() { |
} |
|
void PNP::addMaster(unsigned idx, unsigned vid, unsigned did) { |
regs_.tech.bits.mst_total++; |
iter_.item->mst.vid = vid; |
iter_.item->mst.did = did; |
iter_.item->mst.descr.bits.descrtype = PNP_CFG_TYPE_MASTER; |
iter_.item->mst.descr.bits.descrsize = sizeof(MasterConfigType); |
iter_.buf += sizeof(MasterConfigType); |
} |
|
void PNP::addSlave(uint64_t addr, uint64_t size, unsigned irq, unsigned vid, unsigned did) { |
regs_.tech.bits.slv_total++; |
iter_.item->slv.vid = vid; |
iter_.item->slv.did = did; |
iter_.item->slv.descr.bits.descrtype = PNP_CFG_TYPE_SLAVE; |
iter_.item->slv.descr.bits.descrsize = sizeof(SlaveConfigType); |
iter_.item->slv.descr.bits.bar_total = 1; |
iter_.item->slv.descr.bits.irq_idx = irq; |
iter_.item->slv.xaddr = static_cast<uint32_t>(addr); |
iter_.item->slv.xmask = static_cast<uint32_t>(~(size - 1)); |
iter_.buf += sizeof(SlaveConfigType); |
} |
|
void PNP::postinitService() { |
regs_.tech.bits.tech = static_cast<uint8_t>(tech_.to_uint64()); |
regs_.tech.bits.adc_detect = |
static_cast<uint8_t>(adc_detector_.to_uint64()); |
} |
|
ETransStatus PNP::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask); |
uint8_t *mem_ = reinterpret_cast<uint8_t *>(®s_); |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize; i++) { |
if ((trans->wstrb & (1 << i)) == 0) { |
continue; |
} |
mem_[off + i] = trans->wpayload.b8[i]; |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize; i++) { |
trans->rpayload.b8[i] = mem_[off + i]; |
} |
} |
return TRANS_OK; |
} |
|
} // namespace debugger |
|
/pnp.h
1,60 → 1,52
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plug'n'Play device functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/isocinfo.h" |
|
namespace debugger { |
|
class PNP : public IService, |
public IMemoryOperation { |
public: |
PNP(const char *name); |
~PNP(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
private: |
void addMaster(unsigned idx, unsigned vid, unsigned did); |
void addSlave(uint64_t addr, uint64_t size, unsigned irq, unsigned vid, unsigned did); |
|
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType tech_; |
AttributeType adc_detector_; |
|
PnpMapType regs_; |
union DescriptorTableType { |
union DescriptorItemType { |
MasterConfigType mst; |
SlaveConfigType slv; |
} *item; |
uint8_t *buf; |
} iter_; |
}; |
|
DECLARE_CLASS(PNP) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Plug'n'Play device functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/isocinfo.h" |
|
namespace debugger { |
|
class PNP : public IService, |
public IMemoryOperation { |
public: |
PNP(const char *name); |
~PNP(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
private: |
void addMaster(unsigned idx, unsigned vid, unsigned did); |
void addSlave(uint64_t addr, uint64_t size, unsigned irq, |
unsigned vid, unsigned did); |
|
AttributeType tech_; |
AttributeType adc_detector_; |
|
PnpMapType regs_; |
union DescriptorTableType { |
union DescriptorItemType { |
MasterConfigType mst; |
SlaveConfigType slv; |
} *item; |
uint8_t *buf; |
} iter_; |
}; |
|
DECLARE_CLASS(PNP) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_PNP_H__ |
/rfctrl.cpp
1,68 → 1,64
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief RF front-end black-box model. |
*/ |
|
#include "api_core.h" |
#include "rfctrl.h" |
|
namespace debugger { |
|
RfController::RfController(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
|
memset(®s_, 0, sizeof(regs_)); |
} |
|
RfController::~RfController() { |
} |
|
void RfController::postinitService() { |
} |
|
void RfController::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case (0x2c >> 2): |
RISCV_info("Run channel %d", trans->wpayload.b32[i]); |
regs_.run = 0xf; // simulate loading delay |
break; |
case (0x3c >> 2): //rw_ant_status |
regs_.rw_ant_status &= ~0x3; //enable power ant1/2 |
regs_.rw_ant_status |= trans->wpayload.b32[i]; |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case (0x2c >> 2): // run |
regs_.run >>= 1; |
trans->rpayload.b32[i] = regs_.run; |
break; |
case (0x3c >> 2): //rw_ant_status |
trans->rpayload.b32[i] = regs_.rw_ant_status; |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
} |
|
} // namespace debugger |
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief RF front-end black-box model. |
*/ |
|
#include "api_core.h" |
#include "rfctrl.h" |
|
namespace debugger { |
|
RfController::RfController(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
|
memset(®s_, 0, sizeof(regs_)); |
} |
|
RfController::~RfController() { |
} |
|
void RfController::postinitService() { |
} |
|
ETransStatus RfController::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case (0x2c >> 2): |
RISCV_info("Run channel %d", trans->wpayload.b32[i]); |
regs_.run = 0xf; // simulate loading delay |
break; |
case (0x3c >> 2): //rw_ant_status |
regs_.rw_ant_status &= ~0x3; //enable power ant1/2 |
regs_.rw_ant_status |= trans->wpayload.b32[i]; |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case (0x2c >> 2): // run |
regs_.run >>= 1; |
trans->rpayload.b32[i] = regs_.run; |
break; |
case (0x3c >> 2): //rw_ant_status |
trans->rpayload.b32[i] = regs_.rw_ant_status; |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
return TRANS_OK; |
} |
|
} // namespace debugger |
/rfctrl.h
1,62 → 1,52
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief RF front-end black-box model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
|
namespace debugger { |
|
class RfController : public IService, |
public IMemoryOperation { |
public: |
RfController(const char *name); |
~RfController(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
|
struct rfctrl_map { |
volatile uint32_t conf1; // 0x00 |
volatile uint32_t conf2; // 0x04 |
volatile uint32_t conf3; // 0x08/ |
volatile uint32_t pllconf; // 0x0C/ |
volatile uint32_t div; // 0x10 |
volatile uint32_t fdiv; // 0x14 |
volatile uint32_t strm; // 0x18 |
volatile uint32_t clkdiv; // 0x1C |
volatile uint32_t test1; // 0x20 |
volatile uint32_t test2; // 0x24 |
volatile uint32_t scale; // 0x28 |
volatile uint32_t run; // 0x2C |
volatile uint32_t reserved1[3]; // 0x30,0x34,0x38 |
volatile uint32_t rw_ant_status;// 0x3C |
} regs_; |
}; |
|
DECLARE_CLASS(RfController) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
/** |
* @file |
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief RF front-end black-box model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
|
namespace debugger { |
|
class RfController : public IService, |
public IMemoryOperation { |
public: |
RfController(const char *name); |
~RfController(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
private: |
struct rfctrl_map { |
volatile uint32_t conf1; // 0x00 |
volatile uint32_t conf2; // 0x04 |
volatile uint32_t conf3; // 0x08/ |
volatile uint32_t pllconf; // 0x0C/ |
volatile uint32_t div; // 0x10 |
volatile uint32_t fdiv; // 0x14 |
volatile uint32_t strm; // 0x18 |
volatile uint32_t clkdiv; // 0x1C |
volatile uint32_t test1; // 0x20 |
volatile uint32_t test2; // 0x24 |
volatile uint32_t scale; // 0x28 |
volatile uint32_t run; // 0x2C |
volatile uint32_t reserved1[3]; // 0x30,0x34,0x38 |
volatile uint32_t rw_ant_status;// 0x3C |
} regs_; |
}; |
|
DECLARE_CLASS(RfController) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_RFCTRL_H__ |
/ringbuf.h
1,80 → 1,80
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Ringbuffer implementation. |
*/ |
|
#ifndef __DEBUGGER_RINGBUF_H__ |
#define __DEBUGGER_RINGBUF_H__ |
|
#include <inttypes.h> |
#include <string> |
|
namespace debugger { |
|
class RingBufferType { |
public: |
explicit RingBufferType(int sz) { |
size_ = sz + 1; |
rdpos_ = buf_ = new uint8_t[2 * size_]; |
wrpos_ = rdpos_ + 1; |
} |
~RingBufferType() { |
delete buf_; |
} |
|
uint8_t *put(uint8_t *buf, int sz) { |
uint8_t *ret = wrpos_; |
if (&buf_[size_] >= wrpos_ + sz) { |
memcpy(wrpos_, buf, sz); |
memcpy(wrpos_ + size_, buf, sz); |
wrpos_ += sz; |
} else { |
int part = static_cast<int>(&buf_[size_] - wrpos_); |
memcpy(wrpos_, buf, part); |
memcpy(wrpos_ + size_, buf, part); |
int part2 = sz - part; |
memcpy(buf_, &buf[part], part2); |
memcpy(buf_+ size_, &buf[part], part2); |
wrpos_ += (sz - size_); |
} |
return ret; |
} |
|
int get(uint8_t *obuf, int sz) { |
int ret = sz; |
if (ret > size()) { |
ret = size(); |
} |
/// do not modificate rdpos_ pointer before data reading complete. |
if (rdpos_ == &buf_[size_ - 1]) { |
memcpy(obuf, buf_, ret); |
} else { |
memcpy(obuf, rdpos_ + 1, ret); |
} |
rdpos_ += sz; |
if (rdpos_ >= &buf_[size_]) { |
rdpos_ -= size_; |
} |
return ret; |
} |
|
int size() { |
int t1 = static_cast<int>(wrpos_ - rdpos_) - 1; |
if (t1 < 0) { |
t1 += size_; |
} |
return t1; |
} |
|
private: |
uint8_t *buf_; |
uint8_t *wrpos_; |
uint8_t *rdpos_; |
int size_; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_RINGBUF_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief Ringbuffer implementation. |
*/ |
|
#ifndef __DEBUGGER_RINGBUF_H__ |
#define __DEBUGGER_RINGBUF_H__ |
|
#include <inttypes.h> |
#include <string> |
|
namespace debugger { |
|
class RingBufferType { |
public: |
explicit RingBufferType(int sz) { |
size_ = sz + 1; |
rdpos_ = buf_ = new uint8_t[2 * size_]; |
wrpos_ = rdpos_ + 1; |
} |
~RingBufferType() { |
delete buf_; |
} |
|
uint8_t *put(uint8_t *buf, int sz) { |
uint8_t *ret = wrpos_; |
if (&buf_[size_] >= wrpos_ + sz) { |
memcpy(wrpos_, buf, sz); |
memcpy(wrpos_ + size_, buf, sz); |
wrpos_ += sz; |
} else { |
int part = static_cast<int>(&buf_[size_] - wrpos_); |
memcpy(wrpos_, buf, part); |
memcpy(wrpos_ + size_, buf, part); |
int part2 = sz - part; |
memcpy(buf_, &buf[part], part2); |
memcpy(buf_+ size_, &buf[part], part2); |
wrpos_ += (sz - size_); |
} |
return ret; |
} |
|
int get(uint8_t *obuf, int sz) { |
int ret = sz; |
if (ret > size()) { |
ret = size(); |
} |
/// do not modificate rdpos_ pointer before data reading complete. |
if (rdpos_ == &buf_[size_ - 1]) { |
memcpy(obuf, buf_, ret); |
} else { |
memcpy(obuf, rdpos_ + 1, ret); |
} |
rdpos_ += sz; |
if (rdpos_ >= &buf_[size_]) { |
rdpos_ -= size_; |
} |
return ret; |
} |
|
int size() { |
int t1 = static_cast<int>(wrpos_ - rdpos_) - 1; |
if (t1 < 0) { |
t1 += size_; |
} |
return t1; |
} |
|
private: |
uint8_t *buf_; |
uint8_t *wrpos_; |
uint8_t *rdpos_; |
int size_; |
}; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_RINGBUF_H__ |
/types_amba.h
1,39 → 1,39
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief System Bus configuration types declaration. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
#define __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
static const uint64_t CFG_NASTI_DATA_BITS = 128; |
static const uint64_t CFG_NASTI_DATA_BYTES = CFG_NASTI_DATA_BITS / 8; |
static const uint64_t CFG_NASTI_DATA_WORDS32 = CFG_NASTI_DATA_BYTES / 4; |
static const uint64_t CFG_NASTI_ADDR_BITS = 32; |
static const uint64_t CFG_NASTI_ADDR_OFFSET = 4; |
static const uint64_t CFG_NASTI_CFG_ADDR_BITS = CFG_NASTI_ADDR_BITS - 12; |
|
static const int CFG_NASTI_BOOTROM = 0; |
static const int CFG_NASTI_FWROM = CFG_NASTI_BOOTROM + 1; |
static const int CFG_NASTI_SRAM = CFG_NASTI_FWROM + 1; |
static const int CFG_NASTI_UART = CFG_NASTI_SRAM + 1; |
static const int CFG_NASTI_GPIO = CFG_NASTI_UART + 1; |
static const int CFG_NASTI_IRQCTRL = CFG_NASTI_GPIO + 1; |
static const int CFG_NASTI_GNSSENGINE = CFG_NASTI_IRQCTRL + 1; |
static const int CFG_NASTI_RFCTRL = CFG_NASTI_GNSSENGINE + 1; |
static const int CFG_NASTI_FSE_GPS = CFG_NASTI_RFCTRL + 1; |
static const int CFG_NASTI_ETHMAC = CFG_NASTI_FSE_GPS + 1; |
static const int CFG_NASTI_DSU = CFG_NASTI_ETHMAC + 1; |
static const int CFG_NASTI_PNP = CFG_NASTI_DSU + 1; |
static const int CFG_NASTI_SLAVES_TOTAL = CFG_NASTI_PNP + 1; |
|
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief System Bus configuration types declaration. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
#define __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
static const uint64_t CFG_NASTI_DATA_BITS = 128; |
static const uint64_t CFG_NASTI_DATA_BYTES = CFG_NASTI_DATA_BITS / 8; |
static const uint64_t CFG_NASTI_DATA_WORDS32 = CFG_NASTI_DATA_BYTES / 4; |
static const uint64_t CFG_NASTI_ADDR_BITS = 32; |
static const uint64_t CFG_NASTI_ADDR_OFFSET = 4; |
static const uint64_t CFG_NASTI_CFG_ADDR_BITS = CFG_NASTI_ADDR_BITS - 12; |
|
static const int CFG_NASTI_BOOTROM = 0; |
static const int CFG_NASTI_FWROM = CFG_NASTI_BOOTROM + 1; |
static const int CFG_NASTI_SRAM = CFG_NASTI_FWROM + 1; |
static const int CFG_NASTI_UART = CFG_NASTI_SRAM + 1; |
static const int CFG_NASTI_GPIO = CFG_NASTI_UART + 1; |
static const int CFG_NASTI_IRQCTRL = CFG_NASTI_GPIO + 1; |
static const int CFG_NASTI_GNSSENGINE = CFG_NASTI_IRQCTRL + 1; |
static const int CFG_NASTI_RFCTRL = CFG_NASTI_GNSSENGINE + 1; |
static const int CFG_NASTI_FSE_GPS = CFG_NASTI_RFCTRL + 1; |
static const int CFG_NASTI_ETHMAC = CFG_NASTI_FSE_GPS + 1; |
static const int CFG_NASTI_DSU = CFG_NASTI_ETHMAC + 1; |
static const int CFG_NASTI_PNP = CFG_NASTI_DSU + 1; |
static const int CFG_NASTI_SLAVES_TOTAL = CFG_NASTI_PNP + 1; |
|
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_TYPES_AMBA_H__ |
/uart.cpp
1,171 → 1,247
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief UART functional model. |
*/ |
|
#include "api_core.h" |
#include "uart.h" |
|
namespace debugger { |
|
static const uint32_t UART_STATUS_TX_FULL = 0x00000001; |
static const uint32_t UART_STATUS_TX_EMPTY = 0x00000002; |
static const uint32_t UART_STATUS_RX_FULL = 0x00000010; |
static const uint32_t UART_STATUS_RX_EMPTY = 0x00000020; |
static const uint32_t UART_STATUS_ERR_PARITY = 0x00000100; |
static const uint32_t UART_STATUS_ERR_STOPBIT = 0x00000200; |
static const uint32_t UART_CONTROL_RX_IRQ_ENA = 0x00002000; |
static const uint32_t UART_CONTROL_TX_IRQ_ENA = 0x00004000; |
static const uint32_t UART_CONTROL_PARITY_ENA = 0x00008000; |
|
|
UART::UART(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<ISerial *>(this)); |
registerAttribute("BaseAddress", &baseAddress_); |
registerAttribute("Length", &length_); |
registerAttribute("IrqLine", &irqLine_); |
registerAttribute("IrqControl", &irqctrl_); |
|
baseAddress_.make_uint64(0); |
length_.make_uint64(0); |
irqLine_.make_uint64(0); |
irqctrl_.make_string(""); |
listeners_.make_list(0); |
RISCV_mutex_init(&mutexListeners_); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY; |
|
p_rx_wr_ = rxfifo_; |
p_rx_rd_ = rxfifo_; |
rx_total_ = 0; |
} |
|
UART::~UART() { |
RISCV_mutex_destroy(&mutexListeners_); |
} |
|
void UART::postinitService() { |
iwire_ = static_cast<IWire *>( |
RISCV_get_service_iface(irqctrl_.to_string(), IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_.to_string()); |
} |
} |
|
int UART::writeData(const char *buf, int sz) { |
if (sz > (RX_FIFO_SIZE - rx_total_)) { |
sz = (RX_FIFO_SIZE - rx_total_); |
} |
for (int i = 0; i < sz; i++) { |
rx_total_++; |
*p_rx_wr_ = buf[i]; |
if ((++p_rx_wr_) >= (rxfifo_ + RX_FIFO_SIZE)) { |
p_rx_wr_ = rxfifo_; |
} |
} |
|
if (regs_.status & UART_CONTROL_RX_IRQ_ENA) { |
iwire_->raiseLine(irqLine_.to_int()); |
} |
return sz; |
} |
|
void UART::registerRawListener(IFace *listener) { |
AttributeType lstn(listener); |
RISCV_mutex_lock(&mutexListeners_); |
listeners_.add_to_list(&lstn); |
RISCV_mutex_unlock(&mutexListeners_); |
} |
|
void UART::unregisterRawListener(IFace *listener) { |
for (unsigned i = 0; i < listeners_.size(); i++) { |
IFace *iface = listeners_[i].to_iface(); |
if (iface == listener) { |
RISCV_mutex_lock(&mutexListeners_); |
listeners_.remove_from_list(i); |
RISCV_mutex_unlock(&mutexListeners_); |
break; |
} |
} |
} |
|
void UART::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
char wrdata; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case 0: |
regs_.status = trans->wpayload.b32[i]; |
RISCV_info("Set status = %08x", regs_.status); |
break; |
case 1: |
regs_.scaler = trans->wpayload.b32[i]; |
RISCV_info("Set scaler = %d", regs_.scaler); |
break; |
case 4: |
wrdata = static_cast<char>(trans->wpayload.b32[i]); |
RISCV_info("Set data = %s", ®s_.data); |
RISCV_mutex_lock(&mutexListeners_); |
for (unsigned n = 0; n < listeners_.size(); n++) { |
IRawListener *lstn = static_cast<IRawListener *>( |
listeners_[n].to_iface()); |
|
lstn->updateData(&wrdata, 1); |
} |
RISCV_mutex_unlock(&mutexListeners_); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
if (0) { |
regs_.status &= ~UART_STATUS_TX_EMPTY; |
} else { |
regs_.status |= UART_STATUS_TX_EMPTY; |
} |
if (rx_total_ == 0) { |
regs_.status |= UART_STATUS_RX_EMPTY; |
} else { |
regs_.status &= ~UART_STATUS_RX_EMPTY; |
} |
trans->rpayload.b32[i] = regs_.status; |
RISCV_info("Get status = %08x", regs_.status); |
break; |
case 1: |
trans->rpayload.b32[i] = regs_.scaler; |
RISCV_info("Get scaler = %d", regs_.scaler); |
break; |
case 4: |
if (rx_total_ == 0) { |
trans->rpayload.b32[i] = 0; |
} else { |
trans->rpayload.b32[i] = *p_rx_rd_; |
rx_total_--; |
if ((++p_rx_rd_) >= (rxfifo_ + RX_FIFO_SIZE)) { |
p_rx_rd_ = rxfifo_; |
} |
} |
RISCV_debug("Get data = %02x", (trans->rpayload.b32[i] & 0xFF)); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
} |
|
} // namespace debugger |
|
/* |
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
|
#include "api_core.h" |
#include "uart.h" |
|
namespace debugger { |
|
static const uint32_t UART_STATUS_TX_FULL = 0x00000001; |
static const uint32_t UART_STATUS_TX_EMPTY = 0x00000002; |
static const uint32_t UART_STATUS_RX_FULL = 0x00000010; |
static const uint32_t UART_STATUS_RX_EMPTY = 0x00000020; |
static const uint32_t UART_STATUS_ERR_PARITY = 0x00000100; |
static const uint32_t UART_STATUS_ERR_STOPBIT = 0x00000200; |
static const uint32_t UART_CONTROL_RX_IRQ_ENA = 0x00002000; |
static const uint32_t UART_CONTROL_TX_IRQ_ENA = 0x00004000; |
static const uint32_t UART_CONTROL_PARITY_ENA = 0x00008000; |
|
|
UART::UART(const char *name) : IService(name) { |
registerInterface(static_cast<IMemoryOperation *>(this)); |
registerInterface(static_cast<ISerial *>(this)); |
registerAttribute("IrqControl", &irqctrl_); |
registerAttribute("AutoTestEna", &autoTestEna_); |
registerAttribute("TestCases", &testCases_); |
|
listeners_.make_list(0); |
RISCV_mutex_init(&mutexListeners_); |
|
memset(®s_, 0, sizeof(regs_)); |
regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY; |
|
p_rx_wr_ = rxfifo_; |
p_rx_rd_ = rxfifo_; |
rx_total_ = 0; |
pautotest_ = NULL; |
} |
|
UART::~UART() { |
RISCV_mutex_destroy(&mutexListeners_); |
if (pautotest_) { |
delete pautotest_; |
} |
} |
|
void UART::postinitService() { |
iwire_ = static_cast<IWire *>( |
RISCV_get_service_port_iface(irqctrl_[0u].to_string(), |
irqctrl_[1].to_string(), |
IFACE_WIRE)); |
if (!iwire_) { |
RISCV_error("Can't find IWire interface %s", irqctrl_[0u].to_string()); |
} |
if (autoTestEna_.to_bool()) { |
pautotest_ = new AutoTest(static_cast<ISerial *>(this), &testCases_); |
} |
} |
|
int UART::writeData(const char *buf, int sz) { |
if (sz > (RX_FIFO_SIZE - rx_total_)) { |
sz = (RX_FIFO_SIZE - rx_total_); |
} |
for (int i = 0; i < sz; i++) { |
rx_total_++; |
*p_rx_wr_ = buf[i]; |
if ((++p_rx_wr_) >= (rxfifo_ + RX_FIFO_SIZE)) { |
p_rx_wr_ = rxfifo_; |
} |
} |
|
if (regs_.status & UART_CONTROL_RX_IRQ_ENA) { |
iwire_->raiseLine(); |
} |
return sz; |
} |
|
void UART::registerRawListener(IFace *listener) { |
AttributeType lstn(listener); |
RISCV_mutex_lock(&mutexListeners_); |
listeners_.add_to_list(&lstn); |
RISCV_mutex_unlock(&mutexListeners_); |
} |
|
void UART::unregisterRawListener(IFace *listener) { |
for (unsigned i = 0; i < listeners_.size(); i++) { |
IFace *iface = listeners_[i].to_iface(); |
if (iface == listener) { |
RISCV_mutex_lock(&mutexListeners_); |
listeners_.remove_from_list(i); |
RISCV_mutex_unlock(&mutexListeners_); |
break; |
} |
} |
} |
|
void UART::getListOfPorts(AttributeType *list) { |
list->make_list(0); |
} |
|
int UART::openPort(const char *port, AttributeType settings) { |
return 0; |
} |
|
void UART::closePort() { |
} |
|
|
ETransStatus UART::b_transport(Axi4TransactionType *trans) { |
uint64_t mask = (length_.to_uint64() - 1); |
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4; |
char wrdata; |
trans->response = MemResp_Valid; |
if (trans->action == MemAction_Write) { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
if ((trans->wstrb & (0xf << 4*i)) == 0) { |
continue; |
} |
switch (off + i) { |
case 0: |
regs_.status = trans->wpayload.b32[i]; |
RISCV_info("Set status = %08x", regs_.status); |
break; |
case 1: |
regs_.scaler = trans->wpayload.b32[i]; |
RISCV_info("Set scaler = %d", regs_.scaler); |
break; |
case 4: |
wrdata = static_cast<char>(trans->wpayload.b32[i]); |
RISCV_info("Set data = %s", ®s_.data); |
RISCV_mutex_lock(&mutexListeners_); |
for (unsigned n = 0; n < listeners_.size(); n++) { |
IRawListener *lstn = static_cast<IRawListener *>( |
listeners_[n].to_iface()); |
|
lstn->updateData(&wrdata, 1); |
} |
RISCV_mutex_unlock(&mutexListeners_); |
break; |
default:; |
} |
} |
} else { |
for (uint64_t i = 0; i < trans->xsize/4; i++) { |
switch (off + i) { |
case 0: |
if (0) { |
regs_.status &= ~UART_STATUS_TX_EMPTY; |
} else { |
regs_.status |= UART_STATUS_TX_EMPTY; |
} |
if (rx_total_ == 0) { |
regs_.status |= UART_STATUS_RX_EMPTY; |
} else { |
regs_.status &= ~UART_STATUS_RX_EMPTY; |
} |
trans->rpayload.b32[i] = regs_.status; |
RISCV_info("Get status = %08x", regs_.status); |
break; |
case 1: |
trans->rpayload.b32[i] = regs_.scaler; |
RISCV_info("Get scaler = %d", regs_.scaler); |
break; |
case 4: |
if (rx_total_ == 0) { |
trans->rpayload.b32[i] = 0; |
} else { |
trans->rpayload.b32[i] = *p_rx_rd_; |
rx_total_--; |
if ((++p_rx_rd_) >= (rxfifo_ + RX_FIFO_SIZE)) { |
p_rx_rd_ = rxfifo_; |
} |
} |
RISCV_debug("Get data = %02x", (trans->rpayload.b32[i] & 0xFF)); |
break; |
default: |
trans->rpayload.b32[i] = ~0; |
} |
} |
} |
return TRANS_OK; |
} |
|
/** |
* CPU validation purpose. Reaction on keyboard interrupt: |
*/ |
|
UART::AutoTest::AutoTest(ISerial *parent, AttributeType *tests) { |
parent_ = parent; |
tests_ = *tests; |
testcnt_ = 0; |
IClock *iclk = static_cast<IClock *>( |
RISCV_get_service_iface("core0", IFACE_CLOCK)); |
if (iclk && tests_.is_list() && tests_.size()) { |
const AttributeType &t0 = tests_[testcnt_]; |
if (t0.size() == 2) { |
iclk->registerStepCallback(static_cast<IClockListener *>(this), |
t0[0u].to_uint64()); |
} |
} |
} |
|
void UART::AutoTest::stepCallback(uint64_t t) { |
const AttributeType &tn = tests_[testcnt_]; |
char msg[64]; |
int msglen = 0; |
const char *pbuf = tn[1].to_string(); |
for (unsigned i = 0; i < tn[1].size(); i++) { |
if (pbuf[i] == '\\' && pbuf[i+1] == 'r') { |
++i; |
msg[msglen++] = '\r'; |
msg[msglen] = '\0'; |
continue; |
} else if (pbuf[i] == '\\' && pbuf[i+1] == 'n') { |
++i; |
msg[msglen++] = '\n'; |
msg[msglen] = '\0'; |
continue; |
} |
msg[msglen++] = pbuf[i]; |
msg[msglen] = '\0'; |
} |
parent_->writeData(msg, msglen); |
|
if (++testcnt_ < tests_.size()) { |
const AttributeType &t0 = tests_[testcnt_]; |
IClock *iclk = static_cast<IClock *>( |
RISCV_get_service_iface("core0", IFACE_CLOCK)); |
iclk->registerStepCallback(static_cast<IClockListener *>(this), |
t0[0u].to_uint64()); |
} |
} |
|
} // namespace debugger |
|
/uart.h
1,74 → 1,93
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief UART functional model. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iserial.h" |
#include "coreservices/iwire.h" |
#include "coreservices/irawlistener.h" |
#include <string> |
|
namespace debugger { |
|
class UART : public IService, |
public IMemoryOperation, |
public ISerial { |
public: |
UART(const char *name); |
~UART(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual void b_transport(Axi4TransactionType *trans); |
|
virtual uint64_t getBaseAddress() { |
return baseAddress_.to_uint64(); |
} |
virtual uint64_t getLength() { |
return length_.to_uint64(); |
} |
|
/** ISerial */ |
virtual int writeData(const char *buf, int sz); |
virtual void registerRawListener(IFace *listener); |
virtual void unregisterRawListener(IFace *listener); |
|
private: |
AttributeType baseAddress_; |
AttributeType length_; |
AttributeType irqLine_; |
AttributeType irqctrl_; |
AttributeType listeners_; // non-registering attribute |
IWire *iwire_; |
|
std::string input_; |
static const int RX_FIFO_SIZE = 16; |
char rxfifo_[RX_FIFO_SIZE]; |
char *p_rx_wr_; |
char *p_rx_rd_; |
int rx_total_; |
mutex_def mutexListeners_; |
|
struct uart_map { |
volatile uint32_t status; |
volatile uint32_t scaler; |
uint32_t rsrv[2]; |
volatile uint32_t data; |
} regs_; |
}; |
|
DECLARE_CLASS(UART) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |
/* |
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
|
#ifndef __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |
#define __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/imemop.h" |
#include "coreservices/iserial.h" |
#include "coreservices/iwire.h" |
#include "coreservices/irawlistener.h" |
#include "coreservices/iclock.h" |
#include <string> |
|
namespace debugger { |
|
class UART : public IService, |
public IMemoryOperation, |
public ISerial { |
public: |
UART(const char *name); |
~UART(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IMemoryOperation */ |
virtual ETransStatus b_transport(Axi4TransactionType *trans); |
|
/** ISerial */ |
virtual int writeData(const char *buf, int sz); |
virtual void registerRawListener(IFace *listener); |
virtual void unregisterRawListener(IFace *listener); |
virtual void getListOfPorts(AttributeType *list); |
virtual int openPort(const char *port, AttributeType settings); |
virtual void closePort(); |
|
private: |
AttributeType irqctrl_; |
AttributeType listeners_; // non-registering attribute |
AttributeType autoTestEna_; |
AttributeType testCases_; |
IWire *iwire_; |
|
std::string input_; |
static const int RX_FIFO_SIZE = 16; |
char rxfifo_[RX_FIFO_SIZE]; |
char *p_rx_wr_; |
char *p_rx_rd_; |
int rx_total_; |
mutex_def mutexListeners_; |
|
struct uart_map { |
volatile uint32_t status; |
volatile uint32_t scaler; |
uint32_t rsrv[2]; |
volatile uint32_t data; |
} regs_; |
|
private: |
class AutoTest : public IClockListener { |
public: |
AutoTest(ISerial *parent, AttributeType *tests); |
|
/** IClockListener */ |
virtual void stepCallback(uint64_t t); |
private: |
ISerial *parent_; |
AttributeType tests_; |
unsigned testcnt_; |
}; |
AutoTest *pautotest_; |
}; |
|
DECLARE_CLASS(UART) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_SOCSIM_PLUGIN_UART_H__ |