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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [socsim_plugin/] [uart.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      UART functional model.
6
 */
7
 
8
#include "api_core.h"
9
#include "uart.h"
10
 
11
namespace debugger {
12
 
13
static const uint32_t UART_STATUS_TX_FULL     = 0x00000001;
14
static const uint32_t UART_STATUS_TX_EMPTY    = 0x00000002;
15
static const uint32_t UART_STATUS_RX_FULL     = 0x00000010;
16
static const uint32_t UART_STATUS_RX_EMPTY    = 0x00000020;
17
static const uint32_t UART_STATUS_ERR_PARITY  = 0x00000100;
18
static const uint32_t UART_STATUS_ERR_STOPBIT = 0x00000200;
19
static const uint32_t UART_CONTROL_RX_IRQ_ENA = 0x00002000;
20
static const uint32_t UART_CONTROL_TX_IRQ_ENA = 0x00004000;
21
static const uint32_t UART_CONTROL_PARITY_ENA = 0x00008000;
22
 
23
 
24
UART::UART(const char *name)  : IService(name) {
25
    registerInterface(static_cast<IMemoryOperation *>(this));
26
    registerInterface(static_cast<ISerial *>(this));
27
    registerAttribute("BaseAddress", &baseAddress_);
28
    registerAttribute("Length", &length_);
29
    registerAttribute("IrqLine", &irqLine_);
30
    registerAttribute("IrqControl", &irqctrl_);
31
 
32
    baseAddress_.make_uint64(0);
33
    length_.make_uint64(0);
34
    irqLine_.make_uint64(0);
35
    irqctrl_.make_string("");
36
    listeners_.make_list(0);
37
    RISCV_mutex_init(&mutexListeners_);
38
 
39
    memset(&regs_, 0, sizeof(regs_));
40
    regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY;
41
 
42
    p_rx_wr_ = rxfifo_;
43
    p_rx_rd_ = rxfifo_;
44
    rx_total_ = 0;
45
}
46
 
47
UART::~UART() {
48
    RISCV_mutex_destroy(&mutexListeners_);
49
}
50
 
51
void UART::postinitService() {
52
    iwire_ = static_cast<IWire *>(
53
        RISCV_get_service_iface(irqctrl_.to_string(), IFACE_WIRE));
54
    if (!iwire_) {
55
        RISCV_error("Can't find IWire interface %s", irqctrl_.to_string());
56
    }
57
}
58
 
59
int UART::writeData(const char *buf, int sz) {
60
    if (sz > (RX_FIFO_SIZE - rx_total_)) {
61
        sz = (RX_FIFO_SIZE - rx_total_);
62
    }
63
    for (int i = 0; i < sz; i++) {
64
        rx_total_++;
65
        *p_rx_wr_ = buf[i];
66
        if ((++p_rx_wr_) >= (rxfifo_ + RX_FIFO_SIZE)) {
67
            p_rx_wr_ = rxfifo_;
68
        }
69
    }
70
 
71
    if (regs_.status & UART_CONTROL_RX_IRQ_ENA) {
72
        iwire_->raiseLine(irqLine_.to_int());
73
    }
74
    return sz;
75
}
76
 
77
void UART::registerRawListener(IFace *listener) {
78
    AttributeType lstn(listener);
79
    RISCV_mutex_lock(&mutexListeners_);
80
    listeners_.add_to_list(&lstn);
81
    RISCV_mutex_unlock(&mutexListeners_);
82
}
83
 
84
void UART::unregisterRawListener(IFace *listener) {
85
    for (unsigned i = 0; i < listeners_.size(); i++) {
86
        IFace *iface = listeners_[i].to_iface();
87
        if (iface == listener) {
88
            RISCV_mutex_lock(&mutexListeners_);
89
            listeners_.remove_from_list(i);
90
            RISCV_mutex_unlock(&mutexListeners_);
91
            break;
92
        }
93
    }
94
}
95
 
96
void UART::b_transport(Axi4TransactionType *trans) {
97
    uint64_t mask = (length_.to_uint64() - 1);
98
    uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
99
    char wrdata;
100
    trans->response = MemResp_Valid;
101
    if (trans->action == MemAction_Write) {
102
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
103
            if ((trans->wstrb & (0xf << 4*i)) == 0) {
104
                continue;
105
            }
106
            switch (off + i) {
107
            case 0:
108
                regs_.status = trans->wpayload.b32[i];
109
                RISCV_info("Set status = %08x", regs_.status);
110
                break;
111
            case 1:
112
                regs_.scaler = trans->wpayload.b32[i];
113
                RISCV_info("Set scaler = %d", regs_.scaler);
114
                break;
115
            case 4:
116
                wrdata = static_cast<char>(trans->wpayload.b32[i]);
117
                RISCV_info("Set data = %s", &regs_.data);
118
                RISCV_mutex_lock(&mutexListeners_);
119
                for (unsigned n = 0; n < listeners_.size(); n++) {
120
                    IRawListener *lstn = static_cast<IRawListener *>(
121
                                        listeners_[n].to_iface());
122
 
123
                    lstn->updateData(&wrdata, 1);
124
                }
125
                RISCV_mutex_unlock(&mutexListeners_);
126
                break;
127
            default:;
128
            }
129
        }
130
    } else {
131
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
132
            switch (off + i) {
133
            case 0:
134
                if (0) {
135
                    regs_.status &= ~UART_STATUS_TX_EMPTY;
136
                } else {
137
                    regs_.status |= UART_STATUS_TX_EMPTY;
138
                }
139
                if (rx_total_ == 0) {
140
                    regs_.status |= UART_STATUS_RX_EMPTY;
141
                } else {
142
                    regs_.status &= ~UART_STATUS_RX_EMPTY;
143
                }
144
                trans->rpayload.b32[i] = regs_.status;
145
                RISCV_info("Get status = %08x", regs_.status);
146
                break;
147
            case 1:
148
                trans->rpayload.b32[i] = regs_.scaler;
149
                RISCV_info("Get scaler = %d", regs_.scaler);
150
                break;
151
            case 4:
152
                if (rx_total_ == 0) {
153
                    trans->rpayload.b32[i] = 0;
154
                } else {
155
                    trans->rpayload.b32[i] = *p_rx_rd_;
156
                    rx_total_--;
157
                    if ((++p_rx_rd_) >= (rxfifo_ + RX_FIFO_SIZE)) {
158
                        p_rx_rd_ = rxfifo_;
159
                    }
160
                }
161
                RISCV_debug("Get data = %02x", (trans->rpayload.b32[i] & 0xFF));
162
                break;
163
            default:
164
                trans->rpayload.b32[i] = ~0;
165
            }
166
        }
167
    }
168
}
169
 
170
}  // namespace debugger
171
 

powered by: WebSVN 2.1.0

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