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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [common/] [debug/] [greth.cpp] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Ethernet MAC device functional model.
6
 */
7
 
8
#include <api_core.h>
9
#include "greth.h"
10
#include "coreservices/isocinfo.h"
11
 
12
namespace debugger {
13
 
14
/** Class registration in the Core */
15
REGISTER_CLASS(Greth)
16
 
17
Greth::Greth(const char *name)
18
    : IService(name) {
19
    registerInterface(static_cast<IThread *>(this));
20
    registerInterface(static_cast<IMemoryOperation *>(this));
21
    registerInterface(static_cast<IAxi4NbResponse *>(this));
22
    registerAttribute("IP", &ip_);
23
    registerAttribute("MAC", &mac_);
24
    registerAttribute("Bus", &bus_);
25
    registerAttribute("Transport", &transport_);
26
    registerAttribute("SysBusMasterID", &sysBusMasterID_);
27
 
28
    memset(txbuf_, 0, sizeof(txbuf_));
29
    seq_cnt_ = 35;
30
    RISCV_event_create(&event_tap_, "UART_event_tap");
31
}
32
Greth::~Greth() {
33
    RISCV_event_close(&event_tap_);
34
}
35
 
36
void Greth::postinitService() {
37
    ibus_ = static_cast<IMemoryOperation *>(
38
       RISCV_get_service_iface(bus_.to_string(), IFACE_MEMORY_OPERATION));
39
 
40
    if (!ibus_) {
41
        RISCV_error("Bus interface '%s' not found",
42
                    bus_.to_string());
43
        return;
44
    }
45
 
46
    itransport_ = static_cast<ILink *>(
47
        RISCV_get_service_iface(transport_.to_string(), IFACE_LINK));
48
 
49
    if (!itransport_) {
50
        RISCV_error("UDP interface '%s' not found",
51
                    bus_.to_string());
52
        return;
53
    }
54
 
55
    AttributeType clks;
56
    RISCV_get_clock_services(&clks);
57
    if (clks.size()) {
58
        iclk0_ = static_cast<IClock *>(clks[0u].to_iface());
59
    } else {
60
        RISCV_error("CPUs not found", NULL);
61
    }
62
 
63
    // Get global settings:
64
    const AttributeType *glb = RISCV_get_global_settings();
65
    if ((*glb)["SimEnable"].to_bool()) {
66
        if (!run()) {
67
            RISCV_error("Can't create thread.", NULL);
68
            return;
69
        }
70
    }
71
}
72
 
73
void Greth::busyLoop() {
74
    int bytes;
75
    uint8_t *tbuf;
76
    uint32_t bytes_to_read;
77
    UdpEdclCommonType req;
78
    RISCV_info("Ethernet thread was started", NULL);
79
    trans_.source_idx = sysBusMasterID_.to_int();
80
 
81
    while (isEnabled()) {
82
        bytes =
83
            itransport_->readData(rxbuf_, static_cast<int>(sizeof(rxbuf_)));
84
 
85
        if (bytes == 0) {
86
            continue;
87
        }
88
 
89
        req.control.word = read32(&rxbuf_[2]);
90
        req.address      = read32(&rxbuf_[6]);
91
        if (seq_cnt_ != req.control.request.seqidx) {
92
            sendNAK(&req);
93
            continue;
94
        }
95
 
96
        trans_.addr = req.address;
97
        if (req.control.request.write == 0) {
98
            trans_.action = MemAction_Read;
99
            trans_.wstrb = 0;
100
            tbuf = &txbuf_[10];
101
            bytes = sizeof(UdpEdclCommonType) + req.control.request.len;
102
        } else {
103
            trans_.action = MemAction_Write;
104
            tbuf = &rxbuf_[10];
105
            bytes = sizeof(UdpEdclCommonType);
106
        }
107
        bytes_to_read = req.control.request.len;
108
        while (bytes_to_read) {
109
            trans_.xsize = bytes_to_read;
110
            if (trans_.xsize > 8) {
111
                trans_.xsize = 8;
112
            }
113
            if (trans_.action == MemAction_Write) {
114
                memcpy(trans_.wpayload.b8, tbuf, trans_.xsize);
115
                trans_.wstrb = (1 << trans_.xsize) - 1;
116
            }
117
            RISCV_event_clear(&event_tap_);
118
            ibus_->nb_transport(&trans_, this);
119
            if (RISCV_event_wait_ms(&event_tap_, 500) != 0) {
120
                RISCV_error("CPU queue callback timeout", NULL);
121
            } else if (trans_.action == MemAction_Read) {
122
                memcpy(tbuf, trans_.rpayload.b8, trans_.xsize);
123
            }
124
            tbuf += trans_.xsize;
125
            trans_.addr += trans_.xsize;
126
            bytes_to_read -= trans_.xsize;
127
        }
128
 
129
        req.control.response.nak = 0;
130
        req.control.response.seqidx = seq_cnt_;
131
        write32(&txbuf_[2], req.control.word);
132
 
133
        seq_cnt_++;
134
        itransport_->sendData(txbuf_, bytes);
135
    }
136
}
137
 
138
void Greth::nb_response(Axi4TransactionType *trans) {
139
    RISCV_event_set(&event_tap_);
140
}
141
 
142
ETransStatus Greth::b_transport(Axi4TransactionType *trans) {
143
    RISCV_error("ETH Slave registers not implemented", NULL);
144
    return TRANS_OK;
145
}
146
 
147
void Greth::sendNAK(UdpEdclCommonType *req) {
148
    req->control.response.nak = 1;
149
    req->control.response.seqidx = seq_cnt_;
150
    req->control.response.len = 0;
151
    write32(&txbuf_[2], req->control.word);
152
    write32(&txbuf_[6], req->address);
153
 
154
    itransport_->sendData(txbuf_, sizeof(UdpEdclCommonType));
155
}
156
 
157
uint32_t Greth::read32(uint8_t *buf) {
158
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0);
159
}
160
 
161
void Greth::write32(uint8_t *buf, uint32_t v) {
162
    buf[0] = static_cast<char>((v >> 24) & 0xFF);
163
    buf[1] = static_cast<char>((v >> 16) & 0xFF);
164
    buf[2] = static_cast<char>((v >> 8) & 0xFF);
165
    buf[3] = static_cast<char>(v & 0xFF);
166
}
167
 
168
}  // namespace debugger

powered by: WebSVN 2.1.0

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