mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 04:57:25 -04:00
Added simple system
Simple system is a basic verilator top-level testbench for running executables. It has functionality for outputting text to a log file and for the software to terminate the simulation
This commit is contained in:
parent
31d423ae47
commit
2041f10c69
14 changed files with 970 additions and 0 deletions
107
examples/simple_system/README.md
Normal file
107
examples/simple_system/README.md
Normal file
|
@ -0,0 +1,107 @@
|
|||
# Ibex Simple System
|
||||
|
||||
Simple System gives you an Ibex based system simulated by Verilator that can
|
||||
run stand-alone binaries. It contains:
|
||||
|
||||
* An Ibex Core
|
||||
* A single memory for instructions and data
|
||||
* A basic peripheral to write ASCII output to a file and halt simulation from
|
||||
software
|
||||
* A software framework to build programs for it
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* [Verilator](https://www.veripool.org/wiki/verilator)
|
||||
Note Linux package managers may have Verilator but often a very old version
|
||||
that is not suitable. It is recommended Verilator is built from source.
|
||||
* [FuseSoC](https://github.com/olofk/fusesoc)
|
||||
* RISC-V Compiler Toolchain - lowRISC provides a pre-built GCC based toolchain
|
||||
<https://github.com/lowRISC/lowrisc-toolchains/releases>
|
||||
|
||||
## Building Simulation
|
||||
|
||||
The Simple System simulator binary can be built via FuseSoC. From the Ibex
|
||||
repository root run:
|
||||
|
||||
```
|
||||
fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system --RV32M=1 --RV32E=0
|
||||
```
|
||||
|
||||
## Building Software
|
||||
|
||||
Simple System related software can be found in examples/sw/simple_system
|
||||
|
||||
To build the hello world example, from the Ibex reposistory root run:
|
||||
|
||||
```
|
||||
make -C examples/sw/simple_system/hello_test
|
||||
```
|
||||
|
||||
This should create the file
|
||||
examples/sw/simple_system/hello_test/hello_test.vmem which is the memory
|
||||
initialisation file used to run the hello_test program
|
||||
|
||||
To build new software make a copy of the hello_test directory named as desired.
|
||||
Look inside the Makefile for further instructions.
|
||||
|
||||
If using a toolchain other than the lowRISC pre-built one
|
||||
examples/sw/simple_system/common/common.mk may need altering to point to the
|
||||
correct compiler binaries.
|
||||
|
||||
## Running the Simulator
|
||||
|
||||
Having built the simulator and software, from the Ibex repository root run:
|
||||
|
||||
```
|
||||
./build/lowrisc_ibex_ibex_simple_system_0/sim-verilator/Vibex_simple_system [-t] --raminit=<sw_vmem_file>
|
||||
```
|
||||
|
||||
`<sw_vmem_file>` should be a path to a vmem file built as described above, use
|
||||
./examples/sw/simple_system/hello_test/hello_test.vmem to run the hello_test
|
||||
binary.
|
||||
|
||||
Pass `-t` to get an FST trace of execution that be viewed with [GTKWave](http://gtkwave.sourceforge.net/)
|
||||
If using the hello_test binary the simulator will halt itself, outputting some
|
||||
simulation statistics:
|
||||
|
||||
```
|
||||
Simulation statistics
|
||||
=====================
|
||||
Executed cycles: 633
|
||||
Wallclock time: 0.013 s
|
||||
Simulation speed: 48692.3 cycles/s (48.6923 kHz)
|
||||
|
||||
Performance Counters
|
||||
====================
|
||||
Cycles: 483
|
||||
NONE: 0
|
||||
Instructions Retired: 266
|
||||
LSU Busy: 59
|
||||
Fetch Wait: 16
|
||||
Loads: 21
|
||||
Stores: 38
|
||||
Jumps: 46
|
||||
Conditional Branches: 53
|
||||
Taken Conditional Branches: 48
|
||||
Compressed Instructions: 182
|
||||
```
|
||||
|
||||
The simulator produces several output files
|
||||
|
||||
* ibex_simple_system.log - The ASCII output written via the output peripheral
|
||||
* ibex_simple_system_pcount.csv - A csv of the performance counters
|
||||
* trace_core_00000000.log - An instruction trace of execution
|
||||
|
||||
## System Memory Map
|
||||
|
||||
+---------------------|-----------------------------------------------------------------------------+
|
||||
| Address | Description |
|
||||
+=====================|=============================================================================+
|
||||
| 0x20000 | ASCII Out, write ASCII characters here that will get output to the log file |
|
||||
+---------------------|-----------------------------------------------------------------------------+
|
||||
| 0x20004 | Simulator Halt, write 1 here to halt the simulation |
|
||||
+---------------------|-----------------------------------------------------------------------------+
|
||||
| 0x100000 - 0x1FFFFF | 1 MB memory for instruction and data. Execution starts at 0x100080, |
|
||||
| | exception handler base is 0x100000 |
|
||||
+---------------------|-----------------------------------------------------------------------------+
|
||||
|
50
examples/simple_system/ibex_simple_system.cc
Normal file
50
examples/simple_system/ibex_simple_system.cc
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
|
||||
#include "ibex_pcounts.h"
|
||||
#include "verilated_toplevel.h"
|
||||
#include "verilator_sim_ctrl.h"
|
||||
|
||||
std::shared_ptr<VerilatorSimCtrl> simctrl(nullptr);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int retcode;
|
||||
|
||||
auto top = std::make_shared<ibex_simple_system>();
|
||||
|
||||
simctrl = std::make_shared<VerilatorSimCtrl>(
|
||||
top.get(), top->IO_CLK, top->IO_RST_N,
|
||||
VerilatorSimCtrlFlags::ResetPolarityNegative);
|
||||
|
||||
retcode = simctrl->SetupSimulation(argc, argv);
|
||||
|
||||
if (retcode != 0)
|
||||
return retcode;
|
||||
|
||||
// Initialize RAM
|
||||
simctrl->InitRam("TOP.ibex_simple_system.u_ram");
|
||||
|
||||
std::cout << "Simulation of Ibex" << std::endl
|
||||
<< "==================" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
simctrl->RunSimulation();
|
||||
|
||||
std::cout << "\nPerformance Counters" << std::endl
|
||||
<< "====================" << std::endl;
|
||||
std::cout << ibex_pcount_string(
|
||||
top->ibex_simple_system__DOT__mhpmcounter_vals, false);
|
||||
|
||||
std::ofstream pcount_csv("ibex_simple_system_pcount.csv");
|
||||
pcount_csv << ibex_pcount_string(
|
||||
top->ibex_simple_system__DOT__mhpmcounter_vals, true);
|
||||
|
||||
return 0;
|
||||
}
|
63
examples/simple_system/ibex_simple_system.core
Normal file
63
examples/simple_system/ibex_simple_system.core
Normal file
|
@ -0,0 +1,63 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:ibex:ibex_simple_system"
|
||||
description: "Generic simple system for running binaries on ibex using verilator"
|
||||
filesets:
|
||||
files_sim_verilator:
|
||||
depend:
|
||||
- lowrisc:dv_verilator:simutil_verilator
|
||||
- lowrisc:ibex:ibex_core_tracing
|
||||
- lowrisc:ibex:sim_shared
|
||||
- lowrisc:dv_verilator:ibex_pcounts
|
||||
files:
|
||||
- rtl/ibex_simple_system.sv
|
||||
- ibex_simple_system.cc: { file_type: cppSource }
|
||||
file_type: systemVerilogSource
|
||||
|
||||
parameters:
|
||||
RV32M:
|
||||
datatype: int
|
||||
paramtype: vlogparam
|
||||
default: 1
|
||||
description: Enable the M ISA extension (hardware multiply/divide) [0/1]
|
||||
RV32E:
|
||||
datatype: int
|
||||
paramtype: vlogparam
|
||||
default: 0
|
||||
description: Enable the E ISA extension (reduced register set) [0/1]
|
||||
|
||||
targets:
|
||||
sim:
|
||||
default_tool: verilator
|
||||
filesets:
|
||||
- files_sim_verilator
|
||||
parameters:
|
||||
- RV32M
|
||||
- RV32E
|
||||
toplevel: ibex_simple_system
|
||||
tools:
|
||||
verilator:
|
||||
mode: cc
|
||||
verilator_options:
|
||||
# Disabling tracing reduces compile times by multiple times, but doesn't have a
|
||||
# huge influence on runtime performance. (Based on early observations.)
|
||||
- '--trace'
|
||||
- '--trace-fst' # this requires -DVM_TRACE_FMT_FST in CFLAGS below!
|
||||
- '--trace-structs'
|
||||
- '--trace-params'
|
||||
- '--trace-max-array 1024'
|
||||
# compiler flags
|
||||
#
|
||||
# -O
|
||||
# Optimization levels have a large impact on the runtime performance of the
|
||||
# simulation model. -O2 and -O3 are pretty similar, -Os is slower than -O2/-O3
|
||||
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=ibex_simple_system -g -O0"'
|
||||
- '-LDFLAGS "-pthread -lutil"'
|
||||
- "-Wall"
|
||||
- "-Wno-PINCONNECTEMPTY"
|
||||
# XXX: Cleanup all warnings and remove this option
|
||||
# (or make it more fine-grained at least)
|
||||
- "-Wno-fatal"
|
||||
|
191
examples/simple_system/rtl/ibex_simple_system.sv
Normal file
191
examples/simple_system/rtl/ibex_simple_system.sv
Normal file
|
@ -0,0 +1,191 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Ibex simple system
|
||||
*
|
||||
* This is a basic system consisting of an ibex, a 1 MB sram for instruction/data
|
||||
* and a small memory mapped control module for outputting ASCII text and
|
||||
* controlling/halting the simulation from the software running on the ibex.
|
||||
*
|
||||
* It is designed to be used with verilator but should work with other
|
||||
* simulators, a small amount of work may be required to support the
|
||||
* simulator_ctrl module.
|
||||
*/
|
||||
module ibex_simple_system (
|
||||
input IO_CLK,
|
||||
input IO_RST_N
|
||||
);
|
||||
|
||||
parameter bit RV32E = 0;
|
||||
parameter bit RV32M = 1;
|
||||
|
||||
logic clk_sys, rst_sys_n;
|
||||
|
||||
assign clk_sys = IO_CLK;
|
||||
assign rst_sys_n = IO_RST_N;
|
||||
|
||||
typedef enum {
|
||||
CoreD,
|
||||
CoreI
|
||||
} bus_host_e;
|
||||
|
||||
typedef enum {
|
||||
Ram,
|
||||
SimCtrl
|
||||
} bus_device_e;
|
||||
|
||||
localparam NrDevices = 2;
|
||||
localparam NrHosts = 2;
|
||||
|
||||
// host and device signals
|
||||
logic host_req [NrHosts];
|
||||
logic host_gnt [NrHosts];
|
||||
logic [31:0] host_addr [NrHosts];
|
||||
logic host_we [NrHosts];
|
||||
logic [ 3:0] host_be [NrHosts];
|
||||
logic [31:0] host_wdata [NrHosts];
|
||||
logic host_rvalid [NrHosts];
|
||||
logic [31:0] host_rdata [NrHosts];
|
||||
logic host_err [NrHosts];
|
||||
|
||||
// devices (slaves)
|
||||
logic device_req [NrDevices];
|
||||
logic [31:0] device_addr [NrDevices];
|
||||
logic device_we [NrDevices];
|
||||
logic [ 3:0] device_be [NrDevices];
|
||||
logic [31:0] device_wdata [NrDevices];
|
||||
logic device_rvalid [NrDevices];
|
||||
logic [31:0] device_rdata [NrDevices];
|
||||
logic device_err [NrDevices];
|
||||
|
||||
// Device address mapping
|
||||
logic [31:0] cfg_device_addr_base [NrDevices];
|
||||
logic [31:0] cfg_device_addr_mask [NrDevices];
|
||||
assign cfg_device_addr_base[Ram] = 32'h100000;
|
||||
assign cfg_device_addr_mask[Ram] = ~32'hFFFFF; // 1 MB
|
||||
assign cfg_device_addr_base[SimCtrl] = 32'h20000;
|
||||
assign cfg_device_addr_mask[SimCtrl] = ~32'h3FF; // 1 kB
|
||||
|
||||
|
||||
bus #(
|
||||
.NrDevices (NrDevices),
|
||||
.NrHosts (NrHosts ),
|
||||
.DataWidth (32 ),
|
||||
.AddressWidth(32 )
|
||||
) u_bus (
|
||||
.clk_i (clk_sys),
|
||||
.rst_ni (rst_sys_n),
|
||||
|
||||
.host_req_i (host_req ),
|
||||
.host_gnt_o (host_gnt ),
|
||||
.host_addr_i (host_addr ),
|
||||
.host_we_i (host_we ),
|
||||
.host_be_i (host_be ),
|
||||
.host_wdata_i (host_wdata ),
|
||||
.host_rvalid_o (host_rvalid ),
|
||||
.host_rdata_o (host_rdata ),
|
||||
.host_err_o (host_err ),
|
||||
|
||||
.device_req_o (device_req ),
|
||||
.device_addr_o (device_addr ),
|
||||
.device_we_o (device_we ),
|
||||
.device_be_o (device_be ),
|
||||
.device_wdata_o (device_wdata ),
|
||||
.device_rvalid_i (device_rvalid),
|
||||
.device_rdata_i (device_rdata ),
|
||||
.device_err_i (device_err ),
|
||||
|
||||
.cfg_device_addr_base,
|
||||
.cfg_device_addr_mask
|
||||
);
|
||||
|
||||
assign host_we[CoreI] = 1'b0;
|
||||
assign host_be[CoreI] = 4'b1111;
|
||||
assign host_wdata[CoreI] = 32'b0;
|
||||
|
||||
ibex_core_tracing #(
|
||||
.MHPMCounterNum(29),
|
||||
.DmHaltAddr(32'h00100000),
|
||||
.DmExceptionAddr(32'h00100000),
|
||||
.RV32E(RV32E),
|
||||
.RV32M(RV32M)
|
||||
) u_core (
|
||||
.clk_i (clk_sys),
|
||||
.rst_ni (rst_sys_n),
|
||||
|
||||
.test_en_i ('b0),
|
||||
|
||||
.hart_id_i (32'b0),
|
||||
// First instruction executed is at 0x0 + 0x80
|
||||
.boot_addr_i (32'h00100000),
|
||||
|
||||
.instr_req_o (host_req[CoreI]),
|
||||
.instr_gnt_i (host_gnt[CoreI]),
|
||||
.instr_rvalid_i (host_rvalid[CoreI]),
|
||||
.instr_addr_o (host_addr[CoreI]),
|
||||
.instr_rdata_i (host_rdata[CoreI]),
|
||||
.instr_err_i (host_err[CoreI]),
|
||||
|
||||
.data_req_o (host_req[CoreD]),
|
||||
.data_gnt_i (host_gnt[CoreD]),
|
||||
.data_rvalid_i (host_rvalid[CoreD]),
|
||||
.data_we_o (host_we[CoreD]),
|
||||
.data_be_o (host_be[CoreD]),
|
||||
.data_addr_o (host_addr[CoreD]),
|
||||
.data_wdata_o (host_wdata[CoreD]),
|
||||
.data_rdata_i (host_rdata[CoreD]),
|
||||
.data_err_i (host_err[CoreD]),
|
||||
|
||||
.irq_software_i (1'b0),
|
||||
.irq_timer_i (1'b0),
|
||||
.irq_external_i (1'b0),
|
||||
.irq_fast_i (15'b0),
|
||||
.irq_nm_i (1'b0),
|
||||
|
||||
.debug_req_i ('b0),
|
||||
|
||||
.fetch_enable_i ('b1),
|
||||
.core_sleep_o ()
|
||||
);
|
||||
|
||||
// SRAM block for instruction and data storage
|
||||
ram_1p #(
|
||||
.Depth(1024*1024/4)
|
||||
) u_ram (
|
||||
.clk_i (clk_sys),
|
||||
.rst_ni (rst_sys_n),
|
||||
.req_i (device_req[Ram]),
|
||||
.we_i (device_we[Ram]),
|
||||
.be_i (device_be[Ram]),
|
||||
.addr_i (device_addr[Ram]),
|
||||
.wdata_i (device_wdata[Ram]),
|
||||
.rvalid_o (device_rvalid[Ram]),
|
||||
.rdata_o (device_rdata[Ram])
|
||||
);
|
||||
|
||||
simulator_ctrl #(
|
||||
.LogName("ibex_simple_system.log")
|
||||
) u_simulator_ctrl (
|
||||
.clk_i (clk_sys),
|
||||
.rst_ni (rst_sys_n),
|
||||
|
||||
.req_i (device_req[SimCtrl]),
|
||||
.we_i (device_we[SimCtrl]),
|
||||
.be_i (device_be[SimCtrl]),
|
||||
.addr_i (device_addr[SimCtrl]),
|
||||
.wdata_i (device_wdata[SimCtrl]),
|
||||
.rvalid_o (device_rvalid[SimCtrl]),
|
||||
.rdata_o (device_rdata[SimCtrl])
|
||||
);
|
||||
|
||||
// Expose the performance counter array so it's easy to access in
|
||||
// a verilator siumulation
|
||||
logic [63:0] mhpmcounter_vals [32] /*verilator public_flat*/;
|
||||
|
||||
for(genvar i = 0;i < 32; i = i + 1) begin
|
||||
assign mhpmcounter_vals[i] = u_core.u_ibex_core.cs_registers_i.mhpmcounter_q[i];
|
||||
end
|
||||
endmodule
|
||||
|
69
examples/sw/simple_system/common/common.mk
Normal file
69
examples/sw/simple_system/common/common.mk
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
COMMON_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
COMMON_SRCS = $(wildcard $(COMMON_DIR)/*.c)
|
||||
INCS := -I$(COMMON_DIR)
|
||||
|
||||
# ARCH = rv32im # to disable compressed instructions
|
||||
ARCH ?= rv32imc
|
||||
|
||||
ifdef PROGRAM
|
||||
PROGRAM_C := $(PROGRAM).c
|
||||
endif
|
||||
|
||||
SRCS = $(COMMON_SRCS) $(PROGRAM_C) $(EXTRA_SRCS)
|
||||
|
||||
C_SRCS = $(filter %.c, $(SRCS))
|
||||
ASM_SRCS = $(filter %.S, $(SRCS))
|
||||
|
||||
CC = riscv32-unknown-elf-gcc
|
||||
|
||||
OBJCOPY ?= $(subst gcc,objcopy,$(wordlist 1,1,$(CC)))
|
||||
OBJDUMP ?= $(subst gcc,objdump,$(wordlist 1,1,$(CC)))
|
||||
|
||||
LINKER_SCRIPT ?= $(COMMON_DIR)/link.ld
|
||||
CRT ?= $(COMMON_DIR)/crt0.S
|
||||
CFLAGS ?= -march=$(ARCH) -mabi=ilp32 -static -mcmodel=medany -Wall -g -Os\
|
||||
-fvisibility=hidden -nostdlib -nostartfiles -ffreestanding $(PROGRAM_CFLAGS)
|
||||
|
||||
OBJS := ${C_SRCS:.c=.o} ${ASM_SRCS:.S=.o} ${CRT:.S=.o}
|
||||
DEPS = $(OBJS:%.o=%.d)
|
||||
|
||||
ifdef PROGRAM
|
||||
OUTFILES := $(PROGRAM).elf $(PROGRAM).vmem $(PROGRAM).bin $(PROGRAM).dis
|
||||
else
|
||||
OUTFILES := $(OBJS)
|
||||
endif
|
||||
|
||||
all: $(OUTFILES)
|
||||
|
||||
$(PROGRAM).elf: $(OBJS) $(LINKER_SCRIPT)
|
||||
$(CC) $(CFLAGS) -T $(LINKER_SCRIPT) $(OBJS) -o $@ $(LIBS)
|
||||
|
||||
%.dis: %.elf
|
||||
$(OBJDUMP) -fhSD $^ > $@
|
||||
|
||||
# Note: this target requires the srecord package to be installed.
|
||||
# XXX: This could be replaced by objcopy once
|
||||
# https://sourceware.org/bugzilla/show_bug.cgi?id=19921
|
||||
# is widely available.
|
||||
%.vmem: %.bin
|
||||
srec_cat $^ -binary -offset 0x0000 -byte-swap 4 -o $@ -vmem
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) -f $(OBJS) $(DEPS)
|
||||
|
||||
distclean: clean
|
||||
$(RM) -f $(OUTFILES)
|
97
examples/sw/simple_system/common/crt0.S
Normal file
97
examples/sw/simple_system/common/crt0.S
Normal file
|
@ -0,0 +1,97 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "simple_system_regs.h"
|
||||
|
||||
.section .text
|
||||
|
||||
default_exc_handler:
|
||||
jal x0, simple_exc_handler
|
||||
|
||||
reset_handler:
|
||||
/* set all registers to zero */
|
||||
mv x1, x0
|
||||
mv x2, x1
|
||||
mv x3, x1
|
||||
mv x4, x1
|
||||
mv x5, x1
|
||||
mv x6, x1
|
||||
mv x7, x1
|
||||
mv x8, x1
|
||||
mv x9, x1
|
||||
mv x10, x1
|
||||
mv x11, x1
|
||||
mv x12, x1
|
||||
mv x13, x1
|
||||
mv x14, x1
|
||||
mv x15, x1
|
||||
mv x16, x1
|
||||
mv x17, x1
|
||||
mv x18, x1
|
||||
mv x19, x1
|
||||
mv x20, x1
|
||||
mv x21, x1
|
||||
mv x22, x1
|
||||
mv x23, x1
|
||||
mv x24, x1
|
||||
mv x25, x1
|
||||
mv x26, x1
|
||||
mv x27, x1
|
||||
mv x28, x1
|
||||
mv x29, x1
|
||||
mv x30, x1
|
||||
mv x31, x1
|
||||
|
||||
/* stack initilization */
|
||||
la x2, _stack_start
|
||||
|
||||
_start:
|
||||
.global _start
|
||||
|
||||
/* clear BSS */
|
||||
la x26, _bss_start
|
||||
la x27, _bss_end
|
||||
|
||||
bge x26, x27, zero_loop_end
|
||||
|
||||
zero_loop:
|
||||
sw x0, 0(x26)
|
||||
addi x26, x26, 4
|
||||
ble x26, x27, zero_loop
|
||||
zero_loop_end:
|
||||
|
||||
|
||||
main_entry:
|
||||
/* jump to main program entry point (argc = argv = 0) */
|
||||
addi x10, x0, 0
|
||||
addi x11, x0, 0
|
||||
jal x1, main
|
||||
|
||||
/* Halt simulation */
|
||||
la x5, SIM_CTRL_BASE + SIM_CTRL_CTRL
|
||||
li x6, 1
|
||||
sw x6, 0(x5)
|
||||
|
||||
/* If execution ends up here just put the core to sleep */
|
||||
sleep_loop:
|
||||
wfi
|
||||
j sleep_loop
|
||||
|
||||
/* =================================================== [ exceptions ] === */
|
||||
/* This section has to be down here, since we have to disable rvc for it */
|
||||
|
||||
.section .vectors, "ax"
|
||||
.option norvc;
|
||||
|
||||
// All traps go to the same default_exc_handler. Create a landing pad of nops
|
||||
// as IRQs can come into different addresses.
|
||||
.org 0x00
|
||||
.rept 31
|
||||
nop
|
||||
.endr
|
||||
jal x0, default_exc_handler
|
||||
|
||||
// reset vector
|
||||
.org 0x80
|
||||
jal x0, reset_handler
|
63
examples/sw/simple_system/common/link.ld
Normal file
63
examples/sw/simple_system/common/link.ld
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* Copyright lowRISC contributors.
|
||||
Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
OUTPUT_ARCH(riscv)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* 992 kB should be enough for anybody... */
|
||||
ram : ORIGIN = 0x00100000, LENGTH = 0xF8000 /* 992 kB */
|
||||
stack : ORIGIN = 0x001F8000, LENGTH = 0x8000 /* 32 kB */
|
||||
}
|
||||
|
||||
/* Stack information variables */
|
||||
_min_stack = 0x2000; /* 8K - minimum stack space to reserve */
|
||||
_stack_len = LENGTH(stack);
|
||||
_stack_start = ORIGIN(stack) + LENGTH(stack);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vectors :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.vectors))
|
||||
} > ram
|
||||
|
||||
.text : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} > ram
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata);
|
||||
*(.rodata.*)
|
||||
} > ram
|
||||
|
||||
.data : {
|
||||
. = ALIGN(4);
|
||||
*(.data);
|
||||
*(.data.*)
|
||||
} > ram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_bss_start = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
_bss_end = .;
|
||||
} > ram
|
||||
|
||||
/* ensure there is enough room for stack */
|
||||
.stack (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
. = . + _min_stack ;
|
||||
. = ALIGN(4);
|
||||
stack = . ;
|
||||
_stack = . ;
|
||||
} > stack
|
||||
}
|
141
examples/sw/simple_system/common/simple_system_common.c
Normal file
141
examples/sw/simple_system/common/simple_system_common.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "simple_system_common.h"
|
||||
|
||||
int putchar(int c) {
|
||||
DEV_WRITE(SIM_CTRL_BASE + SIM_CTRL_OUT, (unsigned char)c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int puts(const char *str) {
|
||||
while (*str) {
|
||||
putchar(*str++);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void puthex(uint32_t h) {
|
||||
int cur_digit;
|
||||
// Iterate through h taking top 4 bits each time and outputting ASCII of hex
|
||||
// digit for those 4 bits
|
||||
for (int i = 0; i < 8; i++) {
|
||||
cur_digit = h >> 28;
|
||||
|
||||
if (cur_digit < 10)
|
||||
putchar('0' + cur_digit);
|
||||
else
|
||||
putchar('A' - 10 + cur_digit);
|
||||
|
||||
h <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void sim_halt() { DEV_WRITE(SIM_CTRL_BASE + SIM_CTRL_CTRL, 1); }
|
||||
|
||||
void pcount_reset() {
|
||||
asm volatile(
|
||||
"csrw minstret, x0\n"
|
||||
"csrw mcycle, x0\n"
|
||||
"csrw mhpmcounter3, x0\n"
|
||||
"csrw mhpmcounter4, x0\n"
|
||||
"csrw mhpmcounter5, x0\n"
|
||||
"csrw mhpmcounter6, x0\n"
|
||||
"csrw mhpmcounter7, x0\n"
|
||||
"csrw mhpmcounter8, x0\n"
|
||||
"csrw mhpmcounter9, x0\n"
|
||||
"csrw mhpmcounter10, x0\n"
|
||||
"csrw mhpmcounter11, x0\n"
|
||||
"csrw mhpmcounter12, x0\n"
|
||||
"csrw mhpmcounter13, x0\n"
|
||||
"csrw mhpmcounter14, x0\n"
|
||||
"csrw mhpmcounter15, x0\n"
|
||||
"csrw mhpmcounter16, x0\n"
|
||||
"csrw mhpmcounter17, x0\n"
|
||||
"csrw mhpmcounter18, x0\n"
|
||||
"csrw mhpmcounter19, x0\n"
|
||||
"csrw mhpmcounter20, x0\n"
|
||||
"csrw mhpmcounter21, x0\n"
|
||||
"csrw mhpmcounter22, x0\n"
|
||||
"csrw mhpmcounter23, x0\n"
|
||||
"csrw mhpmcounter24, x0\n"
|
||||
"csrw mhpmcounter25, x0\n"
|
||||
"csrw mhpmcounter26, x0\n"
|
||||
"csrw mhpmcounter27, x0\n"
|
||||
"csrw mhpmcounter28, x0\n"
|
||||
"csrw mhpmcounter29, x0\n"
|
||||
"csrw mhpmcounter30, x0\n"
|
||||
"csrw mhpmcounter31, x0\n"
|
||||
"csrw minstreth, x0\n"
|
||||
"csrw mcycleh, x0\n"
|
||||
"csrw mhpmcounter3h, x0\n"
|
||||
"csrw mhpmcounter4h, x0\n"
|
||||
"csrw mhpmcounter5h, x0\n"
|
||||
"csrw mhpmcounter6h, x0\n"
|
||||
"csrw mhpmcounter7h, x0\n"
|
||||
"csrw mhpmcounter8h, x0\n"
|
||||
"csrw mhpmcounter9h, x0\n"
|
||||
"csrw mhpmcounter10h, x0\n"
|
||||
"csrw mhpmcounter11h, x0\n"
|
||||
"csrw mhpmcounter12h, x0\n"
|
||||
"csrw mhpmcounter13h, x0\n"
|
||||
"csrw mhpmcounter14h, x0\n"
|
||||
"csrw mhpmcounter15h, x0\n"
|
||||
"csrw mhpmcounter16h, x0\n"
|
||||
"csrw mhpmcounter17h, x0\n"
|
||||
"csrw mhpmcounter18h, x0\n"
|
||||
"csrw mhpmcounter19h, x0\n"
|
||||
"csrw mhpmcounter20h, x0\n"
|
||||
"csrw mhpmcounter21h, x0\n"
|
||||
"csrw mhpmcounter22h, x0\n"
|
||||
"csrw mhpmcounter23h, x0\n"
|
||||
"csrw mhpmcounter24h, x0\n"
|
||||
"csrw mhpmcounter25h, x0\n"
|
||||
"csrw mhpmcounter26h, x0\n"
|
||||
"csrw mhpmcounter27h, x0\n"
|
||||
"csrw mhpmcounter28h, x0\n"
|
||||
"csrw mhpmcounter29h, x0\n"
|
||||
"csrw mhpmcounter30h, x0\n"
|
||||
"csrw mhpmcounter31h, x0\n");
|
||||
}
|
||||
|
||||
void pcount_enable(int enable) {
|
||||
// Note cycle is disabled with everything else
|
||||
unsigned int inhibit_val = enable ? 0x0 : 0xFFFFFFFF;
|
||||
// mucounteren == mcountinhibit but binutils doesn't seem to known the
|
||||
// mcountinhibit name
|
||||
asm volatile("csrw mucounteren, %0\n" : : "r"(inhibit_val));
|
||||
}
|
||||
|
||||
unsigned int get_mepc() {
|
||||
uint32_t result;
|
||||
__asm__ volatile("csrr %0, mepc;" : "=r"(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int get_mcause() {
|
||||
uint32_t result;
|
||||
__asm__ volatile("csrr %0, mcause;" : "=r"(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int get_mtval() {
|
||||
uint32_t result;
|
||||
__asm__ volatile("csrr %0, mtval;" : "=r"(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void simple_exc_handler(void) {
|
||||
puts("EXCEPTION!!!\n");
|
||||
puts("============\n");
|
||||
puts("MEPC: 0x%0X");puthex(get_mepc());
|
||||
puts("\nMCAUSE: 0x%0X");puthex(get_mcause());
|
||||
puts("\nMTVAL: 0x%0X");puthex(get_mtval());
|
||||
putchar('\n');
|
||||
sim_halt();
|
||||
|
||||
while(1);
|
||||
}
|
58
examples/sw/simple_system/common/simple_system_common.h
Normal file
58
examples/sw/simple_system/common/simple_system_common.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#ifndef SIMPLE_SYSTEM_COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "simple_system_regs.h"
|
||||
|
||||
#define DEV_WRITE(addr, val) (*((volatile uint32_t *)(addr)) = val)
|
||||
#define DEV_READ(addr, val) (*((volatile uint32_t *)(addr)))
|
||||
|
||||
/**
|
||||
* Writes character to simulator out log. Signature matches c stdlib function
|
||||
* of the same name.
|
||||
*
|
||||
* @param c Character to output
|
||||
* @returns Character output (never fails so no EOF ever returned)
|
||||
*/
|
||||
int putchar(int c);
|
||||
|
||||
/**
|
||||
* Writes string to simulator out log. Signature matches c stdlib function of
|
||||
* the same name.
|
||||
*
|
||||
* @param str String to output
|
||||
* @returns 0 always (never fails so no error)
|
||||
*/
|
||||
int puts(const char *str);
|
||||
|
||||
/**
|
||||
* Writes ASCII hex representation of number to simulator out log.
|
||||
*
|
||||
* @param h Number to output in hex
|
||||
*/
|
||||
void puthex(uint32_t h);
|
||||
|
||||
/**
|
||||
* Immediately halts the simulation
|
||||
*/
|
||||
void sim_halt();
|
||||
|
||||
/**
|
||||
* Enables/disables performance counters. This effects mcycle and minstret as
|
||||
* well as the mhpmcounterN counters.
|
||||
*
|
||||
* @param enable if non-zero enables, otherwise disables
|
||||
*/
|
||||
void pcount_enable(int enable);
|
||||
|
||||
/**
|
||||
* Resets all performance counters. This effects mcycle and minstret as well
|
||||
* as the mhpmcounterN counters.
|
||||
*/
|
||||
void pcount_reset();
|
||||
|
||||
#endif
|
12
examples/sw/simple_system/common/simple_system_regs.h
Normal file
12
examples/sw/simple_system/common/simple_system_regs.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#ifndef SIMPLE_SYSTEM_REGS_H__
|
||||
#define SIMPLE_SYSTEM_REGS_H__
|
||||
|
||||
#define SIM_CTRL_BASE 0x20000
|
||||
#define SIM_CTRL_OUT 0x0
|
||||
#define SIM_CTRL_CTRL 0x4
|
||||
|
||||
#endif // SIMPLE_SYSTEM_REGS_H__
|
14
examples/sw/simple_system/hello_test/Makefile
Normal file
14
examples/sw/simple_system/hello_test/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Generate a baremetal application
|
||||
|
||||
# Name of the program $(PROGRAM).c will be added as a source file
|
||||
PROGRAM = hello_test
|
||||
PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
# Any extra source files to include in the build. Use the upper case .S
|
||||
# extension for assembly files
|
||||
EXTRA_SRCS :=
|
||||
|
||||
include ${PROGRAM_DIR}/../common/common.mk
|
21
examples/sw/simple_system/hello_test/hello_test.c
Normal file
21
examples/sw/simple_system/hello_test/hello_test.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "simple_system_common.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
pcount_enable(0);
|
||||
pcount_reset();
|
||||
pcount_enable(1);
|
||||
|
||||
puts("Hello simple system\n");
|
||||
puthex(0xDEADBEEF);
|
||||
putchar('\n');
|
||||
puthex(0xBAADF00D);
|
||||
putchar('\n');
|
||||
|
||||
pcount_enable(0);
|
||||
|
||||
return 0;
|
||||
}
|
83
shared/rtl/sim/simulator_ctrl.sv
Normal file
83
shared/rtl/sim/simulator_ctrl.sv
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Module for communicating with the simulator that interfaces via the memory
|
||||
* system.
|
||||
*
|
||||
* Contains two registers
|
||||
*
|
||||
* * 0x0 - CHAR_OUT_ADDR - [7:0] of write data output via output_char DPI call
|
||||
* and SimOutputManager (see dv/common/cpp/sim_output_manager.cc)
|
||||
* * 0x4 - SIM_CTRL_ADDR - Write 1 to bit 0 to halt sim
|
||||
*/
|
||||
|
||||
module simulator_ctrl #(
|
||||
// passed to simulator via log_name of output_char DPI call
|
||||
parameter string LogName = "ibex_out.log",
|
||||
// If set flush on every char (useful for monitoring output whilst
|
||||
// simulation is running).
|
||||
parameter bit FlushOnChar = 1
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
|
||||
input req_i,
|
||||
input we_i,
|
||||
input [ 3:0] be_i,
|
||||
input [31:0] addr_i,
|
||||
input [31:0] wdata_i,
|
||||
output logic rvalid_o,
|
||||
output logic [31:0] rdata_o
|
||||
);
|
||||
|
||||
localparam CHAR_OUT_ADDR = 0;
|
||||
localparam SIM_CTRL_ADDR = 1;
|
||||
|
||||
logic [7:0] ctrl_addr;
|
||||
|
||||
integer log_fd;
|
||||
|
||||
initial begin
|
||||
log_fd = $fopen(LogName, "w");
|
||||
end
|
||||
|
||||
final begin
|
||||
$fclose(log_fd);
|
||||
end
|
||||
|
||||
assign ctrl_addr = addr_i[9:2];
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
rvalid_o <= 0;
|
||||
end else begin
|
||||
// Immeditely respond to any request
|
||||
rvalid_o <= req_i;
|
||||
|
||||
if (req_i & we_i) begin
|
||||
case (ctrl_addr)
|
||||
CHAR_OUT_ADDR: begin
|
||||
if (be_i[0]) begin
|
||||
$fwrite(log_fd, "%c", wdata_i[7:0]);
|
||||
|
||||
if(FlushOnChar) begin
|
||||
$fflush(log_fd);
|
||||
end
|
||||
end
|
||||
end
|
||||
SIM_CTRL_ADDR: begin
|
||||
if (be_i[0] & wdata_i[0]) begin
|
||||
$display("Terminating simulation by software request.");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign rdata_o = '0;
|
||||
endmodule
|
||||
|
|
@ -10,6 +10,7 @@ filesets:
|
|||
- ./rtl/prim_clock_gating.sv
|
||||
- ./rtl/ram_1p.sv
|
||||
- ./rtl/bus.sv
|
||||
- ./rtl/sim/simulator_ctrl.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue