From 88914409e05680b1bf0731f6a2abb6716fb2020f Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Sun, 11 Apr 2021 20:20:15 +0200 Subject: Added simple RISC-V PLIC functionality for NS16550 interrupt * RTEMS spconsole01 test now passes --- configure | 20 ++--- configure.ac | 2 +- grlib.c | 263 ++++++++++++++++++++++++++++++++++++++++++++--------------- riscv.c | 9 +- rv32.c | 4 +- sis.info | 11 ++- version.texi | 6 +- 7 files changed, 228 insertions(+), 87 deletions(-) diff --git a/configure b/configure index 023ecd8..34a8e0e 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sis 2.26. +# Generated by GNU Autoconf 2.69 for sis 2.27. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sis' PACKAGE_TARNAME='sis' -PACKAGE_VERSION='2.26' -PACKAGE_STRING='sis 2.26' +PACKAGE_VERSION='2.27' +PACKAGE_STRING='sis 2.27' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1283,7 +1283,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sis 2.26 to adapt to many kinds of systems. +\`configure' configures sis 2.27 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1354,7 +1354,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sis 2.26:";; + short | recursive ) echo "Configuration of sis 2.27:";; esac cat <<\_ACEOF @@ -1444,7 +1444,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sis configure 2.26 +sis configure 2.27 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1742,7 +1742,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sis $as_me 2.26, which was +It was created by sis $as_me 2.27, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2569,7 +2569,7 @@ fi # Define the identity of the package. PACKAGE='sis' - VERSION='2.26' + VERSION='2.27' cat >>confdefs.h <<_ACEOF @@ -4911,7 +4911,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sis $as_me 2.26, which was +This file was extended by sis $as_me 2.27, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4977,7 +4977,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sis config.status 2.26 +sis config.status 2.27 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index b824fba..6396586 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([sis], [2.26]) +AC_INIT([sis], [2.27]) AC_CONFIG_SRCDIR([sis.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS(config.h) diff --git a/grlib.c b/grlib.c index fc99df9..7982059 100644 --- a/grlib.c +++ b/grlib.c @@ -244,7 +244,7 @@ greth_add (int irq, uint32 addr, uint32 mask) GRLIB_PP_APBADDR (addr, mask)); greth_irq = irq; if (sis_verbose) - printf(" GRETH 10/100 Mbit Ethernet core 0x%08x %d\n", addr, irq); + printf (" GRETH 10/100 Mbit Ethernet core 0x%08x %d\n", addr, irq); } const struct grlib_ipcore greth = { @@ -259,7 +259,7 @@ leon3_add () { grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_LEON3, 0, 0)); if (sis_verbose) - printf(" LEON3 SPARC V8 processor \n"); + printf (" LEON3 SPARC V8 processor \n"); } const struct grlib_ipcore leon3s = { @@ -334,7 +334,7 @@ apbmst_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBMST, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); if (sis_verbose) - printf(" AHB/APB Bridge 0x%08x\n", addr); + printf (" AHB/APB Bridge 0x%08x\n", addr); } const struct grlib_ipcore apbmst = { @@ -598,7 +598,7 @@ irqmp_add (int irq, uint32 addr, uint32 mask) grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_IRQMP, 2, 0), GRLIB_PP_APBADDR (addr, mask)); if (sis_verbose) - printf(" IRQMP Interrupt controller 0x%08x\n", addr); + printf (" IRQMP Interrupt controller 0x%08x\n", addr); } const struct grlib_ipcore irqmp = { @@ -671,7 +671,7 @@ gpt_add (int irq, uint32 addr, uint32 mask) GRLIB_PP_APBADDR (addr, mask)); gpt_irq = irq; if (sis_verbose) - printf(" GPTIMER timer unit 0x%08x %d\n", addr, irq); + printf (" GPTIMER timer unit 0x%08x %d\n", addr, irq); } static void @@ -1223,7 +1223,7 @@ apbuart_add (int irq, uint32 addr, uint32 mask) grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBUART, 1, irq), GRLIB_PP_APBADDR (addr, mask)); if (sis_verbose) - printf(" APBUART serial port 0x%08x %d\n", addr, irq); + printf (" APBUART serial port 0x%08x %d\n", addr, irq); } const struct grlib_ipcore apbuart = { @@ -1280,7 +1280,7 @@ sdctrl_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SDCTRL, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 1, 1, 2), 0, 0, 0); if (sis_verbose) - printf(" SDRAM controller %d M 0x%08x\n", + printf (" SDRAM controller %d M 0x%08x\n", (~(mask << 20) + 1) >> 20, addr); } @@ -1311,7 +1311,7 @@ srctrl_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SRCTRL, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 1, 1, 2), 0, 0, 0); if (sis_verbose) - printf(" PROM controller %d M 0x%08x\n", + printf (" PROM controller %d M 0x%08x\n", (~(mask << 20) + 1) >> 20, addr); } @@ -1334,48 +1334,69 @@ grlib_boot_init (void) } /* ------------------- ns16550 -----------------------*/ - -static int32 uart_lcr; +static void plic_irq (int irq); +static int32 uart_lcr, uart_ie, uart_mcr, ns16550_irq, uart_txctrl; static void ns16550_add (int irq, uint32 addr, uint32 mask) { grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_CONTRIB, CONTRIB_NS16550, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); + ns16550_irq = irq; if (sis_verbose) - printf(" NS16550 UART 0x%08x %d\n", addr, irq); + printf (" NS16550 UART 0x%08x %d\n", addr, irq); } static int ns16550_write (uint32 addr, uint32 * data, uint32 sz) { - switch (addr & 0xff) + switch (addr & 0xff) + { + case 0: + if (!uart_lcr) { - case 0: - if (!uart_lcr) - putchar (*data & 0xff); - break; - case 0x0c: - uart_lcr = *data & 0x80; - break; + putchar (*data & 0xff); } + break; + case 4: + if (!uart_lcr) + uart_ie = *data & 0xff; + break; + case 0x08: + uart_txctrl = *data & 0xff; + break; + case 0x0c: + uart_lcr = *data & 0x80; + break; + case 0x10: + uart_mcr = *data & 0xff; + break; + } + if ((uart_ie & 0x2) && (uart_mcr & 0x8)) + plic_irq (ns16550_irq); return 1; } static int ns16550_read (uint32 addr, uint32 * data) { - *data = 0; - switch (addr & 0xff) - { - case 0x10: - *data = 0x03; - break; - case 0x14: - *data = 0x60; - break; - } + *data = 0; + switch (addr & 0xff) + { + case 0x04: + *data = uart_ie; + break; + case 0x08: + *data = uart_txctrl; + break; + case 0x10: + *data = uart_mcr; //0x03; + break; + case 0x14: + *data = 0x60; + break; + } return 4; } @@ -1383,6 +1404,8 @@ static void ns16550_reset (void) { uart_lcr = 0; + uart_ie = 0; + uart_mcr = 0; } const struct grlib_ipcore ns16550 = { @@ -1397,7 +1420,7 @@ clint_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_CONTRIB, CONTRIB_CLINT, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); if (sis_verbose) - printf(" CLINT Interrupt controller 0x%08x %d\n", addr, irq); + printf (" CLINT Interrupt controller 0x%08x %d\n", addr, irq); } #define CLINTSTART 0x00000 @@ -1410,29 +1433,29 @@ clint_read (uint32 addr, uint32 * data) uint64 tmp; int reg, cpuid; - reg = (addr >> 2) & 1; - cpuid = ((addr >> 3) % NCPU); - if ((addr >= CLINT_TIMEBASE) && (addr < CLINTEND)) - { - tmp = ebase.simtime >> 32; - if (reg) - *data = tmp & 0xffffffff; - else - *data = ebase.simtime & 0xffffffff; - } - else if ((addr >= CLINT_TIMECMP) && (addr < CLINT_TIMEBASE)) - { - tmp = sregs[cpuid].mtimecmp >> 32; - if (reg) - *data = tmp & 0xffffffff; - else - *data = sregs[cpuid].mtimecmp & 0xffffffff; - } - else if ((addr >= 0) && (addr < CLINT_TIMECMP)) - { - cpuid = ((addr >> 2) % NCPU); - *data = ((sregs[cpuid].mip & MIP_MSIP) >> 4) & 1; - } + reg = (addr >> 2) & 1; + cpuid = ((addr >> 3) % NCPU); + if ((addr >= CLINT_TIMEBASE) && (addr < CLINTEND)) + { + tmp = ebase.simtime >> 32; + if (reg) + *data = tmp & 0xffffffff; + else + *data = ebase.simtime & 0xffffffff; + } + else if ((addr >= CLINT_TIMECMP) && (addr < CLINT_TIMEBASE)) + { + tmp = sregs[cpuid].mtimecmp >> 32; + if (reg) + *data = tmp & 0xffffffff; + else + *data = sregs[cpuid].mtimecmp & 0xffffffff; + } + else if ((addr >= 0) && (addr < CLINT_TIMECMP)) + { + cpuid = ((addr >> 2) % NCPU); + *data = ((sregs[cpuid].mip & MIP_MSIP) >> 4) & 1; + } return 4; } @@ -1495,7 +1518,115 @@ const struct grlib_ipcore clint = { }; /* ------------------- plic --------------------------*/ -/* no functionality supported for now */ +/* simplified functionality supported for now */ + +#define PLIC_PRIO 0 +#define PLIC_IPEND 0x1000 +#define PLIC_IENA 0x2000 +#define PLIC_THRES 0x200000 +#define PLIC_CLAIM 0x200004 +#define PLIC_MASK1 0xFC + +static unsigned char plic_prio[64]; +static uint32 plic_ie[NCPU][2]; +static uint32 plic_ip[2]; +static uint32 plic_thres[NCPU]; +static uint32 plic_claim[NCPU]; + +static void +plic_check_irq (uint32 hart) +{ + int i, irq; + if (irq = (plic_ie[hart][0] & plic_ip[0])) + { + for (i = 1; i < 32; i++) + { + if ((irq >> i) & 1) + plic_claim[hart] = i; + } + sregs[hart].mip |= MIP_MEIP; + } +} + +static void +plic_irq (int irq) +{ + int i; + plic_ip[0] |= (1 << irq); + for (i = 0; i < NCPU; i++) + { + plic_check_irq (i); + rv32_check_lirq (i); + } +} + +static int +plic_read (uint32 addr, uint32 * data) +{ + int hart; + if (addr >= PLIC_THRES) + { + hart = ((addr >> 12) & 0x0F) % NCPU; + if ((addr & PLIC_MASK1) == 0) + *data = plic_thres[hart]; // irq threshold, not used for now + else + { + *data = plic_claim[hart]; + plic_claim[hart] = 0; + plic_ip[0] &= ~(1 << *data); + } + } + else if (addr >= PLIC_IENA) + { + hart = ((addr >> 7) & 0x0F) % NCPU; + if (addr & 4) + *data = plic_ie[hart][1]; // irq enable + else + *data = plic_ie[hart][0]; + } + else if (addr >= PLIC_IPEND) + { + hart = ((addr >> 7) & 0x0F) % NCPU; + if (addr & 4) + *data = plic_ip[1]; // irq pending + else + *data = plic_ip[0]; + } + else if (addr < PLIC_IPEND) + { + *data = plic_prio[(addr & 0x0ff) >> 2]; // irq priority, not used for now + } + if (sis_verbose) + printf (" PLIC read 0x%08x %d\n", addr, *data); + return 4; +} + +static int +plic_write (uint32 addr, uint32 * data, uint32 sz) +{ + int hart; + if (addr >= PLIC_THRES) + { + hart = ((addr >> 12) & 0x0F) % NCPU; + if ((addr & PLIC_MASK1) == 0) + plic_thres[hart] = *data; // irq threshold, not used for now + else + plic_check_irq (hart); // irq completion + } + else if (addr >= PLIC_IENA) + { + hart = ((addr >> 7) & 0x0F) % NCPU; + if (addr & 4) + plic_ie[hart][1] = *data; // irq enable + else + plic_ie[hart][0] = *data; + } + else if (addr < PLIC_IPEND) + { + plic_prio[(addr & 0x0ff) >> 2] = *data; // irq priority, not used for now + } + return 1; +} static void plic_add (int irq, uint32 addr, uint32 mask) @@ -1503,11 +1634,11 @@ plic_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_CONTRIB, CONTRIB_PLIC, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); if (sis_verbose) - printf(" PLIC Interrupt controller 0x%08x %d\n", addr, irq); + printf (" PLIC Interrupt controller 0x%08x %d\n", addr, irq); } const struct grlib_ipcore plic = { - NULL, NULL, NULL, NULL, plic_add + NULL, NULL, plic_read, plic_write, plic_add }; /* ------------------- sifive test module --------------*/ @@ -1518,17 +1649,17 @@ s5test_write (uint32 addr, uint32 * data, uint32 sz) { int i; - switch (addr & 0xff) + switch (addr & 0xff) + { + case 0: + if (*data == 0x5555) { - case 0: - if (*data == 0x5555) - { - printf ("Power-off issued, exiting ...\n"); - for (i=0; i< ncpu; i++) - sregs[i].trap = ERROR_TRAP; - } - break; + printf ("Power-off issued, exiting ...\n"); + for (i = 0; i < ncpu; i++) + sregs[i].trap = ERROR_TRAP; } + break; + } return 1; } @@ -1539,7 +1670,7 @@ s5test_add (int irq, uint32 addr, uint32 mask) grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_CONTRIB, CONTRIB_S5TEST, 0, 0), GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); if (sis_verbose) - printf(" S5 Test module 0x%08x %d\n", addr, irq); + printf (" S5 Test module 0x%08x %d\n", addr, irq); } const struct grlib_ipcore s5test = { diff --git a/riscv.c b/riscv.c index 6d8fa98..b36fa1e 100644 --- a/riscv.c +++ b/riscv.c @@ -201,7 +201,9 @@ rv32_check_lirq (int cpu) if (sregs[cpu].mstatus & MSTATUS_MIE) { tmpirq = sregs[cpu].mip & sregs[cpu].mie; - if (tmpirq & MIP_MSIP) + if (tmpirq & MIP_MEIP) + ext_irl[cpu] = 0x1b; + else if (tmpirq & MIP_MSIP) ext_irl[cpu] = 0x13; else if (tmpirq & MIP_MTIP) ext_irl[cpu] = 0x17; @@ -2080,7 +2082,8 @@ riscv_execute_trap (sregs) } if (((sregs->trap >= 16) && (sregs->trap < 32)) - || ((sregs->trap == 0x23) || (sregs->trap == 0x27))) + || ((sregs->trap == 0x23) || (sregs->trap == 0x27) + || (sregs->trap == 0x2b))) { sregs->mcause &= 0x1f; // filter trap cause sregs->mcause |= 0x80000000; // indicate async interrupt @@ -2093,6 +2096,8 @@ riscv_execute_trap (sregs) sregs->mip &= ~MIP_MSIP; if (sregs->trap == 0x27) sregs->mip &= ~MIP_MTIP; + if (sregs->trap == 0x2b) + sregs->mip &= ~MIP_MEIP; // save mstatus.mie in mstatus.mpie sregs->mstatus |= (sregs->mstatus << 4) & MSTATUS_MPIE; diff --git a/rv32.c b/rv32.c index 305fd1e..73cc523 100644 --- a/rv32.c +++ b/rv32.c @@ -69,7 +69,7 @@ init_sim (void) grlib_ahbs_add (&s5test, 0, TESTSTART, 0xFFF); grlib_ahbs_add (&clint, 0, CLINT_START, 0xFFF); grlib_ahbs_add (&plic, 0, PLIC_START, PLIC_MASK); - grlib_ahbs_add (&ns16550, 0, NS16550_START, 0xFFF); + grlib_ahbs_add (&ns16550, 10, NS16550_START, 0xFFF); grlib_ahbs_add (&srctrl, 0, ROM_START, ROM_MASKPP); grlib_ahbs_add (&sdctrl, 0, RAM_START, RAM_MASKPP); @@ -174,7 +174,7 @@ memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws) *ws = 4; } - if (sis_verbose > 0) + if (sis_verbose > 2) printf ("AHB write a: %08x, d: %08x\n", addr, *data); if (sis_verbose && mexc) { diff --git a/sis.info b/sis.info index cc0750e..44a5c99 100644 --- a/sis.info +++ b/sis.info @@ -1,6 +1,6 @@ -This is sis.info, produced by makeinfo version 6.5 from sis.texi. +This is sis.info, produced by makeinfo version 6.7 from sis.texi. -This manual is for SIS (version 2.26, 15 December 2020). +This manual is for SIS (version 2.27, 18 December 2020). Copyright (C) 2020 Free Software Foundation, Inc. @@ -21,7 +21,7 @@ File: sis.info, Node: Top, Next: Introduction, Up: (dir) SIS *** -This manual is for SIS (version 2.26, 15 December 2020). +This manual is for SIS (version 2.27, 18 December 2020). * Menu: @@ -1433,3 +1433,8 @@ Node: GNU Free Documentation License31926 Node: Index57070  End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/version.texi b/version.texi index 0aad4bb..702b422 100644 --- a/version.texi +++ b/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 15 December 2020 +@set UPDATED 18 December 2020 @set UPDATED-MONTH December 2020 -@set EDITION 2.26 -@set VERSION 2.26 +@set EDITION 2.27 +@set VERSION 2.27 -- cgit v1.2.3