Skip to content

Commit

Permalink
fix interrupts
Browse files Browse the repository at this point in the history
- add iffifo interrupt into the PLIC system
- remove FULL and AVAILABLE interrupts as they can be implemented with REACHED interrupts
  • Loading branch information
Pierre Guillod committed Oct 28, 2023
1 parent 192f13e commit f15c86a
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 135 deletions.
4 changes: 1 addition & 3 deletions hw/ip_examples/iffifo/data/iffifo.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@
hwaccess: "hro"
hwqe: "true" # Used to catch software writes
fields: [
{ bits: "0", name: "AVAILABLE", desc: "Data available interrupt" }
{ bits: "1", name: "REACHED", desc: "Watermark reached interrupt" }
{ bits: "2", name: "FULL", desc: "FIFO full interrupt" }
{ bits: "0", name: "REACHED", desc: "Watermark reached interrupt" }
]
}

Expand Down
28 changes: 6 additions & 22 deletions hw/ip_examples/iffifo/rtl/iffifo.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ module iffifo #(
output logic iffifo_out_valid_o,

// Interrupt lines
output logic iffifo_available_int_o,
output logic iffifo_reached_int_o,
output logic iffifo_full_int_o
output logic iffifo_int_o
);

import iffifo_reg_pkg::*;
Expand Down Expand Up @@ -57,32 +55,18 @@ module iffifo #(
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin

iffifo_available_int_o <= 0;
iffifo_reached_int_o <= 0;
iffifo_full_int_o <= 0;
iffifo_int_o <= 0;

end else begin

// Interrupts firing
if (full & reg2hw.interrupts.full.q) begin
iffifo_full_int_o <= 1;
end
if (reached & reg2hw.interrupts.reached.q) begin
iffifo_reached_int_o <= 1;
end
if (available & reg2hw.interrupts.available.q) begin
iffifo_available_int_o <= 1;
if (reached & reg2hw.interrupts.q) begin
iffifo_int_o <= 1;
end

// Interrupts assertion
if (reg2hw.interrupts.full.qe) begin
iffifo_full_int_o <= 0;
end
if (reg2hw.interrupts.reached.qe) begin
iffifo_reached_int_o <= 0;
end
if (reg2hw.interrupts.available.qe) begin
iffifo_available_int_o <= 0;
if (reg2hw.interrupts.qe) begin
iffifo_int_o <= 0;
end

end
Expand Down
22 changes: 6 additions & 16 deletions hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,8 @@ package iffifo_reg_pkg;
typedef struct packed {logic [31:0] q;} iffifo_reg2hw_watermark_reg_t;

typedef struct packed {
struct packed {
logic q;
logic qe;
} available;
struct packed {
logic q;
logic qe;
} reached;
struct packed {
logic q;
logic qe;
} full;
logic q;
logic qe;
} iffifo_reg2hw_interrupts_reg_t;

typedef struct packed {logic [31:0] d;} iffifo_hw2reg_fifo_out_reg_t;
Expand Down Expand Up @@ -68,10 +58,10 @@ package iffifo_reg_pkg;

// Register -> HW type
typedef struct packed {
iffifo_reg2hw_fifo_out_reg_t fifo_out; // [103:71]
iffifo_reg2hw_fifo_in_reg_t fifo_in; // [70:38]
iffifo_reg2hw_watermark_reg_t watermark; // [37:6]
iffifo_reg2hw_interrupts_reg_t interrupts; // [5:0]
iffifo_reg2hw_fifo_out_reg_t fifo_out; // [99:67]
iffifo_reg2hw_fifo_in_reg_t fifo_in; // [66:34]
iffifo_reg2hw_watermark_reg_t watermark; // [33:2]
iffifo_reg2hw_interrupts_reg_t interrupts; // [1:0]
} iffifo_reg2hw_t;

