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

Subversion Repositories riscv_vhdl

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 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 "iotypes.h"
19
 
20
namespace debugger {
21
 
22
IOReg8Type::IOReg8Type(IService *parent, const char *name,
23
                  uint16_t addr, uint16_t len, int priority) {
24
    if (parent == NULL) {
25
    } else {
26
        parent->registerPortInterface(name,
27
                static_cast<IMemoryOperation *>(this));
28
        parent->registerPortInterface(name, static_cast<IIOPort *>(this));
29
        parent->registerPortInterface(name,
30
                static_cast<IResetListener *>(this));
31
    }
32
    parent_ = parent;
33
    portListeners_.make_list(0);
34
    regname_.make_string(name);
35
    baseAddress_.make_uint64(addr);
36
    length_.make_uint64(len);
37
    priority_.make_int64(priority);
38
    value.byte = 0;
39
    hard_reset_value_ = 0;
40
}
41
 
42
IFace *IOReg8Type::getInterface(const char *name) {
43
    if (strcmp(name, IFACE_MEMORY_OPERATION) == 0) {
44
        return static_cast<IMemoryOperation *>(this);
45
    }
46
    return parent_->getInterface(name);
47
}
48
 
49
void IOReg8Type::reset(bool active) {
50
    if (!active) {
51
        return;
52
    }
53
    write(hard_reset_value_);
54
}
55
 
56
ETransStatus IOReg8Type::b_transport(Axi4TransactionType *trans) {
57
    uint16_t addr = static_cast<uint16_t>(trans->addr);
58
    if (trans->action == MemAction_Read) {
59
        trans->rpayload.b8[0] = read();
60
        RISCV_debug("Read %s [%02x] => %02x",
61
                    regName(), addr, trans->rpayload.b8[0]);
62
    } else {
63
        write(trans->wpayload.b8[0]);
64
        RISCV_debug("Write %s [%02x] <= %02x",
65
                    regName(), addr, trans->wpayload.b8[0]);
66
    }
67
    return TRANS_OK;
68
}
69
 
70
uint8_t IOReg8Type::read() {
71
    IIOPortListener *lstn;
72
    uint8_t odata = value.byte;
73
    for (unsigned i = 0; i < portListeners_.size(); i++) {
74
        lstn = static_cast<IIOPortListener *>(portListeners_[i].to_iface());
75
        lstn->readData(&odata, get_direction());
76
    }
77
    return odata;
78
}
79
 
80
void IOReg8Type::write(uint8_t data) {
81
    IIOPortListener *lstn;
82
    value.byte = data;
83
    for (unsigned i = 0; i < portListeners_.size(); i++) {
84
        lstn = static_cast<IIOPortListener *>(portListeners_[i].to_iface());
85
        lstn->writeData(data, get_direction());
86
    }
87
    for (unsigned i = 0; i < portListeners_.size(); i++) {
88
        lstn = static_cast<IIOPortListener *>(portListeners_[i].to_iface());
89
        lstn->latch();
90
    }
91
}
92
 
93
void IOReg8Type::registerPortListener(IFace *listener) {
94
    AttributeType item;
95
    item.make_iface(listener);
96
    portListeners_.add_to_list(&item);
97
}
98
 
99
void IOReg8Type::unregisterPortListener(IFace *listener) {
100
    for (unsigned i = 0; i < portListeners_.size(); i++) {
101
        if (listener == portListeners_[i].to_iface()) {
102
            portListeners_.remove_from_list(i);
103
            break;
104
        }
105
    }
106
}
107
 
108
/** */
109
IOPinType::IOPinType(IService *parent, const char *name) : parent_(parent) {
110
    pinName_.make_string(name);
111
    iwire_ = 0;
112
    value_ = 0;
113
    bitIdx_ = 0;
114
    access_ = 0;
115
 
116
    char tstr[256];
117
    RISCV_sprintf(tstr, sizeof(tstr), "pin_%s", name);
118
    parent_->registerAttribute(tstr, &IOPinTypeCfg_);
119
}
120
 
121
// Memory access use direction xDD register value (IN/OUT)
122
void IOPinType::readData(uint8_t *val, uint8_t mask) {
123
    uint8_t v;
124
    if (iwire_ && (access_ & READ_MASK)) {
125
        v = iwire_->getLevel();
126
    } else {
127
        v = aboutToRead(value_);
128
    }
129
    *val &= ~(1 << bitIdx_);
130
    *val |= (v << bitIdx_);
131
}
132
 
133
void IOPinType::writeData(uint8_t val, uint8_t mask) {
134
    prelatch_ = (val >> bitIdx_) & 0x1;
135
    if (iwire_ && (access_ & WRITE_MASK) && (mask & (1u << bitIdx_))) {
136
        iwire_->setLevel(prelatch_ == 0 ? false : true);
137
    } else {
138
        aboutToWrite(value_, prelatch_);
139
    }
140
}
141
 
142
// Direct access to wire doesn't use Direction xDD mask register
143
uint8_t IOPinType::get_bit() {
144
    if (iwire_ && (access_ & READ_MASK)) {
145
        return iwire_->getLevel() ? 1u : 0;
146
    }
147
    return value_;
148
}
149
 
150
void IOPinType::set_bit(uint8_t v) {
151
    if (iwire_ && (access_ & WRITE_MASK)) {
152
        iwire_->setLevel(v == 0 ? false : true);
153
    }
154
    prelatch_ = v;
155
    value_ = prelatch_;
156
}
157
 
158
 
159
void IOPinType::latch() {
160
    value_ = prelatch_;
161
}
162
 
163
void IOPinType::postinit() {
164
    connectToBit(IOPinTypeCfg_);
165
    if (IOPinTypeCfg_.size() >= 3) {
166
        connectToWire(IOPinTypeCfg_[2]);
167
    }
168
}
169
 
170
void IOPinType::connectToBit(const AttributeType &cfg) {
171
    if (!cfg.is_list() || cfg.size() < 2) {
172
        RISCV_printf(NULL, LOG_ERROR,
173
            "Cannot connect IOPinType %s: Wrong format of port attribute",
174
            pinName_.to_string());
175
        return;
176
    }
177
    IIOPort *iport = 0;
178
    if (cfg[0u].is_string()) {
179
        iport = static_cast<IIOPort *>(RISCV_get_service_iface(
180
                cfg[0u].to_string(), IFACE_IOPORT));
181
    } else if (cfg[0u].is_list()) {
182
        const AttributeType &prt = cfg[0u];
183
        iport = static_cast<IIOPort *>(RISCV_get_service_port_iface(
184
                prt[0u].to_string(), prt[1].to_string(), IFACE_IOPORT));
185
    }
186
    bitIdx_ = cfg[1].to_int();
187
 
188
    if (iport == 0) {
189
        RISCV_printf(NULL, LOG_ERROR,
190
            "Cannot connect IOPinType: Can't get port interface %s",
191
             cfg[0u].to_string());
192
        return;
193
    }
194
    iport->registerPortListener(static_cast<IIOPortListener *>(this));
195
}
196
 
197
void IOPinType::connectToWire(const AttributeType &cfg) {
198
    if (!cfg.is_list() || cfg.size() < 2) {
199
        RISCV_printf(NULL, LOG_ERROR,
200
            "[%s] Cannot connect IWire input: wrong attribute",
201
            pinName_.to_string());
202
        return;
203
    }
204
    const char *rw;
205
    if (cfg.size() == 2) {
206
        iwire_ = static_cast<IWire *>(RISCV_get_service_iface(
207
                cfg[0u].to_string(), IFACE_WIRE));
208
        rw = cfg[1].to_string();
209
    } else {
210
        iwire_ = static_cast<IWire *>(RISCV_get_service_port_iface(
211
                cfg[0u].to_string(), cfg[1].to_string(), IFACE_WIRE));
212
        rw = cfg[2].to_string();
213
    }
214
    if (!iwire_) {
215
        RISCV_printf(NULL, LOG_ERROR,
216
            "[%s] Cannot find IWire interface in %s",
217
            pinName_.to_string(), cfg[0u].to_string());
218
        return;
219
    }
220
 
221
    access_ = 0;
222
    if (strstr(rw, "r")) {
223
        access_ |= READ_MASK;
224
        prelatch_ = iwire_->getLevel();
225
        value_ = prelatch_;
226
    }
227
    if (strstr(rw, "w")) {
228
        access_ |= WRITE_MASK;
229
    }
230
}
231
 
232
}  // namespace debugger
233
 

powered by: WebSVN 2.1.0

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