Menu Close

RISC-V PLIC Project Design(2)

1. PLIC software design

 

Related reference articles:

RISC-V teaching plan

 

1.4. plic_driver.c

#include "platform.h"
#include "plic.h"
#include "plic_driver.h"
#include "encoding.h"
#include <string.h>

//Initialize the value in the interval to 0, volatile means that the variable does not need to be optimized and can be changed at any time
void volatile_memzero(u8_t * base, unsigned int size)
{
    volatile u8_t *ptr;
    for (ptr = base; ptr < (base + size); ptr++){
        *ptr = 0;
    }
}

//initialization
void PLIC_init (
    plic_instance_t * this_plic,
    uintptr_t base_addr,
    u32_t num_sources,
    u32_t num_priorities
)
{
    //Access variables in this_plic_struct
    this_plic->base_addr = base_addr;
    this_plic->num_sources = num_sources;
    this_plic->num_priorities = num_priorities;

    // disable all interrupts
    unsigned long hart_id = read_csr(mhartid); //Applicable to multi-core systems
    volatile_memzero(   (u8_t*) (this_plic->base_addr + PLIC_ENABLE_OFFSET 
                        + (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
    //The unit of address range is 1byte/8 bit, +8 is because the division of integers is rounded up, where num_sources = 64                        
                        (num_sources + 8) / 8); 



    // Set the priority of all interrupts to 0
    volatile_memzero (  (u8_t *)(this_plic->base_addr +
                        PLIC_PRIORITY_OFFSET),
                        (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);

    // Initialize the priority threshold to 0, volatile means that the variable does not need to be optimized and can be changed at any time
    volatile plic_threshold* threshold =    (plic_threshold*)
                                            (this_plic->base_addr +
                                            PLIC_THRESHOLD_OFFSET +
                                            (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));

    *threshold = 0; //The threshold pointed to by the pointer is set to 0
}


//Set the priority threshold
void PLIC_set_threshold (plic_instance_t * this_plic,plic_threshold threshold)
{
    unsigned long hart_id = read_csr(mhartid); //Applicable to multi-core systems
    //pointer value
    volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
                                                PLIC_THRESHOLD_OFFSET +
                                                (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));

    *threshold_ptr = threshold;//address
}


//set priority

void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority)
{
    if (this_plic->num_priorities > 0) {
        volatile plic_priority * priority_ptr = (volatile plic_priority *)
                                                (this_plic->base_addr +
                                                PLIC_PRIORITY_OFFSET +
                                                /*The unit of address range is 1byte */
                                                (source << PLIC_PRIORITY_SHIFT_PER_SOURCE)); 
                                                
        *priority_ptr = priority;
    }
}



//read interrupt declaration register
plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
    unsigned long hart_id = read_csr(mhartid); //Applicable to multi-core systems

    volatile plic_source * claim_addr = (volatile plic_source * )
                                        (this_plic->base_addr +
                                        PLIC_CLAIM_OFFSET +
                                        (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));

    return *claim_addr;

}

// interrupt complete

void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){
    unsigned long hart_id = read_csr(mhartid); //Applicable to multi-core systems
    
    volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
                                        PLIC_CLAIM_OFFSET +
                                        (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
    *claim_addr = source;
}

 

 

1.5. main.c

Only the functions related to PLIC in the main function are listed here, and other detailed parts of the main function will be introduced in the project related to PLIC.

//PLIC enable
static void enable_plic_int(u8_t int_src)
{
    u8_t reg_off = 0;
    u8_t reg_val = 0;


    reg_off = (int_src / 32) * 4; //by definition
    reg_val = int_src & 0x1f; //Only 31 bits are reserved, 1F(16)=31(10)

    PLIC_REG(PLIC_ENABLE_OFFSET + reg_off) |= 1 << reg_val; //Set up the corresponding bit

    return;
}


//PLIC prohibited
static void disable_plic_int(u8_t int_src)
{
    u8_t reg_off = 0;
    u8_t reg_val = 0;

    reg_off = (int_src / 32) * 4; //by definition
    reg_val = int_src & 0x1f; //Only 31 bits are reserved, 1F(16)=31(10)

    PLIC_REG(PLIC_ENABLE_OFFSET + reg_off) &= ~(1 << reg_val); //Clear the corresponding bit

    return;
}

 

 

Posted in FPGA, RISC-V, RISC-V Textbook, Textbook and Training Project

Related Articles

Leave a Reply

Your email address will not be published.

Leave the field below empty!