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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [common/] [debug/] [dsu.cpp] - Rev 5

Compare with Previous | Blame | View Log

/**
 * @file
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
 * @brief      Debug Support Unit (DSU) functional model.
 */
 
#include <api_core.h>
#include "dsu.h"
 
namespace debugger {
 
DSU::DSU(const char *name)  : IService(name) {
    registerInterface(static_cast<IMemoryOperation *>(this));
    registerInterface(static_cast<IDbgNbResponse *>(this));
    registerInterface(static_cast<IDsuGeneric *>(this));
    registerAttribute("CPU", &cpu_);
    registerAttribute("Bus", &bus_);
 
    memset(&info_, 0, sizeof(info_));
    soft_reset_ = 0x0;  // Active LOW
}
 
DSU::~DSU() {
}
 
void DSU::postinitService() {
    icpu_ = static_cast<ICpuGeneric *>(
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_GENERIC));
    if (!icpu_) {
        RISCV_error("Can't find ICpuGeneric interface %s", cpu_.to_string());
    }
    icpurst_ = static_cast<IResetListener *>(
        RISCV_get_service_iface(cpu_.to_string(), IFACE_RESET_LISTENER));
    if (!icpurst_) {
        RISCV_error("Can't find IResetListener interface %s",
                    cpu_.to_string());
    }
    ibus_ = static_cast<IMemoryOperation *>(
        RISCV_get_service_iface(bus_.to_string(), IFACE_MEMORY_OPERATION));
    if (!ibus_) {
        RISCV_error("Can't find IBus interface %s", bus_.to_string());
    }
}
 
ETransStatus DSU::b_transport(Axi4TransactionType *trans) {
    uint64_t mask = (length_.to_uint64() - 1);
    uint64_t off64 = (trans->addr - getBaseAddress()) & mask;
    if (!icpu_) {
        trans->response = MemResp_Error;
        return TRANS_ERROR;
    }
    uint64_t region = (off64 >> 15) & 0x3;
 
    if (region < 3) {
        RISCV_error("b_transport() to debug port NOT SUPPORTED", NULL);
        trans->response = MemResp_Error;
        return TRANS_ERROR;
    }
 
    if (trans->action == MemAction_Read) {
        readLocal(off64 & 0x7fff, trans);
    } else {
        writeLocal(off64 & 0x7fff, trans);
    }
 
    trans->response = MemResp_Valid;
    // @todo Memory mapped registers not related to debug port
    return TRANS_OK;
}
 
ETransStatus DSU::nb_transport(Axi4TransactionType *trans,
                               IAxi4NbResponse *cb) {
    uint64_t mask = (length_.to_uint64() - 1);
    uint64_t off64 = (trans->addr - getBaseAddress()) & mask;
    if (!icpu_) {
        trans->response = MemResp_Error;
        cb->nb_response(trans);
        return TRANS_ERROR;
    }
 
    nb_trans_.p_axi_trans = trans;
    nb_trans_.iaxi_cb = cb;
 
    nb_trans_.dbg_trans.write = 0;
    nb_trans_.dbg_trans.bytes = trans->xsize;
    if (trans->action == MemAction_Write) {
        nb_trans_.dbg_trans.write = 1;
        nb_trans_.dbg_trans.wdata = trans->wpayload.b64[0];
    }
 
    ETransStatus ret = TRANS_OK;
    nb_trans_.dbg_trans.addr = off64 & 0x7FFF;
    nb_trans_.dbg_trans.region = (off64 >> 15) & 0x3;
    if (nb_trans_.dbg_trans.region == 3) {
        ret = b_transport(trans);
        cb->nb_response(trans);
    } else {
        icpu_->nb_transport_debug_port(&nb_trans_.dbg_trans, this);
    }
    return ret;
}
 
void DSU::nb_response_debug_port(DebugPortTransactionType *trans) {
    nb_trans_.p_axi_trans->response = MemResp_Valid;
    nb_trans_.p_axi_trans->rpayload.b64[0] = trans->rdata;
    nb_trans_.iaxi_cb->nb_response(nb_trans_.p_axi_trans);
}
 
void DSU::readLocal(uint64_t off, Axi4TransactionType *trans) {
    switch (off >> 3) {
    case 0:
        trans->rpayload.b64[0] = soft_reset_;
        break;
    case 8:
        trans->rpayload.b64[0] = info_[0].w_cnt;
        break;
    case 9:
        trans->rpayload.b64[0] = info_[0].r_cnt;
        break;
    case 12:
        trans->rpayload.b64[0] = info_[2].w_cnt;
        break;
    case 13:
        trans->rpayload.b64[0] = info_[2].r_cnt;
        break;
    default:
        trans->rpayload.b64[0] = 0;
    }
    if (trans->xsize == 4 && (off & 0x4) == 0x4) {
        trans->rpayload.b64[0] >>= 32;
    }
}
 
void DSU::writeLocal(uint64_t off, Axi4TransactionType *trans) {
    if (trans->xsize == 4) {
        if ((off & 0x4) == 0) {
            wdata64_ = trans->wpayload.b32[0];
            return;
        } else {
            wdata64_ |= static_cast<uint64_t>(trans->wpayload.b32[0]) << 32;
        }
    } else {
        wdata64_ = trans->wpayload.b64[0];
    }
    switch (off >> 3) {
    case 0:     // soft reset
        if (wdata64_ & 0x1) {
            icpurst_->reset(true);
        } else {
            icpurst_->reset(false);
        }
        soft_reset_ = wdata64_;
        break;
    default:;
    }
}
 
void DSU::incrementRdAccess(int mst_id) {
    info_[mst_id].r_cnt++;
}
 
void DSU::incrementWrAccess(int mst_id) {
    info_[mst_id].w_cnt++;
}
 
}  // namespace debugger
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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