Skip to content

Commit

Permalink
Move peripherals to devices directory
Browse files Browse the repository at this point in the history
- modify Makefile to enable detect devices directory
- decouple PLIC and UART into separate files
- Bind RISC-V core to plic_t to enable sending interrupt from PLIC to
  core
  • Loading branch information
ChinYikMing committed Nov 2, 2024
1 parent cfb3c3a commit 011c1fb
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 87 deletions.
17 changes: 13 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ OBJS_EXT :=

ifeq ($(call has, SYSTEM), 1)
OBJS_EXT += system.o
OBJS_EXT += plic.o
OBJS_EXT += uart.o
endif

# Integer Multiplication and Division instructions
Expand Down Expand Up @@ -230,11 +228,22 @@ ifeq ($(call has, GDBSTUB), 1)
$(OBJS): $(GDBSTUB_LIB)
endif

# Peripherals for system emulation
ifeq ($(call has, SYSTEM), 1)
DEV_OUT := $(OUT)/devices
DEV_SRC := src/devices
$(DEV_OUT)/%.o: $(DEV_SRC)/%.c $(deps_emcc)
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $<
DEV_OBJS := $(patsubst $(DEV_SRC)/%.c, $(DEV_OUT)/%.o, $(wildcard $(DEV_SRC)/*.c))
deps += $(DEV_OBJS:%.o=%.o.d)
endif

$(OUT)/%.o: src/%.c $(deps_emcc)
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $<

$(BIN): $(OBJS)
$(BIN): $(OBJS) $(DEV_OBJS)
$(VECHO) " LD\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS_emcc) $^ $(LDFLAGS)

Expand Down Expand Up @@ -331,7 +340,7 @@ endif
endif

clean:
$(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c
$(RM) $(BIN) $(OBJS) $(DEV_OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c
distclean: clean
-$(RM) $(DOOM_DATA) $(QUAKE_DATA)
$(RM) -r $(TIMIDITY_DATA)
Expand Down
33 changes: 22 additions & 11 deletions src/plic.c → src/devices/plic.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
/*
* rv32emu is freely redistributable under the MIT License. See the file
* "LICENSE" for information on usage and redistribution of this file.
*/

#include <assert.h>
#include <stdlib.h>

#include "plic.h"
#include "../riscv.h"
#include "../riscv_private.h"

void plic_update_interrupts(riscv_t *rv)
void plic_update_interrupts(plic_t *plic)
{
vm_attr_t *attr = PRIV(rv);
plic_t *plic = attr->plic;
riscv_t *rv = (riscv_t *) plic->rv;

/* Update pending interrupts */
plic->ip |= plic->active & ~plic->masked;
Expand All @@ -15,11 +24,8 @@ void plic_update_interrupts(riscv_t *rv)
rv->csr_sip &= ~SIP_SEIP;
}

uint32_t plic_read(riscv_t *rv, const uint32_t addr)
uint32_t plic_read(plic_t *plic, const uint32_t addr)
{
vm_attr_t *attr = PRIV(rv);
plic_t *plic = attr->plic;

/* no priority support: source priority hardwired to 1 */
if (1 <= addr && addr <= 31)
return 0;
Expand Down Expand Up @@ -54,11 +60,8 @@ uint32_t plic_read(riscv_t *rv, const uint32_t addr)
return plic_read_val;
}

void plic_write(riscv_t *rv, const uint32_t addr, uint32_t value)
void plic_write(plic_t *plic, const uint32_t addr, uint32_t value)
{
vm_attr_t *attr = PRIV(rv);
plic_t *plic = attr->plic;

/* no priority support: source priority hardwired to 1 */
if (1 <= addr && addr <= 31)
return;
Expand All @@ -81,3 +84,11 @@ void plic_write(riscv_t *rv, const uint32_t addr, uint32_t value)

return;
}

plic_t *plic_new()
{
plic_t *plic = calloc(1, sizeof(plic_t));
assert(plic);

return plic;
}
31 changes: 31 additions & 0 deletions src/devices/plic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* rv32emu is freely redistributable under the MIT License. See the file
* "LICENSE" for information on usage and redistribution of this file.
*/

#pragma once

#include <stdint.h>

/* PLIC */
typedef struct {
uint32_t masked;
uint32_t ip;
uint32_t ie;
/* state of input interrupt lines (level-triggered), set by environment */
uint32_t active;
/* RISC-V instance to receive PLIC interrupt */
void *rv;
} plic_t;

/* update PLIC status */
void plic_update_interrupts(plic_t *plic);

/* read a word from PLIC */
uint32_t plic_read(plic_t *plic, const uint32_t addr);

/* write a word to PLIC */
void plic_write(plic_t *plic, const uint32_t addr, uint32_t value);

/* create a PLIC instance */
plic_t *plic_new();
18 changes: 16 additions & 2 deletions src/uart.c → src/devices/uart.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
/*
* rv32emu is freely redistributable under the MIT License. See the file
* "LICENSE" for information on usage and redistribution of this file.
*/

#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "io.h"
#include <assert.h>

/* Emulate 8250 (plain, without loopback mode support) */

#include "uart.h"

#define U8250_INT_THRE 1

void u8250_update_interrupts(u8250_state_t *uart)
Expand Down Expand Up @@ -142,3 +148,11 @@ void u8250_write(u8250_state_t *uart, uint32_t addr, uint32_t value)
{
u8250_reg_write(uart, addr, value);
}

u8250_state_t *u8250_new()
{
u8250_state_t *uart = calloc(1, sizeof(u8250_state_t));
assert(uart);

return uart;
}
37 changes: 37 additions & 0 deletions src/devices/uart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* rv32emu is freely redistributable under the MIT License. See the file
* "LICENSE" for information on usage and redistribution of this file.
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>

#define IRQ_UART 1
#define IRQ_UART_BIT (1 << IRQ_UART)

typedef struct {
uint8_t dll, dlh; /* divisor (ignored) */
uint8_t lcr; /* UART config */
uint8_t ier; /* interrupt config */
uint8_t current_int, pending_ints; /* interrupt status */
uint8_t mcr; /* other output signals, loopback mode (ignored) */
int in_fd, out_fd; /* I/O handling */
bool in_ready;
} u8250_state_t;

/* update UART status */
void u8250_update_interrupts(u8250_state_t *uart);

/* poll UART status */
void u8250_check_ready(u8250_state_t *uart);

/* read a word from UART */
uint32_t u8250_read(u8250_state_t *uart, uint32_t addr);

/* write a word to UART */
void u8250_write(u8250_state_t *uart, uint32_t addr, uint32_t value);

/* create a UART instance */
u8250_state_t *u8250_new();
4 changes: 0 additions & 4 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#include <stdlib.h>
#include <string.h>

#if RV32_HAS(SYSTEM)
#include "plic.h"
#endif /* RV32_HAS(SYSTEM) */

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
Expand Down
16 changes: 0 additions & 16 deletions src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@

#include "io.h"

u8250_state_t *u8250_new()
{
u8250_state_t *uart = calloc(1, sizeof(u8250_state_t));
assert(uart);

return uart;
}

plic_t *plic_new()
{
plic_t *plic = calloc(1, sizeof(plic_t));
assert(plic);

return plic;
}

static uint8_t *data_memory_base;

memory_t *memory_new(uint32_t size)
Expand Down
38 changes: 1 addition & 37 deletions src/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,7 @@
#include <stdint.h>
#include <string.h>

/* UART */

#define IRQ_UART 1
#define IRQ_UART_BIT (1 << IRQ_UART)

typedef struct {
uint8_t dll, dlh; /**< divisor (ignored) */
uint8_t lcr; /**< UART config */
uint8_t ier; /**< interrupt config */
uint8_t current_int, pending_ints; /**< interrupt status */
/* other output signals, loopback mode (ignored) */
uint8_t mcr;
/* I/O handling */
int in_fd, out_fd;
bool in_ready;
} u8250_state_t;
void u8250_update_interrupts(u8250_state_t *uart);
void u8250_check_ready(u8250_state_t *uart);

uint32_t u8250_read(u8250_state_t *uart, uint32_t addr);

void u8250_write(u8250_state_t *uart, uint32_t addr, uint32_t value);

/* create a UART controller */
u8250_state_t *u8250_new();

typedef struct {
uint32_t masked;
uint32_t ip;
uint32_t ie;
/* state of input interrupt lines (level-triggered), set by environment */
uint32_t active;
} plic_t;

/* create a PLIC core */
plic_t *plic_new();

/* main memory */
typedef struct {
uint8_t *mem_base;
uint64_t mem_size;
Expand Down
7 changes: 0 additions & 7 deletions src/plic.h

This file was deleted.

1 change: 1 addition & 0 deletions src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ riscv_t *rv_create(riscv_user_t rv_attr)
/* setup PLIC */
attr->plic = plic_new();
assert(attr->plic);
attr->plic->rv = rv;

/* setup PLIC */
attr->uart = u8250_new();
Expand Down
7 changes: 7 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
#include "io.h"
#include "map.h"

#if RV32_HAS(SYSTEM)
#include "devices/plic.h"
#include "devices/uart.h"
#endif /* RV32_HAS(EXT_SYSTEM) */

#if RV32_HAS(EXT_F)
#define float16_t softfloat_float16_t
#define bfloat16_t softfloat_bfloat16_t
Expand Down Expand Up @@ -541,11 +546,13 @@ typedef struct {
} vm_data_t;

typedef struct {
#if RV32_HAS(SYSTEM)
/* uart object */
u8250_state_t *uart;

/* plic object */
plic_t *plic;
#endif /* RV32_HAS(SYSTEM) */

/* vm memory object */
memory_t *mem;
Expand Down
13 changes: 7 additions & 6 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
#error "Do not manage to build this file unless you enable system support."
#endif

#include "plic.h"
#include "devices/plic.h"
#include "devices/uart.h"
#include "riscv_private.h"

void emu_update_uart_interrupts(riscv_t *rv)
Expand All @@ -18,7 +19,7 @@ void emu_update_uart_interrupts(riscv_t *rv)
attr->plic->active |= IRQ_UART_BIT;
} else
attr->plic->active &= ~IRQ_UART_BIT;
plic_update_interrupts(rv);
plic_update_interrupts(attr->plic);
}

#define MMIO_PLIC 1
Expand All @@ -31,11 +32,11 @@ uint8_t ret_char;
#define MMIO_OP(io, rw) \
IIF(io)( /* PLIC */ \
IIF(rw)( /* read */ \
read_val = plic_read(rv, (addr & 0x3FFFFFF) >> 2); \
plic_update_interrupts(rv); return read_val; \
read_val = plic_read(PRIV(rv)->plic, (addr & 0x3FFFFFF) >> 2); \
plic_update_interrupts(PRIV(rv)->plic); return read_val; \
, /* write */ \
plic_write(rv, (addr & 0x3FFFFFF) >> 2, val); \
plic_update_interrupts(rv); return; \
plic_write(PRIV(rv)->plic, (addr & 0x3FFFFFF) >> 2, val); \
plic_update_interrupts(PRIV(rv)->plic); return; \
) \
, /* UART */ \
IIF(rw)( /* read */ \
Expand Down

0 comments on commit 011c1fb

Please sign in to comment.