mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw into wsim_updates
This commit is contained in:
commit
cda490c911
2
.gitignore
vendored
2
.gitignore
vendored
@ -153,6 +153,8 @@ examples/C/mcmodel/mcmodel_medany
|
||||
examples/C/mcmodel/mcmodel_medlow
|
||||
examples/C/sum/sum
|
||||
examples/C/sum_mixed/sum_mixed
|
||||
examples/C/hello/hello
|
||||
examples/C/gpio/gpio
|
||||
examples/asm/sumtest/sumtest
|
||||
examples/asm/example/example
|
||||
examples/asm/trap/trap
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
# Core settings
|
||||
--variant RV32GCK # for RV32GC
|
||||
--override cpu/priv_version=1.12
|
||||
--override cpu/priv_version=1.12
|
||||
--override cpu/user_version=20191213
|
||||
# arch
|
||||
--override cpu/mimpid=0x100
|
||||
@ -20,7 +20,7 @@
|
||||
--override refRoot/cpu/envcfg_mask=1 # dh 1/26/24 this should be deleted when ImperasDV is updated to allow envcfg.FIOM to be written
|
||||
|
||||
# bit manipulation
|
||||
--override cpu/add_Extensions=B
|
||||
--override cpu/add_Extensions=B
|
||||
--override cpu/bitmanip_version=1.0.0
|
||||
--override cpu/misa_B_Zba_Zbb_Zbs=T
|
||||
|
||||
@ -70,9 +70,9 @@
|
||||
--override cpu/trigger_num=0 # disable CSRs 7a0-7a8
|
||||
|
||||
# For code coverage, don't produce pseudoinstructions
|
||||
--override no_pseudo_inst=T
|
||||
--override no_pseudo_inst=T
|
||||
|
||||
# Show "c." with compressed instructions
|
||||
# Show "c." with compressed instructions
|
||||
--override show_c_prefix=T
|
||||
|
||||
# nonratified mnoise register not implemented
|
||||
@ -88,6 +88,10 @@
|
||||
# Zkr entropy source and seed register not supported.
|
||||
--override cpu/Zkr=F
|
||||
|
||||
# ShangMi Crypto not supported
|
||||
--override cpu/Zksed=F
|
||||
--override cpu/Zksh=F
|
||||
|
||||
--override cpu/reset_address=0x80000000
|
||||
|
||||
--override cpu/unaligned=F # Zicclsm (should be true)
|
||||
@ -107,7 +111,7 @@
|
||||
# mstatus.FS is set dirty on any write to a FPR, or when a fp operation signals an exception
|
||||
--override cpu/mstatus_fs_mode=write_1
|
||||
|
||||
# PMA Settings
|
||||
# PMA Settings
|
||||
# 'r': read access allowed
|
||||
# 'w': write access allowed
|
||||
# 'x': execute access allowed
|
||||
|
@ -9,7 +9,7 @@
|
||||
#--showcommands
|
||||
|
||||
# Core settings
|
||||
--override cpu/priv_version=1.12
|
||||
--override cpu/priv_version=1.12
|
||||
--override cpu/user_version=20191213
|
||||
# arch
|
||||
--override cpu/mimpid=0x100
|
||||
@ -19,7 +19,7 @@
|
||||
--override refRoot/cpu/envcfg_mask=1 # dh 1/26/24 this should be deleted when ImperasDV is updated to allow envcfg.FIOM to be written
|
||||
|
||||
# bit manipulation
|
||||
--override cpu/add_Extensions=B
|
||||
--override cpu/add_Extensions=B
|
||||
--override cpu/bitmanip_version=1.0.0
|
||||
--override cpu/misa_B_Zba_Zbb_Zbs=T
|
||||
|
||||
@ -68,9 +68,9 @@
|
||||
--override cpu/trigger_num=0 # disable CSRs 7a0-7a8
|
||||
|
||||
# For code coverage, don't produce pseudoinstructions
|
||||
--override no_pseudo_inst=T
|
||||
--override no_pseudo_inst=T
|
||||
|
||||
# Show "c." with compressed instructions
|
||||
# Show "c." with compressed instructions
|
||||
--override show_c_prefix=T
|
||||
|
||||
# nonratified mnoise register not implemented
|
||||
@ -86,6 +86,10 @@
|
||||
# Zkr entropy source and seed register not supported.
|
||||
--override cpu/Zkr=F
|
||||
|
||||
# ShangMi Crypto not supported
|
||||
--override cpu/Zksed=F
|
||||
--override cpu/Zksh=F
|
||||
|
||||
--override cpu/reset_address=0x80000000
|
||||
|
||||
--override cpu/unaligned=T # Zicclsm (should be true)
|
||||
@ -105,7 +109,7 @@
|
||||
# mstatus.FS is set dirty on any write to a FPR, or when a fp operation signals an exception
|
||||
--override cpu/mstatus_fs_mode=write_1
|
||||
|
||||
# PMA Settings
|
||||
# PMA Settings
|
||||
# 'r': read access allowed
|
||||
# 'w': write access allowed
|
||||
# 'x': execute access allowed
|
||||
|
@ -15,6 +15,44 @@
|
||||
extern volatile uint64_t tohost;
|
||||
extern volatile uint64_t fromhost;
|
||||
|
||||
/////////////////////////////
|
||||
// Start of code added for Wally
|
||||
// Use UART rather than syscall host interface for printing
|
||||
//////////////////////////////
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void uartInit(void) {
|
||||
volatile uint8_t *UART_LCR = (uint8_t*)0x10000003;
|
||||
*UART_LCR = 0b0000011; // 8-bit characters, 1 stop bit, no parity
|
||||
}
|
||||
|
||||
void uartSend(char c) {
|
||||
volatile uint8_t *UART_THR = (uint8_t*)0x10000000;
|
||||
volatile uint8_t *UART_LSR = (uint8_t*)0x10000005;
|
||||
|
||||
while (!(*UART_LSR & (1<<5))); // wait for THRE (trans hold reg empty)
|
||||
*UART_THR = c;
|
||||
}
|
||||
|
||||
char uartReceive(void) {
|
||||
volatile uint8_t *UART_RBR = (uint8_t*)0x10000000;
|
||||
volatile uint8_t *UART_LSR = (uint8_t*)0x10000005;
|
||||
|
||||
while (!(*UART_LSR & (1<<0))); // wait for DR (Data Ready)
|
||||
return *UART_RBR;
|
||||
}
|
||||
|
||||
char uartPutStr(const char *str) {
|
||||
while (*str) {
|
||||
uartSend(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// End of code added for Wally
|
||||
//////////////////////////////
|
||||
|
||||
static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
volatile uint64_t magic_mem[8] __attribute__((aligned(64)));
|
||||
@ -76,7 +114,19 @@ void abort()
|
||||
|
||||
void printstr(const char* s)
|
||||
{
|
||||
syscall(SYS_write, 1, (uintptr_t)s, strlen(s));
|
||||
// david_harris@hmc.edu 11/30/24 switch to printing via UART rather than syscall
|
||||
// This works on both Spike and Wally simulations
|
||||
//syscall(SYS_write, 1, (uintptr_t)s, strlen(s));
|
||||
uartPutStr(s);
|
||||
}
|
||||
|
||||
// Added 30 November 2024 David_Harris@hmc.edu
|
||||
// The compiler encountering printf with a pure string argument tries to invoke puts
|
||||
// rather than the usual printf, so puts must be defined.
|
||||
int puts(const char* s)
|
||||
{
|
||||
printstr(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__((weak)) thread_entry(int cid, int nc)
|
||||
@ -107,6 +157,7 @@ void _init(int cid, int nc)
|
||||
{
|
||||
init_tls();
|
||||
thread_entry(cid, nc);
|
||||
uartInit(); // added 11/30/2024 David_Harris@hmc.edu for printing via UART
|
||||
|
||||
// only single-threaded programs should ever get here.
|
||||
int ret = main(0, 0);
|
||||
@ -125,6 +176,11 @@ void _init(int cid, int nc)
|
||||
#undef putchar
|
||||
int putchar(int ch)
|
||||
{
|
||||
// David_Harris@hmc.edu 11/30/2024
|
||||
// Replaced syscall with uartSend
|
||||
uartSend(ch);
|
||||
|
||||
/*
|
||||
static __thread char buf[64] __attribute__((aligned(64)));
|
||||
static __thread int buflen = 0;
|
||||
|
||||
@ -134,7 +190,7 @@ int putchar(int ch)
|
||||
{
|
||||
syscall(SYS_write, 1, (uintptr_t)buf, buflen);
|
||||
buflen = 0;
|
||||
}
|
||||
} */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
33
examples/C/gpio/Makefile
Normal file
33
examples/C/gpio/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
TARGET = gpio
|
||||
|
||||
$(TARGET).objdump: $(TARGET)
|
||||
riscv64-unknown-elf-objdump -S -D $(TARGET) > $(TARGET).objdump
|
||||
cp $(TARGET) $(TARGET).elf
|
||||
|
||||
$(TARGET): $(TARGET).c Makefile
|
||||
riscv64-unknown-elf-gcc -o $(TARGET) -gdwarf-2 -O\
|
||||
-march=rv64gc -mabi=lp64d -mcmodel=medany \
|
||||
-nostdlib -static -lm -fno-tree-loop-distribute-patterns \
|
||||
-T../common/test.ld -I../common \
|
||||
$(TARGET).c ../common/crt.S ../common/syscalls.c
|
||||
# Compiler flags:
|
||||
# -o $(TARGET) defines the name of the output file
|
||||
# -g generates debugging symbols for gdb
|
||||
# -O turns on basic optimization; -O3 turns on heavy optimization; omit for no optimization
|
||||
# -march=rv64gc -mabi=lp64d =mcmodel=medany generates code for RV64GC with doubles and long/ptrs = 64 bits
|
||||
# -static forces static linking (no dynamic shared libraries on bare metal)
|
||||
# -lm links the math library if necessary (when #include math.h)
|
||||
# -nostdlib avoids inserting standard startup files and default libraries
|
||||
# because we are using crt.s on bare metal
|
||||
# -fno-tree-loop-distribute-patterns turns replacing loops with memcpy/memset in the std library
|
||||
# -T specifies the linker file
|
||||
# -I specifies the include path (e.g. for util.h)
|
||||
# The last line defines the C files to compile.
|
||||
# crt.S is needed as our startup file to initialize the processor
|
||||
# syscalls.c implements printf through the HTIF for Spike
|
||||
# other flags from riscv-tests makefiles that don't seem to be important
|
||||
# -ffast-math -DPREALLOCATE=1 -std=gnu99 \
|
||||
# -fno-common -fno-builtin-printf -nostartfiles -lgcc \
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(TARGET).objdump
|
28
examples/C/gpio/gpio.c
Normal file
28
examples/C/gpio/gpio.c
Normal file
@ -0,0 +1,28 @@
|
||||
// gpio.c
|
||||
// David_Harris@hmc.edu 30 November 2024
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
|
||||
// General-Purpose I/O (GPIO) example program illustrating compiled C code
|
||||
// compile with make
|
||||
// simulate with: wsim rv64gc hello.elf --sim verilator
|
||||
|
||||
#include <stdio.h>
|
||||
#include "gpiolib.h"
|
||||
|
||||
int main(void) {
|
||||
printf("GPIO Example!\n\r");
|
||||
pinMode(0, INPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
// Read pin 0 and write it to pin 1
|
||||
int val = digitalRead(0);
|
||||
printf("Pin 0: %d\n", val);
|
||||
digitalWrite(1, val);
|
||||
|
||||
// Toggle pin 2
|
||||
printf("Pin 2: %d\n", i%2);
|
||||
digitalWrite(2, i%2);
|
||||
}
|
||||
}
|
81
examples/C/gpio/gpiolib.h
Normal file
81
examples/C/gpio/gpiolib.h
Normal file
@ -0,0 +1,81 @@
|
||||
// gpiolib.h
|
||||
// Basic Arduino-compatible functions for general-purpose input/output
|
||||
|
||||
// Assumes GPIO0_BASE is set to the memory-mapped GPIO address from
|
||||
// config/rv64gc/config.vh.
|
||||
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Bitfield Structs
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t input_val; // (GPIO offset 0x00) Pin value
|
||||
volatile uint32_t input_en; // (GPIO offset 0x04) Pin input enable*
|
||||
volatile uint32_t output_en; // (GPIO offset 0x08) Pin output enable*
|
||||
volatile uint32_t output_val; // (GPIO offset 0x0C) Output value
|
||||
volatile uint32_t pue; // (GPIO offset 0x10) Internal pull-up enable*
|
||||
volatile uint32_t ds; // (GPIO offset 0x14) Pin drive strength
|
||||
volatile uint32_t rise_ie; // (GPIO offset 0x18) Rise interrupt enable
|
||||
volatile uint32_t rise_ip; // (GPIO offset 0x1C) Rise interrupt pending
|
||||
volatile uint32_t fall_ie; // (GPIO offset 0x20) Fall interrupt enable
|
||||
volatile uint32_t fall_ip; // (GPIO offset 0x24) Fall interrupt pending
|
||||
volatile uint32_t high_ie; // (GPIO offset 0x28) High interrupt enable
|
||||
volatile uint32_t high_ip; // (GPIO offset 0x2C) High interrupt pending
|
||||
volatile uint32_t low_ie; // (GPIO offset 0x30) Low interrupt enable
|
||||
volatile uint32_t low_ip; // (GPIO offset 0x34) Low interrupt pending
|
||||
volatile uint32_t iof_en; // (GPIO offset 0x38) HW-Driven functions enable
|
||||
volatile uint32_t iof_sel; // (GPIO offset 0x3C) HW-Driven functions selection
|
||||
volatile uint32_t out_xor; // (GPIO offset 0x40) Output XOR (invert)
|
||||
// Registers marked with * are asynchronously reset to 0. All others are synchronously reset to 0.
|
||||
} GPIO;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GPIO Constant Definitions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GPIO0_BASE (0x10060000U) // GPIO memory-mapped base address
|
||||
|
||||
#define GPIO0 ((GPIO*) GPIO0_BASE) // Set up pointer to struct of type GPIO aligned at the base GPIO0 memory-mapped address
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
#define GPIO_IOF0 2
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GPIO Functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void pinMode(int pin, int function)
|
||||
{
|
||||
switch(function) {
|
||||
case INPUT:
|
||||
GPIO0->input_en |= (1 << pin); // Sets a pin as an input
|
||||
break;
|
||||
case OUTPUT:
|
||||
GPIO0->output_en |= (1 << pin); // Set pin as an output
|
||||
GPIO0->iof_en &= ~(1 << pin);
|
||||
break;
|
||||
case GPIO_IOF0:
|
||||
GPIO0->iof_sel &= ~(1 << pin);
|
||||
GPIO0->iof_en |= (1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(int pin, int val)
|
||||
{
|
||||
if (val) GPIO0->output_val |= (1 << pin);
|
||||
else GPIO0->output_val &= ~(1 << pin);
|
||||
}
|
||||
|
||||
int digitalRead(int pin)
|
||||
{
|
||||
return (GPIO0->input_val >> pin) & 0x1;
|
||||
}
|
33
examples/C/hello/Makefile
Normal file
33
examples/C/hello/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
TARGET = hello
|
||||
|
||||
$(TARGET).objdump: $(TARGET)
|
||||
riscv64-unknown-elf-objdump -S -D $(TARGET) > $(TARGET).objdump
|
||||
cp $(TARGET) $(TARGET).elf
|
||||
|
||||
$(TARGET): $(TARGET).c Makefile
|
||||
riscv64-unknown-elf-gcc -o $(TARGET) -gdwarf-2 -O\
|
||||
-march=rv64gc -mabi=lp64d -mcmodel=medany \
|
||||
-nostdlib -static -lm -fno-tree-loop-distribute-patterns \
|
||||
-T../common/test.ld -I../common \
|
||||
$(TARGET).c ../common/crt.S ../common/syscalls.c
|
||||
# Compiler flags:
|
||||
# -o $(TARGET) defines the name of the output file
|
||||
# -g generates debugging symbols for gdb
|
||||
# -O turns on basic optimization; -O3 turns on heavy optimization; omit for no optimization
|
||||
# -march=rv64gc -mabi=lp64d =mcmodel=medany generates code for RV64GC with doubles and long/ptrs = 64 bits
|
||||
# -static forces static linking (no dynamic shared libraries on bare metal)
|
||||
# -lm links the math library if necessary (when #include math.h)
|
||||
# -nostdlib avoids inserting standard startup files and default libraries
|
||||
# because we are using crt.s on bare metal
|
||||
# -fno-tree-loop-distribute-patterns turns replacing loops with memcpy/memset in the std library
|
||||
# -T specifies the linker file
|
||||
# -I specifies the include path (e.g. for util.h)
|
||||
# The last line defines the C files to compile.
|
||||
# crt.S is needed as our startup file to initialize the processor
|
||||
# syscalls.c implements printf through the HTIF for Spike
|
||||
# other flags from riscv-tests makefiles that don't seem to be important
|
||||
# -ffast-math -DPREALLOCATE=1 -std=gnu99 \
|
||||
# -fno-common -fno-builtin-printf -nostartfiles -lgcc \
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(TARGET).objdump
|
25
examples/C/hello/hello.c
Normal file
25
examples/C/hello/hello.c
Normal file
@ -0,0 +1,25 @@
|
||||
// hello.c
|
||||
// David_Harris@hmc.edu 30 November 2024
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
|
||||
// Hello World program illustrating compiled C code printing via the UART
|
||||
// The Wally team has modified the Berkeley syscalls.c (in examples/C/common)
|
||||
// to print via UART rather than the syscall interface. This is supported
|
||||
// on both Spike and Wally. It assumes the PC16550-compatible UART is at
|
||||
// the default SiFive address of 0x10000000.
|
||||
// Note that there seem to be some discrepancies between the UART and Spike
|
||||
// such that using \n\r for new lines works best.
|
||||
|
||||
// compile with make
|
||||
// simulate Wally with: wsim rv64gc hello.elf --sim verilator
|
||||
// simulate in Spike with: spike hello.elf
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("Hello Wally!\n\r");
|
||||
for (int i = 0; i < 10; i++) {
|
||||
printf("%d ", i);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
Loading…
Reference in New Issue
Block a user