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 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/*
2
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 */
16
 
17
#include "api_core.h"
18
#include "uart.h"
19
 
20
namespace debugger {
21
 
22
static const uint32_t UART_STATUS_TX_FULL     = 0x00000001;
23
static const uint32_t UART_STATUS_TX_EMPTY    = 0x00000002;
24
static const uint32_t UART_STATUS_RX_FULL     = 0x00000010;
25
static const uint32_t UART_STATUS_RX_EMPTY    = 0x00000020;
26
static const uint32_t UART_STATUS_ERR_PARITY  = 0x00000100;
27
static const uint32_t UART_STATUS_ERR_STOPBIT = 0x00000200;
28
static const uint32_t UART_CONTROL_RX_IRQ_ENA = 0x00002000;
29
static const uint32_t UART_CONTROL_TX_IRQ_ENA = 0x00004000;
30
static const uint32_t UART_CONTROL_PARITY_ENA = 0x00008000;
31
 
32
 
33
UART::UART(const char *name)  : IService(name) {
34
    registerInterface(static_cast<IMemoryOperation *>(this));
35
    registerInterface(static_cast<ISerial *>(this));
36
    registerAttribute("IrqControl", &irqctrl_);
37
    registerAttribute("AutoTestEna", &autoTestEna_);
38
    registerAttribute("TestCases", &testCases_);
39
 
40
    listeners_.make_list(0);
41
    RISCV_mutex_init(&mutexListeners_);
42
 
43
    memset(&regs_, 0, sizeof(regs_));
44
    regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY;
45
 
46
    p_rx_wr_ = rxfifo_;
47
    p_rx_rd_ = rxfifo_;
48
    rx_total_ = 0;
49
    pautotest_ = NULL;
50
}
51
 
52
UART::~UART() {
53
    RISCV_mutex_destroy(&mutexListeners_);
54
    if (pautotest_) {
55
        delete pautotest_;
56
    }
57
}
58
 
59
void UART::postinitService() {
60
    iwire_ = static_cast<IWire *>(
61
        RISCV_get_service_port_iface(irqctrl_[0u].to_string(),
62
                                     irqctrl_[1].to_string(),
63
                                     IFACE_WIRE));
64
    if (!iwire_) {
65
        RISCV_error("Can't find IWire interface %s", irqctrl_[0u].to_string());
66
    }
67
    if (autoTestEna_.to_bool()) {
68
        pautotest_ = new AutoTest(static_cast<ISerial *>(this), &testCases_);
69
    }
70
}
71
 
72
int UART::writeData(const char *buf, int sz) {
73
    if (sz > (RX_FIFO_SIZE - rx_total_)) {
74
        sz = (RX_FIFO_SIZE - rx_total_);
75
    }
76
    for (int i = 0; i < sz; i++) {
77
        rx_total_++;
78
        *p_rx_wr_ = buf[i];
79
        if ((++p_rx_wr_) >= (rxfifo_ + RX_FIFO_SIZE)) {
80
            p_rx_wr_ = rxfifo_;
81
        }
82
    }
83
 
84
    if (regs_.status & UART_CONTROL_RX_IRQ_ENA) {
85
        iwire_->raiseLine();
86
    }
87
    return sz;
88
}
89
 
90
void UART::registerRawListener(IFace *listener) {
91
    AttributeType lstn(listener);
92
    RISCV_mutex_lock(&mutexListeners_);
93
    listeners_.add_to_list(&lstn);
94
    RISCV_mutex_unlock(&mutexListeners_);
95
}
96
 
97
void UART::unregisterRawListener(IFace *listener) {
98
    for (unsigned i = 0; i < listeners_.size(); i++) {
99
        IFace *iface = listeners_[i].to_iface();
100
        if (iface == listener) {
101
            RISCV_mutex_lock(&mutexListeners_);
102
            listeners_.remove_from_list(i);
103
            RISCV_mutex_unlock(&mutexListeners_);
104
            break;
105
        }
106
    }
107
}
108
 
109
void UART::getListOfPorts(AttributeType *list) {
110
    list->make_list(0);
111
}
112
 
113
int UART::openPort(const char *port, AttributeType settings) {
114
    return 0;
115
}
116
 
117
void UART::closePort() {
118
}
119
 
120
 
121
ETransStatus UART::b_transport(Axi4TransactionType *trans) {
122
    uint64_t mask = (length_.to_uint64() - 1);
123
    uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
124
    char wrdata;
125
    trans->response = MemResp_Valid;
126
    if (trans->action == MemAction_Write) {
127
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
128
            if ((trans->wstrb & (0xf << 4*i)) == 0) {
129
                continue;
130
            }
131
            switch (off + i) {
132
            case 0:
133
                regs_.status = trans->wpayload.b32[i];
134
                RISCV_info("Set status = %08x", regs_.status);
135
                break;
136
            case 1:
137
                regs_.scaler = trans->wpayload.b32[i];
138
                RISCV_info("Set scaler = %d", regs_.scaler);
139
                break;
140
            case 4:
141
                wrdata = static_cast<char>(trans->wpayload.b32[i]);
142
                RISCV_info("Set data = %s", &regs_.data);
143
                RISCV_mutex_lock(&mutexListeners_);
144
                for (unsigned n = 0; n < listeners_.size(); n++) {
145
                    IRawListener *lstn = static_cast<IRawListener *>(
146
                                        listeners_[n].to_iface());
147
 
148
                    lstn->updateData(&wrdata, 1);
149
                }
150
                RISCV_mutex_unlock(&mutexListeners_);
151
                break;
152
            default:;
153
            }
154
        }
155
    } else {
156
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
157
            switch (off + i) {
158
            case 0:
159
                if (0) {
160
                    regs_.status &= ~UART_STATUS_TX_EMPTY;
161
                } else {
162
                    regs_.status |= UART_STATUS_TX_EMPTY;
163
                }
164
                if (rx_total_ == 0) {
165
                    regs_.status |= UART_STATUS_RX_EMPTY;
166
                } else {
167
                    regs_.status &= ~UART_STATUS_RX_EMPTY;
168
                }
169
                trans->rpayload.b32[i] = regs_.status;
170
                RISCV_info("Get status = %08x", regs_.status);
171
                break;
172
            case 1:
173
                trans->rpayload.b32[i] = regs_.scaler;
174
                RISCV_info("Get scaler = %d", regs_.scaler);
175
                break;
176
            case 4:
177
                if (rx_total_ == 0) {
178
                    trans->rpayload.b32[i] = 0;
179
                } else {
180
                    trans->rpayload.b32[i] = *p_rx_rd_;
181
                    rx_total_--;
182
                    if ((++p_rx_rd_) >= (rxfifo_ + RX_FIFO_SIZE)) {
183
                        p_rx_rd_ = rxfifo_;
184
                    }
185
                }
186
                RISCV_debug("Get data = %02x", (trans->rpayload.b32[i] & 0xFF));
187
                break;
188
            default:
189
                trans->rpayload.b32[i] = ~0;
190
            }
191
        }
192
    }
