URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [socsim_plugin/] [uart.cpp] - Rev 2
Go to most recent revision | Compare with Previous | Blame | View Log
/** * @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
Go to most recent revision | Compare with Previous | Blame | View Log