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

Subversion Repositories riscv_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /riscv_vhdl/trunk/debugger/src/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(&regs_, 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 *>(&regs_)[off], trans->wpayload.b8,
trans->xsize);
} else {
memcpy(trans->rpayload.b8, &reinterpret_cast<uint8_t *>(&regs_)[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(&regs_, 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 *>(&regs_)[off], trans->wpayload.b8,
trans->xsize);
} else {
memcpy(trans->rpayload.b8, &reinterpret_cast<uint8_t *>(&regs_)[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(&regs_, 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(&regs_.tmr.rw_MsLength)) {
RISCV_info("Set rw_MsLength = %d", regs_.tmr.rw_MsLength);
}
}
} else {
uint8_t *m = reinterpret_cast<uint8_t *>(&regs_);
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(&regs_, 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(&regs_.tmr.rw_MsLength)) {
RISCV_info("Set rw_MsLength = %d", regs_.tmr.rw_MsLength);
}
}
} else {
uint8_t *m = reinterpret_cast<uint8_t *>(&regs_);
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>(&regs_);
}
 
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>(&regs_);
}
 
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(&regs_, 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 *>(&regs_);
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>(&regs_.led)
- reinterpret_cast<uint64_t>(&regs_))) {
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(&regs_, 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 *>(&regs_);
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>(&regs_.led)
- reinterpret_cast<uint64_t>(&regs_))) {
/*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(&regs_, 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(&regs_, 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(&regs_, 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(&regs_, 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(&regs_, 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 *>(&regs_);
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(&regs_, 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 *>(&regs_);
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(&regs_, 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(&regs_, 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(&regs_, 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", &regs_.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(&regs_, 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", &regs_.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__

powered by: WebSVN 2.1.0

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