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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [socsim_plugin/] [irqctrl.cpp] - Diff between revs 2 and 4

Show entire file | Details | Blame | View Log

Rev 2 Rev 4
Line 5... Line 5...
 * @brief      Interrupt controller functional model.
 * @brief      Interrupt controller functional model.
 */
 */
 
 
#include "api_core.h"
#include "api_core.h"
#include "irqctrl.h"
#include "irqctrl.h"
 
#include <riscv-isa.h>
 
#include "coreservices/icpuriscv.h"
 
 
namespace debugger {
namespace debugger {
 
 
 
IrqPort::IrqPort(IService *parent, const char *portname, int idx) {
 
    parent_ = parent;
 
    parent->registerPortInterface(portname, static_cast<IWire *>(this));
 
    idx_ = idx;
 
    level_ = false;
 
};
 
 
 
void IrqPort::raiseLine() {
 
    level_ = true;
 
    static_cast<IrqController *>(parent_)->requestInterrupt(idx_);
 
}
 
 
 
void IrqPort::setLevel(bool level) {
 
    if (!level_ && level) {
 
        raiseLine();
 
    } else if (level_ && !level) {
 
        lowerLine();
 
    }
 
}
 
 
IrqController::IrqController(const char *name)  : IService(name) {
IrqController::IrqController(const char *name)  : IService(name) {
    registerInterface(static_cast<IMemoryOperation *>(this));
    registerInterface(static_cast<IMemoryOperation *>(this));
    registerInterface(static_cast<IWire *>(this));
    registerInterface(static_cast<IClockListener *>(this));
    registerAttribute("BaseAddress", &baseAddress_);
 
    registerAttribute("Length", &length_);
 
    registerAttribute("CPU", &cpu_);
    registerAttribute("CPU", &cpu_);
    registerAttribute("CSR_MIPI", &mipi_);
    registerAttribute("CSR_MIPI", &mipi_);
    registerAttribute("IrqTotal", &irqTotal_);
    registerAttribute("IrqTotal", &irqTotal_);
 
 
    baseAddress_.make_uint64(0);
    char portname[256];
 
    for (int i = 1; i < IRQ_MAX; i++) {
 
        RISCV_sprintf(portname, sizeof(portname), "irq%d", i);
 
        irqlines_[i] = new IrqPort(this, portname, i);
 
    }
 
 
    mipi_.make_uint64(0x783);
    mipi_.make_uint64(0x783);
    length_.make_uint64(0);
 
    cpu_.make_string("");
    cpu_.make_string("");
    irqTotal_.make_uint64(4);
    irqTotal_.make_uint64(4);
 
 
    memset(&regs_, 0, sizeof(regs_));
    memset(&regs_, 0, sizeof(regs_));
    regs_.irq_mask = ~0;
    regs_.irq_mask = ~0;
    regs_.irq_lock = 1;
    regs_.irq_lock = 1;
    irq_wait_unlock = 0;
 
}
}
 
 
IrqController::~IrqController() {
IrqController::~IrqController() {
}
}
 
 
void IrqController::postinitService() {
void IrqController::postinitService() {
    icpu_ = static_cast<ICpuRiscV *>(
    iclk_ = static_cast<IClock *>(
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_RISCV));
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CLOCK));
 
    if (!iclk_) {
 
        RISCV_error("Can't find IClock interface %s", cpu_.to_string());
 
        return;
 
    }
 
 
 
    icpu_ = static_cast<ICpuGeneric *>(
 
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_GENERIC));
    if (!icpu_) {
    if (!icpu_) {
        RISCV_error("Can't find ICpuRiscV interface %s", cpu_.to_string());
        RISCV_error("Can't find ICpuRiscV interface %s", cpu_.to_string());
 
        return;
    }
    }
 
    uint64_t t = iclk_->getStepCounter();
 
    iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1);
}
}
 
 
void IrqController::b_transport(Axi4TransactionType *trans) {
ETransStatus IrqController::b_transport(Axi4TransactionType *trans) {
    uint64_t mask = (length_.to_uint64() - 1);
    uint64_t mask = (length_.to_uint64() - 1);
    uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
    uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
    uint32_t t1;
    uint32_t t1;
    trans->response = MemResp_Valid;
    trans->response = MemResp_Valid;
    if (trans->action == MemAction_Write) {
    if (trans->action == MemAction_Write) {
Line 64... Line 97...
                break;
                break;
            case 2:
            case 2:
                t1 = regs_.irq_pending;
                t1 = regs_.irq_pending;
                regs_.irq_pending &= ~trans->wpayload.b32[i];
                regs_.irq_pending &= ~trans->wpayload.b32[i];
                if (t1 && !regs_.irq_pending) {
                if (t1 && !regs_.irq_pending) {
                    icpu_->lowerSignal(CPU_SIGNAL_EXT_IRQ);
                    icpu_->lowerSignal(INTERRUPT_MExternal);
                }
                }
                RISCV_info("Set irq_clear = %08x", trans->wpayload.b32[i]);
                RISCV_info("Set irq_clear = %08x", trans->wpayload.b32[i]);
                break;
                break;
            case 3:
            case 3:
                regs_.irq_pending |= trans->wpayload.b32[i];
                regs_.irq_pending |= trans->wpayload.b32[i];
Line 113... Line 146...
                            trans->wpayload.b32[i]);
                            trans->wpayload.b32[i]);
                break;
                break;
            case 10:
            case 10:
                regs_.irq_lock = trans->wpayload.b32[i];
                regs_.irq_lock = trans->wpayload.b32[i];
                RISCV_info("Set irq_ena = %08x", trans->wpayload.b32[i]);
                RISCV_info("Set irq_ena = %08x", trans->wpayload.b32[i]);
                if (regs_.irq_lock == 0 && (regs_.irq_pending ||irq_wait_unlock)) {
                if (regs_.irq_lock == 0 && regs_.irq_pending) {
                    regs_.irq_pending |= irq_wait_unlock;
                    icpu_->lowerSignal(INTERRUPT_MExternal);
                    icpu_->raiseSignal(CPU_SIGNAL_EXT_IRQ);
 
                    irq_wait_unlock = 0;
 
                } else if (regs_.irq_lock == 1 && regs_.irq_pending) {
 
                    icpu_->lowerSignal(CPU_SIGNAL_EXT_IRQ);
 
                }
                }
                break;
                break;
            case 11:
            case 11:
                regs_.irq_cause_idx = trans->wpayload.b32[i];
                regs_.irq_cause_idx = trans->wpayload.b32[i];
                RISCV_info("Set irq_cause_idx = %08x", trans->wpayload.b32[i]);
                RISCV_info("Set irq_cause_idx = %08x", trans->wpayload.b32[i]);
Line 197... Line 226...
            default:
            default:
                trans->rpayload.b32[i] = ~0;
                trans->rpayload.b32[i] = ~0;
            }
            }
        }
        }
    }
    }
 
    return TRANS_OK;
}
}
 
 
void IrqController::raiseLine(int idx) {
void IrqController::stepCallback(uint64_t t) {
    if (regs_.irq_lock) {
    iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1);
        irq_wait_unlock |= (~regs_.irq_mask & (1 << idx));
    if (regs_.irq_lock == 1) {
        return;
        return;
    }
    }
    if ((regs_.irq_mask & (0x1 << idx)) == 0) {
    if (~regs_.irq_mask & regs_.irq_pending) {
        regs_.irq_pending |= (0x1 << idx);
        icpu_->raiseSignal(INTERRUPT_MExternal);   // PLIC interrupt (external)
        icpu_->raiseSignal(CPU_SIGNAL_EXT_IRQ);   // PLIC interrupt (external)
        RISCV_debug("Raise interrupt", NULL);
        RISCV_info("Raise interrupt", NULL);
 
    }
    }
}
}
 
 
 
void IrqController::requestInterrupt(int idx) {
 
    regs_.irq_pending |= (0x1 << idx);
 
    RISCV_info("request Interrupt %d", idx);
 
}
 
 
}  // namespace debugger
}  // namespace debugger
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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