// HW -> register type
Expand Down
91 changes: 12 additions & 79 deletions hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,9 @@ module iffifo_reg_top #(
logic [31:0] watermark_qs;
logic [31:0] watermark_wd;
logic watermark_we;
logic interrupts_available_qs;
logic interrupts_available_wd;
logic interrupts_available_we;
logic interrupts_reached_qs;
logic interrupts_reached_wd;
logic interrupts_reached_we;
logic interrupts_full_qs;
logic interrupts_full_wd;
logic interrupts_full_we;
logic interrupts_qs;
logic interrupts_wd;
logic interrupts_we;

// Register instances
// R[fifo_out]: V(True)
Expand Down Expand Up @@ -292,81 +286,28 @@ module iffifo_reg_top #(

// R[interrupts]: V(False)

// F[available]: 0:0
prim_subreg #(
.DW (1),
.SWACCESS("RW"),
.RESVAL (1'h0)
) u_interrupts_available (
) u_interrupts (
.clk_i (clk_i),
.rst_ni(rst_ni),

// from register interface
.we(interrupts_available_we),
.wd(interrupts_available_wd),
.we(interrupts_we),
.wd(interrupts_wd),

// from internal hardware
.de(1'b0),
.d ('0),

// to internal hardware
.qe(reg2hw.interrupts.available.qe),
.q (reg2hw.interrupts.available.q),
.qe(reg2hw.interrupts.qe),
.q (reg2hw.interrupts.q),

// to register interface (read)
.qs(interrupts_available_qs)
);


// F[reached]: 1:1
prim_subreg #(
.DW (1),
.SWACCESS("RW"),
.RESVAL (1'h0)
) u_interrupts_reached (
.clk_i (clk_i),
.rst_ni(rst_ni),

// from register interface
.we(interrupts_reached_we),
.wd(interrupts_reached_wd),

// from internal hardware
.de(1'b0),
.d ('0),

// to internal hardware
.qe(reg2hw.interrupts.reached.qe),
.q (reg2hw.interrupts.reached.q),

// to register interface (read)
.qs(interrupts_reached_qs)
);


// F[full]: 2:2
prim_subreg #(
.DW (1),
.SWACCESS("RW"),
.RESVAL (1'h0)
) u_interrupts_full (
.clk_i (clk_i),
.rst_ni(rst_ni),

// from register interface
.we(interrupts_full_we),
.wd(interrupts_full_wd),

// from internal hardware
.de(1'b0),
.d ('0),

// to internal hardware
.qe(reg2hw.interrupts.full.qe),
.q (reg2hw.interrupts.full.q),

// to register interface (read)
.qs(interrupts_full_qs)
.qs(interrupts_qs)
);


Expand Down Expand Up @@ -404,14 +345,8 @@ module iffifo_reg_top #(
assign watermark_we = addr_hit[4] & reg_we & !reg_error;
assign watermark_wd = reg_wdata[31:0];

assign interrupts_available_we = addr_hit[5] & reg_we & !reg_error;
assign interrupts_available_wd = reg_wdata[0];

assign interrupts_reached_we = addr_hit[5] & reg_we & !reg_error;
assign interrupts_reached_wd = reg_wdata[1];

assign interrupts_full_we = addr_hit[5] & reg_we & !reg_error;
assign interrupts_full_wd = reg_wdata[2];
assign interrupts_we = addr_hit[5] & reg_we & !reg_error;
assign interrupts_wd = reg_wdata[0];

// Read data return
always_comb begin
Expand Down Expand Up @@ -441,9 +376,7 @@ module iffifo_reg_top #(
end

addr_hit[5]: begin
reg_rdata_next[0] = interrupts_available_qs;
reg_rdata_next[1] = interrupts_reached_qs;
reg_rdata_next[2] = interrupts_full_qs;
reg_rdata_next[0] = interrupts_qs;
end

default: begin
Expand Down
27 changes: 18 additions & 9 deletions sw/applications/example_iffifo_poll/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@

#include "fast_intr_ctrl.h"
#include "dma.h"
#include "rv_plic.h"

#include "x-heep.h"

#define DMA_CSR_REG_MIE_MASK 0xFFFFFFFF
#include "iffifo.h"

unsigned int IFFIFO_START_ADDRESS = EXT_PERIPHERAL_START_ADDRESS + 0x2000;

#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)

unsigned int IFFIFO_START_ADDRESS = EXT_PERIPHERAL_START_ADDRESS + 0x2000;

void iffifo_isr(void)
void handler_irq_iffifo(uint32_t id)
{
mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS);
// Assert and disable interrupts
mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b000);
PRINTF(" ** REACH interrupt fired.");
mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b0);
PRINTF(" ** REACH intr. fired.\n");
}

void print_status_register(void)
Expand All @@ -50,12 +50,21 @@ void print_status_register(void)

int main(int argc, char *argv[]) {

CSR_SET_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK );
// Enable interrupt on processor side
// Enable global interrupt for machine-level interrupts
CSR_SET_BITS(CSR_REG_MSTATUS, 0x8);
// Set mie.MEIE bit to one to enable machine-level external interrupts
const uint32_t mask = 1 << 11;
CSR_SET_BITS(CSR_REG_MIE, mask);

if(plic_Init()) {return EXIT_FAILURE;};
if(plic_irq_set_priority(EXT_INTR_1, 1)) {return EXIT_FAILURE;};
if(plic_irq_set_enabled(EXT_INTR_1, kPlicToggleEnabled)) {return EXIT_FAILURE;};

mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS);

mmio_region_write32(iffifo_base_addr, IFFIFO_WATERMARK_REG_OFFSET, 2);
mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b010);
mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b1);
print_status_register();
mmio_region_write32(iffifo_base_addr, IFFIFO_FIFO_IN_REG_OFFSET, 1);
print_status_register();
Expand Down
56 changes: 56 additions & 0 deletions sw/device/lib/drivers/iffifo/iffifo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
*******************
******************************* C SOURCE FILE *******************************
** ******************* **
** **
** project : x-heep **
** filename : i2s.h **
** date : 28/10/2023 **
** **
*****************************************************************************
** **
** Copyright (c) EPFL contributors. **
** All rights reserved. **
** **
*****************************************************************************
*/