193
    return TRANS_OK;
194
}
195
 
196
/**
197
 * CPU validation purpose. Reaction on keyboard interrupt:
198
 */
199
 
200
UART::AutoTest::AutoTest(ISerial *parent, AttributeType *tests) {
201
    parent_ = parent;
202
    tests_ = *tests;
203
    testcnt_ = 0;
204
    IClock *iclk = static_cast<IClock *>(
205
            RISCV_get_service_iface("core0", IFACE_CLOCK));
206
    if (iclk && tests_.is_list() && tests_.size()) {
207
        const AttributeType &t0 = tests_[testcnt_];
208
        if (t0.size() == 2) {
209
            iclk->registerStepCallback(static_cast<IClockListener *>(this),
210
                                       t0[0u].to_uint64());
211
        }
212
    }
213
}
214
 
215
void UART::AutoTest::stepCallback(uint64_t t) {
216
    const AttributeType &tn = tests_[testcnt_];
217
    char msg[64];
218
    int msglen = 0;
219
    const char *pbuf = tn[1].to_string();
220
    for (unsigned i = 0; i < tn[1].size(); i++) {
221
        if (pbuf[i] == '\\' && pbuf[i+1] == 'r') {
222
            ++i;
223
            msg[msglen++] = '\r';
224
            msg[msglen] = '\0';
225
            continue;
226
        } else if (pbuf[i] == '\\' && pbuf[i+1] == 'n') {
227
            ++i;
228
            msg[msglen++] = '\n';
229
            msg[msglen] = '\0';
230
            continue;
231
        }
232
        msg[msglen++] = pbuf[i];
233
        msg[msglen] = '\0';
234
    }
235
    parent_->writeData(msg, msglen);
236
 
237
    if (++testcnt_ < tests_.size()) {
238
        const AttributeType &t0 = tests_[testcnt_];
239
        IClock *iclk = static_cast<IClock *>(
240
                RISCV_get_service_iface("core0", IFACE_CLOCK));
241
        iclk->registerStepCallback(static_cast<IClockListener *>(this),
242
                                   t0[0u].to_uint64());
243
    }
244
}
245
 
246
}  // namespace debugger
247
 

powered by: WebSVN 2.1.0

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