/***************************************************************************/
/***************************************************************************/

/**
* @file iffifo.h
* @date 28/10/2023
* @author Pierre Guillod
* @brief HAL of the IFFIFO peripheral
*
*/

#ifndef _DRIVERS_IFFIFO_H_
#define _DRIVERS_IFFIFO_H_

/****************************************************************************/
/** **/
/* MODULES USED */
/** **/
/****************************************************************************/


#ifdef __cplusplus
extern "C" {
#endif

__attribute__((weak)) void handler_irq_iffifo(uint32_t id);

#ifdef __cplusplus
}
#endif

#endif // _DRIVERS_IFFIFO_H_

/****************************************************************************/
/** **/
/* EOF */
/** **/
/****************************************************************************/
4 changes: 1 addition & 3 deletions sw/device/lib/drivers/iffifo/iffifo_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ extern "C" {
// Write any value to assert an interrupt. Write 0 or 1 to disable or enable
// an interrupt.
#define IFFIFO_INTERRUPTS_REG_OFFSET 0x14
#define IFFIFO_INTERRUPTS_AVAILABLE_BIT 0
#define IFFIFO_INTERRUPTS_REACHED_BIT 1
#define IFFIFO_INTERRUPTS_FULL_BIT 2
#define IFFIFO_INTERRUPTS_REACHED_BIT 0

#ifdef __cplusplus
} // extern "C"
Expand Down
7 changes: 7 additions & 0 deletions sw/device/lib/drivers/rv_plic/rv_plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
#include "i2s.h"
#include "dma.h"
#include "spi_host.h"
#include "iffifo.h"

#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)

/****************************************************************************/
/** **/
Expand Down Expand Up @@ -407,6 +410,10 @@ void plic_reset_handlers_list(void)
{
handlers[i] = &handler_irq_dma;
}
else if ( i == EXT_INTR_1)
{
handlers[i] = &handler_irq_iffifo;
}
else
{
handlers[i] = &handler_irq_dummy;
Expand Down
Loading

0 comments on commit f15c86a

Please sign in to comment.