forked from Github_Repos/cvw
Merge branch 'tests' into icache-almost-working
This commit is contained in:
commit
6e803b724e
6
.gitignore
vendored
6
.gitignore
vendored
@ -17,3 +17,9 @@ wlft*
|
||||
/imperas-riscv-tests/ProgramMap.txt
|
||||
/wally-pipelined/busybear-testgen/gdbcombined.txt
|
||||
/wally-pipelined/busybear-testgen/first10.txt
|
||||
*.o
|
||||
*.d
|
||||
testsBP/*/*/*.elf*
|
||||
testsBP/*/OBJ/*
|
||||
testsBP/*/*.a
|
||||
|
||||
|
26
testsBP/crt0/Makefile
Normal file
26
testsBP/crt0/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
TARGETDIR := bin
|
||||
TARGET := $(TARGETDIR)/start
|
||||
ROOT := ..
|
||||
LIBRARY_DIRS :=
|
||||
LIBRARY_FILES :=
|
||||
|
||||
MARCH :=-march=rv64ic
|
||||
MABI :=-mabi=lp64
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
|
||||
|
||||
AFLAGS =$(MARCH) $(MABI) -march=rv64ic -mabi=lp64 -W
|
||||
CFLAGS =$(MARCH) $(MABI) -march=rv64ic -mabi=lp64 -mcmodel=medany
|
||||
AS=riscv64-unknown-elf-as
|
||||
CC=riscv64-unknown-elf-gcc
|
||||
AR=riscv64-unknown-elf-ar
|
||||
|
||||
all: libcrt0.a
|
||||
|
||||
%.o: %.s
|
||||
${AS} ${AFLAGS} -c $< -o $@
|
||||
|
||||
libcrt0.a: start.o
|
||||
${AR} -r $@ $^
|
||||
|
||||
clean:
|
||||
rm -rf *.a *.o
|
213
testsBP/crt0/isr.s
Normal file
213
testsBP/crt0/isr.s
Normal file
@ -0,0 +1,213 @@
|
||||
.section .text
|
||||
.global __trap_handler
|
||||
.type __trap_handler, @function
|
||||
|
||||
__trap_handler:
|
||||
# save the context of the cpu to the top of the current stack
|
||||
addi sp, sp, -124
|
||||
sw x1, 0x0(sp)
|
||||
sw x2, 0x4(sp)
|
||||
sw x3, 0x8(sp)
|
||||
sw x4, 0xC(sp)
|
||||
sw x5, 0x10(sp)
|
||||
sw x6, 0x14(sp)
|
||||
sw x7, 0x18(sp)
|
||||
sw x8, 0x1C(sp)
|
||||
sw x9, 0x20(sp)
|
||||
sw x10, 0x24(sp)
|
||||
sw x11, 0x28(sp)
|
||||
sw x12, 0x2C(sp)
|
||||
sw x13, 0x30(sp)
|
||||
sw x14, 0x34(sp)
|
||||
sw x15, 0x38(sp)
|
||||
sw x16, 0x3C(sp)
|
||||
sw x17, 0x40(sp)
|
||||
sw x18, 0x44(sp)
|
||||
sw x19, 0x48(sp)
|
||||
sw x20, 0x4C(sp)
|
||||
sw x21, 0x50(sp)
|
||||
sw x22, 0x54(sp)
|
||||
sw x23, 0x58(sp)
|
||||
sw x24, 0x5C(sp)
|
||||
sw x25, 0x60(sp)
|
||||
sw x26, 0x64(sp)
|
||||
sw x27, 0x68(sp)
|
||||
sw x28, 0x6C(sp)
|
||||
sw x29, 0x70(sp)
|
||||
sw x30, 0x74(sp)
|
||||
sw x31, 0x78(sp)
|
||||
|
||||
# figure out what caused the trap.
|
||||
csrrw t0, mcause, x0
|
||||
# mcause is {int, 31 bit exception code}
|
||||
# for this implementation only the lowest 4 bits are used
|
||||
srli t1, t0, 31 # interrupt flag
|
||||
andi t2, t0, 0xF # 4 bit cause
|
||||
|
||||
slli t1, t1, 5 # shift int flag
|
||||
or t1, t1, t2 # combine
|
||||
slli t1, t1, 2 # multiply by 4
|
||||
la t3, exception_table
|
||||
add t4, t3, t1
|
||||
lw t5, 0(t4)
|
||||
jr t5, 0 # jump to specific ISR
|
||||
# specific ISR is expected to set epc
|
||||
|
||||
restore_st:
|
||||
# restore register from stack on exit.
|
||||
|
||||
lw x1, 0x0(sp)
|
||||
lw x2, 0x4(sp)
|
||||
lw x3, 0x8(sp)
|
||||
lw x4, 0xC(sp)
|
||||
lw x5, 0x10(sp)
|
||||
lw x6, 0x14(sp)
|
||||
lw x7, 0x18(sp)
|
||||
lw x8, 0x1C(sp)
|
||||
lw x9, 0x20(sp)
|
||||
lw x10, 0x24(sp)
|
||||
lw x11, 0x28(sp)
|
||||
lw x12, 0x2C(sp)
|
||||
lw x13, 0x30(sp)
|
||||
lw x14, 0x34(sp)
|
||||
lw x15, 0x38(sp)
|
||||
lw x16, 0x3C(sp)
|
||||
lw x17, 0x40(sp)
|
||||
lw x18, 0x44(sp)
|
||||
lw x19, 0x48(sp)
|
||||
lw x20, 0x4C(sp)
|
||||
lw x21, 0x50(sp)
|
||||
lw x22, 0x54(sp)
|
||||
lw x23, 0x58(sp)
|
||||
lw x24, 0x5C(sp)
|
||||
lw x25, 0x60(sp)
|
||||
lw x26, 0x64(sp)
|
||||
lw x27, 0x68(sp)
|
||||
lw x28, 0x6C(sp)
|
||||
lw x29, 0x70(sp)
|
||||
lw x30, 0x74(sp)
|
||||
lw x31, 0x78(sp)
|
||||
|
||||
addi sp, sp, 124
|
||||
|
||||
mret
|
||||
|
||||
.section .text
|
||||
.type trap_instr_addr_misalign, @function
|
||||
trap_instr_addr_misalign:
|
||||
# fatal error, report error and halt
|
||||
addi sp, sp, 4
|
||||
sw ra, 0(sp)
|
||||
jal fail
|
||||
lw ra, 0(sp)
|
||||
la t0, restore_st
|
||||
jr t0, 0
|
||||
|
||||
.section .text
|
||||
.type trap_m_ecall, @function
|
||||
trap_m_ecall:
|
||||
addi sp, sp, -4
|
||||
sw ra, 0(sp)
|
||||
# select which system call based on a7.
|
||||
# for this example we will just define the following.
|
||||
# not standard with linux or anything.
|
||||
# 0: execute a call back function
|
||||
# 1: decrease privilege by 1 (m=>s, s=>u, u=>u)
|
||||
# 2: increase privilege by 1 (m=>m, s=>m, u=>s)
|
||||
|
||||
# check a7
|
||||
li t0, 1
|
||||
beq a7, t0, trap_m_decrease_privilege
|
||||
li t0, 2
|
||||
beq a7, t0, trap_m_increase_privilege
|
||||
|
||||
# call call back function if not zero
|
||||
la t1, isr_m_ecall_cb_fp
|
||||
lw t0, 0(t1)
|
||||
beq t0, x0, trap_m_ecall_skip_cb
|
||||
jalr ra, t0, 0
|
||||
trap_m_ecall_skip_cb:
|
||||
# modify the mepc
|
||||
csrrw t0, mepc, x0
|
||||
addi t0, t0, 4
|
||||
csrrw x0, mepc, t0
|
||||
lw ra, 0(sp)
|
||||
addi sp, sp, 4
|
||||
la t0, restore_st
|
||||
jr t0, 0
|
||||
|
||||
trap_m_decrease_privilege:
|
||||
# read the mstatus register
|
||||
csrrw t0, mstatus, x0
|
||||
# 11 => 01, and 01 => 00.
|
||||
# this is accomplished by clearing bit 12 and taking the old
|
||||
# bit 12 as the new bit 11.
|
||||
li t3, 0x00001800
|
||||
and t1, t0, t3 # isolates the bits 12 and 11.
|
||||
# shift right by 1.
|
||||
srli t2, t1, 1
|
||||
and t2, t2, t3 # this will clear bit 10.
|
||||
li t3, ~0x00001800
|
||||
and t4, t0, t3
|
||||
or t0, t2, t4
|
||||
csrrw x0, mstatus, t0
|
||||
j trap_m_ecall_skip_cb
|
||||
|
||||
trap_m_increase_privilege:
|
||||
# read the mstatus register
|
||||
csrrw t0, mstatus, x0
|
||||
# 11 => 01, and 01 => 00.
|
||||
# this is accomplished by setting bit 11 and taking the old
|
||||
# bit 11 as the new bit 12.
|
||||
li t3, 0x00000800
|
||||
li t4, ~0x00000800
|
||||
and t1, t0, t3
|
||||
slli t2, t1, 1 # shift left by 1.
|
||||
or t2, t2, t3 # bit 11 is always set.
|
||||
and t1, t0, t5
|
||||
or t0, t1, t2
|
||||
csrrw x0, mstatus, t0
|
||||
j trap_m_ecall_skip_cb
|
||||
|
||||
.data
|
||||
exception_table:
|
||||
.int trap_instr_addr_misalign
|
||||
.int trap_instr_addr_misalign #trap_instr_access_fault
|
||||
.int trap_instr_addr_misalign #trap_illegal_instr
|
||||
.int trap_instr_addr_misalign #trap_breakpoint
|
||||
.int trap_instr_addr_misalign #trap_load_addr_misalign
|
||||
.int trap_instr_addr_misalign #trap_load_access_fault
|
||||
.int trap_instr_addr_misalign #trap_store_addr_misalign
|
||||
.int trap_instr_addr_misalign #trap_store_access_fault
|
||||
.int trap_m_ecall
|
||||
.int trap_m_ecall
|
||||
.int restore_st
|
||||
.int trap_m_ecall
|
||||
.int trap_instr_addr_misalign #trap_instr_page_fault
|
||||
.int trap_instr_addr_misalign #trap_load_page_fault
|
||||
.int restore_st
|
||||
.int trap_instr_addr_misalign #trap_store_page_fault
|
||||
#.data
|
||||
#interrupt_table:
|
||||
.int trap_instr_addr_misalign #trap_u_software
|
||||
.int trap_instr_addr_misalign #trap_s_software
|
||||
.int restore_st
|
||||
.int trap_instr_addr_misalign #trap_m_software
|
||||
.int trap_instr_addr_misalign #trap_u_timer
|
||||
.int trap_instr_addr_misalign #trap_s_timer
|
||||
.int restore_st
|
||||
.int trap_instr_addr_misalign #trap_m_timer
|
||||
.int trap_instr_addr_misalign #trap_u_external
|
||||
.int trap_instr_addr_misalign #trap_s_external
|
||||
.int restore_st
|
||||
.int trap_instr_addr_misalign #trap_m_external
|
||||
.int restore_st
|
||||
.int restore_st
|
||||
.int restore_st
|
||||
.int restore_st
|
||||
|
||||
|
||||
.section .data
|
||||
.global isr_m_ecall_cb_fp
|
||||
isr_m_ecall_cb_fp:
|
||||
.int 0
|
60
testsBP/crt0/start.s
Normal file
60
testsBP/crt0/start.s
Normal file
@ -0,0 +1,60 @@
|
||||
.section .init
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
# Initialize global pointer
|
||||
.option push
|
||||
.option norelax
|
||||
1:auipc gp, %pcrel_hi(__global_pointer$)
|
||||
addi gp, gp, %pcrel_lo(1b)
|
||||
.option pop
|
||||
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10, 0
|
||||
li x11, 0
|
||||
li x12, 0
|
||||
li x13, 0
|
||||
li x14, 0
|
||||
li x15, 0
|
||||
li x16, 0
|
||||
li x17, 0
|
||||
li x18, 0
|
||||
li x19, 0
|
||||
li x20, 0
|
||||
li x21, 0
|
||||
li x22, 0
|
||||
li x23, 0
|
||||
li x24, 0
|
||||
li x25, 0
|
||||
li x26, 0
|
||||
li x27, 0
|
||||
li x28, 0
|
||||
li x29, 0
|
||||
li x30, 0
|
||||
li x31, 0
|
||||
|
||||
|
||||
|
||||
# set the stack pointer to the top of memory
|
||||
# 0x8000_0000 + 64K - 8 bytes
|
||||
li sp, 0x007FFFF8
|
||||
|
||||
jal ra, main
|
||||
jal ra, _halt
|
||||
|
||||
.section .text
|
||||
.global _halt
|
||||
.type _halt, @function
|
||||
_halt:
|
||||
li gp, 1
|
||||
li a0, 0
|
||||
ecall
|
||||
j _halt
|
244
testsBP/linker.x
Normal file
244
testsBP/linker.x
Normal file
@ -0,0 +1,244 @@
|
||||
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv",
|
||||
"elf64-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("/opt/riscv/riscv64-unknown-elf/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
/* init segment to ensure we get a consistent start routine*/
|
||||
. = 0x0000000000000000;
|
||||
. = ALIGN(0x0);
|
||||
.init : {
|
||||
*(.init)
|
||||
}
|
||||
_start_end = .;
|
||||
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", _start_end);
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.dyn :
|
||||
{
|
||||
*(.rela.init)
|
||||
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||
*(.rela.fini)
|
||||
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||
*(.rela.ctors)
|
||||
*(.rela.dtors)
|
||||
*(.rela.got)
|
||||
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
|
||||
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
|
||||
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
|
||||
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
|
||||
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
}
|
||||
.rela.plt :
|
||||
{
|
||||
*(.rela.plt)
|
||||
}
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}
|
||||
.plt : { *(.plt) }
|
||||
.iplt : { *(.iplt) }
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf64.em. */
|
||||
*(.gnu.warning)
|
||||
}
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.sdata2 :
|
||||
{
|
||||
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||
}
|
||||
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
. = DATA_SEGMENT_RELRO_END (0, .);
|
||||
.data :
|
||||
{
|
||||
__DATA_BEGIN__ = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
.sdata :
|
||||
{
|
||||
__SDATA_BEGIN__ = .;
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
}
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
.sbss :
|
||||
{
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
. = ALIGN(64 / 8);
|
||||
__BSS_END__ = .;
|
||||
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
|
||||
MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
|
||||
_end = .; PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3 */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
/* DWARF Extension. */
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
}
|
93
testsBP/makefile.inc
Normal file
93
testsBP/makefile.inc
Normal file
@ -0,0 +1,93 @@
|
||||
CEXT := c
|
||||
CPPEXT := cpp
|
||||
AEXT := s
|
||||
SEXT := S
|
||||
SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\)
|
||||
OBJEXT := o
|
||||
DEPEXT := d
|
||||
SRCDIR := .
|
||||
BUILDDIR := OBJ
|
||||
LINKER := ${ROOT}/linker.x
|
||||
|
||||
SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort)
|
||||
OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
|
||||
|
||||
#Default Make
|
||||
all: directories $(TARGET).memfile
|
||||
|
||||
#Remake
|
||||
remake: clean all
|
||||
|
||||
#Make the Directories
|
||||
directories:
|
||||
@mkdir -p $(TARGETDIR)
|
||||
@mkdir -p $(BUILDDIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump
|
||||
|
||||
|
||||
#Needed for building additional library projects
|
||||
ifdef LIBRARY_DIRS
|
||||
LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%}
|
||||
INC+=${LIBRARY_DIRS:%=-I%}
|
||||
|
||||
${LIBRARY_DIRS}:
|
||||
make -C $@ -j 1
|
||||
|
||||
.PHONY: $(LIBRARY_DIRS) $(TARGET)
|
||||
endif
|
||||
|
||||
|
||||
#Pull in dependency info for *existing* .o files
|
||||
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
||||
|
||||
#Link
|
||||
$(TARGET): $(OBJECTS) $(LIBRARY_DIRS)
|
||||
$(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER}
|
||||
|
||||
|
||||
#Compile
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
||||
# gcc won't output dependencies for assembly files for some reason
|
||||
# most asm files don't have dependencies so the echo will work for now.
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
|
||||
# C++
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
||||
# convert to hex
|
||||
$(TARGET).memfile: $(TARGET)
|
||||
@echo 'Making object dump file.'
|
||||
@riscv64-unknown-elf-objdump -D $< > $<.objdump
|
||||
@echo 'Making memory file'
|
||||
exe2memfile0.pl $<
|
||||
extractFunctionRadix.sh $<.objdump
|
||||
cp $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/
|
3
testsBP/mibench_qsort/LICENSE
Normal file
3
testsBP/mibench_qsort/LICENSE
Normal file
@ -0,0 +1,3 @@
|
||||
Matt wrote this using STL.
|
||||
|
||||
It is GPL'ed.
|
19
testsBP/mibench_qsort/Makefile
Normal file
19
testsBP/mibench_qsort/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
TARGETDIR := qsort
|
||||
TARGET := $(TARGETDIR)/$(TARGETDIR).elf
|
||||
ROOT := ..
|
||||
LIBRARY_DIRS := ${ROOT}/crt0
|
||||
LIBRARY_FILES := crt0
|
||||
|
||||
MARCH :=-march=rv64ic
|
||||
MABI :=-mabi=lp64
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles -Wl,-Map=$(TARGET).map
|
||||
|
||||
CFLAGS =$(MARCH) $(MABI) -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align
|
||||
|
||||
CC=riscv64-unknown-elf-gcc
|
||||
DA=riscv64-unknown-elf-objdump -d
|
||||
|
||||
|
||||
include $(ROOT)/makefile.inc
|
||||
|
||||
|
10038
testsBP/mibench_qsort/qsort_small.c
Normal file
10038
testsBP/mibench_qsort/qsort_small.c
Normal file
File diff suppressed because it is too large
Load Diff
19
testsBP/sieve/Makefile
Normal file
19
testsBP/sieve/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
TARGETDIR := sieve
|
||||
TARGET := $(TARGETDIR)/$(TARGETDIR).elf
|
||||
ROOT := ..
|
||||
LIBRARY_DIRS := ${ROOT}/crt0
|
||||
LIBRARY_FILES := crt0
|
||||
|
||||
MARCH :=-march=rv64ic
|
||||
MABI :=-mabi=lp64
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles -Wl,-Map=$(TARGET).map
|
||||
|
||||
CFLAGS =$(MARCH) $(MABI) -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align
|
||||
|
||||
CC=riscv64-unknown-elf-gcc
|
||||
DA=riscv64-unknown-elf-objdump -d
|
||||
|
||||
|
||||
include $(ROOT)/makefile.inc
|
||||
|
||||
|
101
testsBP/sieve/sieve.c
Normal file
101
testsBP/sieve/sieve.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Filename:
|
||||
*
|
||||
* sieve.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* The Sieve of Eratosthenes benchmark, from Byte Magazine
|
||||
* early 1980s, when a PC would do well to run this in 10
|
||||
* seconds. This version really does count prime numbers
|
||||
* but omits the numbers 1, 3 and all even numbers. The
|
||||
* expected count is 1899.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SIZE 8190
|
||||
|
||||
//#define SIZE 8388608
|
||||
double time_diff(struct timeval x , struct timeval y);
|
||||
|
||||
int sieve () {
|
||||
|
||||
unsigned char flags [SIZE + 1];
|
||||
int iter;
|
||||
int count;
|
||||
|
||||
for (iter = 1; iter <= 10; iter++)
|
||||
{
|
||||
int i, prime, k;
|
||||
|
||||
count = 0;
|
||||
|
||||
for (i = 0; i <= SIZE; i++)
|
||||
flags [i] = 1;
|
||||
|
||||
for (i = 0; i <= SIZE; i++)
|
||||
{
|
||||
if (flags [i])
|
||||
{
|
||||
prime = i + i + 3;
|
||||
k = i + prime;
|
||||
|
||||
while (k <= SIZE)
|
||||
{
|
||||
flags [k] = 0;
|
||||
k += prime;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int main () {
|
||||
|
||||
int ans;
|
||||
|
||||
//struct timeval before , after;
|
||||
//gettimeofday(&before , NULL);
|
||||
|
||||
ans = sieve ();
|
||||
//gettimeofday(&after , NULL);
|
||||
if (ans != 1899)
|
||||
printf ("Sieve result wrong, ans = %d, expected 1899", ans);
|
||||
|
||||
//printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) );
|
||||
|
||||
|
||||
printf("Round 2\n");
|
||||
//gettimeofday(&before , NULL);
|
||||
|
||||
ans = sieve ();
|
||||
//gettimeofday(&after , NULL);
|
||||
if (ans != 1899)
|
||||
printf ("Sieve result wrong, ans = %d, expected 1899", ans);
|
||||
|
||||
//printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) );
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
double time_diff(struct timeval x , struct timeval y)
|
||||
{
|
||||
double x_ms , y_ms , diff;
|
||||
|
||||
x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
|
||||
y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
|
||||
|
||||
diff = (double)y_ms - (double)x_ms;
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
18
testsBP/simple/Makefile
Normal file
18
testsBP/simple/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
TARGETDIR := simple
|
||||
TARGET := $(TARGETDIR)/$(TARGETDIR).elf
|
||||
ROOT := ..
|
||||
LIBRARY_DIRS := ${ROOT}/crt0
|
||||
LIBRARY_FILES := crt0
|
||||
|
||||
MARCH :=-march=rv64ic
|
||||
MABI :=-mabi=lp64
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles -Wl,-Map=$(TARGET).map
|
||||
|
||||
CFLAGS =$(MARCH) $(MABI) -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align
|
||||
CC=riscv64-unknown-elf-gcc
|
||||
DA=riscv64-unknown-elf-objdump -d
|
||||
|
||||
|
||||
include $(ROOT)/makefile.inc
|
||||
|
||||
|
11
testsBP/simple/fail.s
Normal file
11
testsBP/simple/fail.s
Normal file
@ -0,0 +1,11 @@
|
||||
# Ross Thompson
|
||||
# March 17, 2021
|
||||
# Oklahoma State University
|
||||
|
||||
.section .text
|
||||
.global fail
|
||||
.type fail, @function
|
||||
fail:
|
||||
li gp, 1
|
||||
li a0, -1
|
||||
ecall
|
8
testsBP/simple/header.h
Normal file
8
testsBP/simple/header.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __header
|
||||
#define __header
|
||||
|
||||
int fail();
|
||||
int simple_csrbr_test();
|
||||
int lbu_test();
|
||||
int icache_spill_test();
|
||||
#endif
|
19
testsBP/simple/lbu_test.s
Normal file
19
testsBP/simple/lbu_test.s
Normal file
@ -0,0 +1,19 @@
|
||||
.section .text
|
||||
.global lbu_test
|
||||
.type lbu_test, @function
|
||||
|
||||
lbu_test:
|
||||
|
||||
li t0, 0x80000
|
||||
lbu t1, 0(t0)
|
||||
|
||||
|
||||
pass:
|
||||
li a0, 0
|
||||
done:
|
||||
ret
|
||||
|
||||
fail:
|
||||
li a0, -1
|
||||
j done
|
||||
|
16
testsBP/simple/main.c
Normal file
16
testsBP/simple/main.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "header.h"
|
||||
|
||||
int main(){
|
||||
int res = icache_spill_test();
|
||||
if (res < 0) {
|
||||
fail();
|
||||
return 0;
|
||||
}else {
|
||||
if((res = lbu_test()) < 0) {
|
||||
fail();
|
||||
return 0;
|
||||
}
|
||||
res = simple_csrbr_test();
|
||||
return 0;
|
||||
}
|
||||
}
|
61
testsBP/simple/sample.s
Normal file
61
testsBP/simple/sample.s
Normal file
@ -0,0 +1,61 @@
|
||||
.section .text
|
||||
.global simple_csrbr_test
|
||||
.type simple_csrbr_test, @function
|
||||
|
||||
simple_csrbr_test:
|
||||
|
||||
# step 1 enable the performance counters
|
||||
# by default the hardware enables all performance counters
|
||||
# however we will eventually want to manually enable incase
|
||||
# some other code disables them
|
||||
|
||||
# br count is counter 5
|
||||
# br mp count is counter 4
|
||||
li t0, 0x30
|
||||
|
||||
csrrc x0, 0x320, t0 # clear bits 4 and 5 of inhibit register.
|
||||
|
||||
# step 2 read performance counters into general purpose registers
|
||||
|
||||
csrrw t2, 0xB05, x0 # t2 = BR COUNT (perf count 5)
|
||||
csrrw t3, 0xB04, x0 # t3 = BRMP COUNT (perf count 4)
|
||||
|
||||
# step 3 simple loop to show the counters are updated.
|
||||
li t0, 0 # this is the loop counter
|
||||
li t1, 100 # this is the loop end condition
|
||||
|
||||
# for(t1 = 0; t1 < t0; t1++);
|
||||
|
||||
loop:
|
||||
addi t0, t0, 1
|
||||
blt t0, t1, loop
|
||||
|
||||
loop_done:
|
||||
|
||||
# step 2 read performance counters into general purpose registers
|
||||
|
||||
csrrw t4, 0xB05, x0 # t4 = BR COUNT (perf count 5)
|
||||
csrrw t5, 0xB04, x0 # t5 = BRMP COUNT (perf count 4)
|
||||
|
||||
sub t2, t4, t2 # this is the number of branch instructions committed.
|
||||
sub t3, t5, t3 # this is the number of branch mispredictions committed.
|
||||
|
||||
# now check if the branch count equals 100 and if the branch
|
||||
bne t4, t2, fail
|
||||
li t5, 3
|
||||
bne t3, t5, fail
|
||||
|
||||
pass:
|
||||
li a0, 0
|
||||
done:
|
||||
li t0, 0x30
|
||||
csrrs x0, 0x320, t0 # set bits 4 and 5
|
||||
ret
|
||||
|
||||
fail:
|
||||
li a0, -1
|
||||
j done
|
||||
|
||||
.data
|
||||
sample_data:
|
||||
.int 0
|
@ -18,7 +18,7 @@ my $maxaddress = 0;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
# *** Ross Thompson I think there is a bug here needs to be +1
|
||||
print ("Processing $#ARGV memfiles: ");
|
||||
print ("Processing $#ARGV memfiles: \n");
|
||||
my $frac = $#ARGV/10;
|
||||
for(my $i=0; $i<=$#ARGV; $i++) {
|
||||
if ($i < 10 || $i % $frac == 0) { print ("$i ") };
|
||||
@ -40,60 +40,113 @@ for(my $i=0; $i<=$#ARGV; $i++) {
|
||||
if ($needsprocessing == 1) {
|
||||
open(FILE, $ofile) || die("Can't read $ofile");
|
||||
my $mode = 0; # parse for code
|
||||
my $section = "";
|
||||
my $data = "";
|
||||
my $address;
|
||||
my $first = 0;
|
||||
my $firstAddress;
|
||||
|
||||
# initialize to all zeros;
|
||||
# *** need to fix the zeroing range. Not always 64K
|
||||
for (my $i=0; $i < 65536*4; $i++) {
|
||||
$memfilebytes[$i] = "00";
|
||||
}
|
||||
|
||||
while(<FILE>) {
|
||||
if ($mode == 0) { # Parse code
|
||||
# print("Examining $_\n");
|
||||
if (/^\s*(\S\S\S\S\S\S\S\S):\s+(\S+)\s+/) {
|
||||
$address = &fixadr($1);
|
||||
my $instr = $2;
|
||||
my $len = length($instr);
|
||||
for (my $i=0; $i<$len/2; $i++) {
|
||||
$memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2);
|
||||
}
|
||||
# print ("address $address $instr\n");
|
||||
}
|
||||
if (/Disassembly of section .data:/) { $mode = 1;}
|
||||
} elsif ($mode == 1) { # Parse data segment
|
||||
if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) {
|
||||
$address = &fixadr($1);
|
||||
# print "addresss $address maxaddress $maxaddress\n";
|
||||
if ($address > $maxaddress) { $maxaddress = $address; }
|
||||
my $line = $2;
|
||||
# merge chunks with spaces
|
||||
$line =~ s/(\S)\s(\S)/$1$2/g;
|
||||
# strip off comments
|
||||
$line =~ /^(\S*)/;
|
||||
$payload = $1;
|
||||
&emitData($address, $payload);
|
||||
}
|
||||
if (/Disassembly of section .riscv.attributes:/) { $mode = 2; }
|
||||
}
|
||||
# objdump fill is divided into several .sections of which only some we want to actually process.
|
||||
# In general we want everything except the .comment and .*attributes
|
||||
if (/Disassembly of section (.*):/) {
|
||||
$section = $1;
|
||||
print ("setting section to $section\n");
|
||||
} else {
|
||||
# now check if the section is one we are interested in processing.
|
||||
#if ($section ne ".comment" && $section ne ".riscv.attributes" && $section =~ /\.debug.*/) {
|
||||
if ($section =~ "\.init|\.text|\..*data|\..*bss") {
|
||||
# the structure is: possible space(s) hex number: possible space(s) hex number space(s) junk
|
||||
# there are also lines we need to skip: possible space(s) hex number <string>:
|
||||
if (/^\s*([0-9A-Fa-f]{1,16}):\s+([0-9A-Fa-f]+).*$/) {
|
||||
$address = &fixadr($1);
|
||||
if ($first == 0) {
|
||||
$first = 1;
|
||||
$firstAddress = $address;
|
||||
}
|
||||
$data = $2;
|
||||
&emitData($address, $data);
|
||||
# my $len = length($data);
|
||||
# for (my $i=0; $i<$len/2; $i++) {
|
||||
# $memfilebytes[$address+$i] = substr($data, $len-2-2*$i, 2);
|
||||
# }
|
||||
# print ("Addr $address $data\n");
|
||||
# } elsif (/^\s*\.\.\./) {
|
||||
# print ("Got ...\n");
|
||||
# } else {
|
||||
# print ("No match\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
# # *** this mode stuff does not work if a section is missing or reordered.
|
||||
# if ($mode == 0) { # Parse code
|
||||
# # print("Examining $_\n");
|
||||
# if (/^\s*(\S{1,16}):\s+(\S+)\s+/) {
|
||||
# $address = &fixadr($1);
|
||||
# my $instr = $2;
|
||||
# my $len = length($instr);
|
||||
# for (my $i=0; $i<$len/2; $i++) {
|
||||
# $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2);
|
||||
# }
|
||||
# print ("address $address $instr\n");
|
||||
# }
|
||||
# if (/Disassembly of section .data:/) { $mode = 1;}
|
||||
# } elsif ($mode == 1) { # Parse data segment
|
||||
# if (/^\s*(\S{1,16}):\s+(.*)/) {
|
||||
# $address = &fixadr($1);
|
||||
# # print "addresss $address maxaddress $maxaddress\n";
|
||||
# if ($address > $maxaddress) { $maxaddress = $address; }
|
||||
# my $line = $2;
|
||||
# # merge chunks with spaces
|
||||
# # *** might need to change
|
||||
# $line =~ s/(\S)\s(\S)/$1$2/g;
|
||||
# # strip off comments
|
||||
# $line =~ /^(\S*)/;
|
||||
# $payload = $1;
|
||||
# &emitData($address, $payload);
|
||||
# }
|
||||
# if (/Disassembly of section .comment:/) { $mode = 2; }
|
||||
# } elsif ($mode == 2) { # parse the comment section
|
||||
# if (/Disassembly of section .riscv.attributes:/) { $mode = 3; }
|
||||
# }
|
||||
}
|
||||
close(FILE);
|
||||
$maxaddress += 32; # pad some zeros at the end
|
||||
$maxaddress = $address + 32; # pad some zeros at the end
|
||||
|
||||
# print to memory file
|
||||
# *** this is a problem
|
||||
if ($fname =~ /rv32/) {
|
||||
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
|
||||
for (my $i=0; $i<= $maxaddress; $i = $i + 4) {
|
||||
for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 4) {
|
||||
for ($j=3; $j>=0; $j--) {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
no warnings 'uninitialized';
|
||||
my $value = $memfilebytes[$i+$j];
|
||||
if ($value eq ""){
|
||||
print MEMFILE "00";
|
||||
} else {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
}
|
||||
}
|
||||
print MEMFILE "\n";
|
||||
}
|
||||
close(MEMFILE);
|
||||
} else {
|
||||
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
|
||||
for (my $i=0; $i<= $maxaddress; $i = $i + 8) {
|
||||
for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 8) {
|
||||
for ($j=7; $j>=0; $j--) {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
no warnings 'uninitialized';
|
||||
my $value = $memfilebytes[$i+$j];
|
||||
if ($value eq ""){
|
||||
print MEMFILE "00";
|
||||
} else {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
}
|
||||
}
|
||||
print MEMFILE "\n";
|
||||
}
|
||||
@ -133,7 +186,15 @@ sub emitData {
|
||||
|
||||
sub fixadr {
|
||||
# strip off leading 8 from address and convert to decimal
|
||||
# if the leading 8 is not present don't remove.
|
||||
my $adr = shift;
|
||||
#print "addr $adr\n";
|
||||
|
||||
# start at 0
|
||||
#return hex($adr);
|
||||
|
||||
# start at 8
|
||||
if ($adr =~ s/^8/0/) { return hex($adr); }
|
||||
else { die("address $adr lacks leading 8\n"); }
|
||||
else { return hex($adr) }
|
||||
|
||||
}
|
||||
|
200
wally-pipelined/bin/exe2memfile0.pl
Executable file
200
wally-pipelined/bin/exe2memfile0.pl
Executable file
@ -0,0 +1,200 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# exe2memfile.pl
|
||||
# David_Harris@hmc.edu 26 November 2020
|
||||
# Converts an executable file to a series of 32-bit hex instructions
|
||||
# to read into a Verilog simulation with $readmemh
|
||||
|
||||
use File::stat;
|
||||
use IO::Handle;
|
||||
|
||||
if ($#ARGV == -1) {
|
||||
die("Usage: $0 executable_file");
|
||||
}
|
||||
|
||||
# array to hold contents of memory file
|
||||
my @memfilebytes = (0)*16384*4;
|
||||
my $maxaddress = 0;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
# *** Ross Thompson I think there is a bug here needs to be +1
|
||||
print ("Processing $#ARGV memfiles: \n");
|
||||
my $frac = $#ARGV/10;
|
||||
for(my $i=0; $i<=$#ARGV; $i++) {
|
||||
if ($i < 10 || $i % $frac == 0) { print ("$i ") };
|
||||
my $fname = $ARGV[$i];
|
||||
# print "fname = $fname";
|
||||
my $ofile = $fname.".objdump";
|
||||
my $memfile = $fname.".memfile";
|
||||
|
||||
my $needsprocessing = 0;
|
||||
if (!-e $memfile) { $needsprocessing = 1; } # create memfile if it doesn't exist
|
||||
else {
|
||||
my $osb = stat($ofile) || die("Can't stat $ofile");
|
||||
my $msb = stat($memfile) || die("Can't stat $memfile");
|
||||
my $otime = $osb->mtime;
|
||||
my $mtime = $msb->mtime;
|
||||
if ($otime > $mtime) { $needsprocessing = 1; } # is memfile out of date?
|
||||
}
|
||||
|
||||
if ($needsprocessing == 1) {
|
||||
open(FILE, $ofile) || die("Can't read $ofile");
|
||||
my $mode = 0; # parse for code
|
||||
my $section = "";
|
||||
my $data = "";
|
||||
my $address;
|
||||
my $first = 0;
|
||||
my $firstAddress;
|
||||
|
||||
# initialize to all zeros;
|
||||
# *** need to fix the zeroing range. Not always 64K
|
||||
for (my $i=0; $i < 65536*4; $i++) {
|
||||
$memfilebytes[$i] = "00";
|
||||
}
|
||||
|
||||
while(<FILE>) {
|
||||
# objdump fill is divided into several .sections of which only some we want to actually process.
|
||||
# In general we want everything except the .comment and .*attributes
|
||||
if (/Disassembly of section (.*):/) {
|
||||
$section = $1;
|
||||
print ("setting section to $section\n");
|
||||
} else {
|
||||
# now check if the section is one we are interested in processing.
|
||||
#if ($section ne ".comment" && $section ne ".riscv.attributes" && $section =~ /\.debug.*/) {
|
||||
if ($section =~ "\.init|\.text|\..*data|\..*bss") {
|
||||
# the structure is: possible space(s) hex number: possible space(s) hex number space(s) junk
|
||||
# there are also lines we need to skip: possible space(s) hex number <string>:
|
||||
if (/^\s*([0-9A-Fa-f]{1,16}):\s+([0-9A-Fa-f]+).*$/) {
|
||||
$address = &fixadr($1);
|
||||
if ($first == 0) {
|
||||
$first = 1;
|
||||
$firstAddress = $address;
|
||||
}
|
||||
$data = $2;
|
||||
&emitData($address, $data);
|
||||
# my $len = length($data);
|
||||
# for (my $i=0; $i<$len/2; $i++) {
|
||||
# $memfilebytes[$address+$i] = substr($data, $len-2-2*$i, 2);
|
||||
# }
|
||||
# print ("Addr $address $data\n");
|
||||
# } elsif (/^\s*\.\.\./) {
|
||||
# print ("Got ...\n");
|
||||
# } else {
|
||||
# print ("No match\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
# # *** this mode stuff does not work if a section is missing or reordered.
|
||||
# if ($mode == 0) { # Parse code
|
||||
# # print("Examining $_\n");
|
||||
# if (/^\s*(\S{1,16}):\s+(\S+)\s+/) {
|
||||
# $address = &fixadr($1);
|
||||
# my $instr = $2;
|
||||
# my $len = length($instr);
|
||||
# for (my $i=0; $i<$len/2; $i++) {
|
||||
# $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2);
|
||||
# }
|
||||
# print ("address $address $instr\n");
|
||||
# }
|
||||
# if (/Disassembly of section .data:/) { $mode = 1;}
|
||||
# } elsif ($mode == 1) { # Parse data segment
|
||||
# if (/^\s*(\S{1,16}):\s+(.*)/) {
|
||||
# $address = &fixadr($1);
|
||||
# # print "addresss $address maxaddress $maxaddress\n";
|
||||
# if ($address > $maxaddress) { $maxaddress = $address; }
|
||||
# my $line = $2;
|
||||
# # merge chunks with spaces
|
||||
# # *** might need to change
|
||||
# $line =~ s/(\S)\s(\S)/$1$2/g;
|
||||
# # strip off comments
|
||||
# $line =~ /^(\S*)/;
|
||||
# $payload = $1;
|
||||
# &emitData($address, $payload);
|
||||
# }
|
||||
# if (/Disassembly of section .comment:/) { $mode = 2; }
|
||||
# } elsif ($mode == 2) { # parse the comment section
|
||||
# if (/Disassembly of section .riscv.attributes:/) { $mode = 3; }
|
||||
# }
|
||||
}
|
||||
close(FILE);
|
||||
$maxaddress = $address + 32; # pad some zeros at the end
|
||||
|
||||
# print to memory file
|
||||
# *** this is a problem
|
||||
if ($fname =~ /rv32/) {
|
||||
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
|
||||
for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 4) {
|
||||
for ($j=3; $j>=0; $j--) {
|
||||
no warnings 'uninitialized';
|
||||
my $value = $memfilebytes[$i+$j];
|
||||
if ($value eq ""){
|
||||
print MEMFILE "00";
|
||||
} else {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
}
|
||||
}
|
||||
print MEMFILE "\n";
|
||||
}
|
||||
close(MEMFILE);
|
||||
} else {
|
||||
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
|
||||
for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 8) {
|
||||
for ($j=7; $j>=0; $j--) {
|
||||
no warnings 'uninitialized';
|
||||
my $value = $memfilebytes[$i+$j];
|
||||
if ($value eq ""){
|
||||
print MEMFILE "00";
|
||||
} else {
|
||||
print MEMFILE "$memfilebytes[$i+$j]";
|
||||
}
|
||||
}
|
||||
print MEMFILE "\n";
|
||||
}
|
||||
close(MEMFILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
print("\n");
|
||||
|
||||
sub emitData {
|
||||
# print the data portion of the ELF into a memroy file, including 0s for empty stuff
|
||||
# deal with endianness
|
||||
my $address = shift;
|
||||
my $payload = shift;
|
||||
|
||||
# print("Emitting data. address = $address payload = $payload\n");
|
||||
|
||||
my $len = length($payload);
|
||||
if ($len <= 8) {
|
||||
# print word or halfword
|
||||
for(my $i=0; $i<$len/2; $i++) {
|
||||
my $adr = $address+$i;
|
||||
my $b = substr($payload, $len-2-2*$i, 2);
|
||||
$memfilebytes[$adr] = $b;
|
||||
# print(" $adr $b\n");
|
||||
}
|
||||
} elsif ($len == 12) {
|
||||
# weird case of three halfwords on line
|
||||
&emitData($address, substr($payload, 0, 4));
|
||||
&emitData($address+2, substr($payload, 4, 4));
|
||||
&emitData($address+4, substr($payload, 8, 4));
|
||||
} else {
|
||||
&emitData($address, substr($payload, 0, 8));
|
||||
&emitData($address+4, substr($payload, 8, $len-8));
|
||||
}
|
||||
}
|
||||
|
||||
sub fixadr {
|
||||
# strip off leading 8 from address and convert to decimal
|
||||
# if the leading 8 is not present don't remove.
|
||||
my $adr = shift;
|
||||
#print "addr $adr\n";
|
||||
|
||||
# start at 0
|
||||
return hex($adr);
|
||||
|
||||
# start at 8
|
||||
#if ($adr =~ s/^8/0/) { return hex($adr); }
|
||||
#else { return hex($adr) }
|
||||
|
||||
}
|
@ -106,3 +106,4 @@
|
||||
`define TWO_BIT_PRELOAD "../config/busybear/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/busybear/BTBPredictor.txt"
|
||||
`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE
|
||||
`define TESTSBP 0
|
||||
|
@ -108,3 +108,4 @@
|
||||
`define TWO_BIT_PRELOAD "../config/coremark/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/coremark/BTBPredictor.txt"
|
||||
`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE
|
||||
`define TESTSBP 0
|
||||
|
@ -105,3 +105,4 @@
|
||||
`define TWO_BIT_PRELOAD "../config/coremark_bare/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/coremark_bare/BTBPredictor.txt"
|
||||
`define BPTYPE "BPGSHARE"
|
||||
`define TESTSBP 0
|
||||
|
1024
wally-pipelined/config/rv64BP/BTBPredictor.txt
Normal file
1024
wally-pipelined/config/rv64BP/BTBPredictor.txt
Normal file
File diff suppressed because it is too large
Load Diff
1024
wally-pipelined/config/rv64BP/twoBitPredictor.txt
Normal file
1024
wally-pipelined/config/rv64BP/twoBitPredictor.txt
Normal file
File diff suppressed because it is too large
Load Diff
101
wally-pipelined/config/rv64BP/wally-config.vh
Normal file
101
wally-pipelined/config/rv64BP/wally-config.vh
Normal file
@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////
|
||||
// wally-config.vh
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 4 January 2021
|
||||
// Modified: Brett Mathis
|
||||
//
|
||||
// Purpose: Specify which features are configured
|
||||
// Macros to determine which modes are supported based on MISA
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
// RV32 or RV64: XLEN = 32 or 64
|
||||
`define XLEN 64
|
||||
|
||||
//`define MISA (32'h00000104)
|
||||
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20)
|
||||
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
|
||||
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
|
||||
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
|
||||
`define F_SUPPORTED ((`MISA >> 5) % 2 == 1)
|
||||
`define M_SUPPORTED ((`MISA >> 12) % 2 == 1)
|
||||
`define S_SUPPORTED ((`MISA >> 18) % 2 == 1)
|
||||
`define U_SUPPORTED ((`MISA >> 20) % 2 == 1)
|
||||
`define ZCSR_SUPPORTED 1
|
||||
`define COUNTERS 31
|
||||
`define ZCOUNTERS_SUPPORTED 1
|
||||
// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21
|
||||
//`define N_SUPPORTED ((MISA >> 13) % 2 == 1)
|
||||
`define N_SUPPORTED 0
|
||||
|
||||
`define M_MODE (2'b11)
|
||||
`define S_MODE (2'b01)
|
||||
`define U_MODE (2'b00)
|
||||
|
||||
// Microarchitectural Features
|
||||
`define UARCH_PIPELINED 1
|
||||
`define UARCH_SUPERSCALR 0
|
||||
`define UARCH_SINGLECYCLE 0
|
||||
`define MEM_DCACHE 0
|
||||
`define MEM_DTIM 1
|
||||
`define MEM_ICACHE 0
|
||||
`define MEM_VIRTMEM 0
|
||||
|
||||
// Address space
|
||||
`define RESET_VECTOR 64'h0000000000000000
|
||||
|
||||
// Bus Interface width
|
||||
`define AHBW 64
|
||||
|
||||
// Peripheral Addresses
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00800000
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h00000000
|
||||
`define TIMRANGE 32'h007FFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
`define GPIO_LOOPBACK_TEST 0
|
||||
|
||||
// Busybear special CSR config to match OVPSim
|
||||
`define OVPSIM_CSR_CONFIG 0
|
||||
|
||||
// Hardware configuration
|
||||
`define UART_PRESCALE 1
|
||||
|
||||
/* verilator lint_off STMTDLY */
|
||||
/* verilator lint_off WIDTH */
|
||||
/* verilator lint_off ASSIGNDLY */
|
||||
/* verilator lint_off PINCONNECTEMPTY */
|
||||
|
||||
`define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt"
|
||||
`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE
|
||||
`define TESTSBP 1
|
31
wally-pipelined/config/rv64BP/wally-constants.vh
Normal file
31
wally-pipelined/config/rv64BP/wally-constants.vh
Normal file
@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////
|
||||
// wally-constants.vh
|
||||
//
|
||||
// Written: tfleming@hmc.edu 4 March 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture.
|
||||
// These macros should not be changed, except in the event of an
|
||||
// update to the architecture or particularly special circumstances.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PA_BITS 56
|
@ -5,7 +5,7 @@ add wave -noupdate /testbench/clk
|
||||
add wave -noupdate /testbench/reset
|
||||
add wave -noupdate /testbench/test
|
||||
add wave -noupdate -radix ascii /testbench/memfilename
|
||||
add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/function_radix/FunctionName
|
||||
add wave -noupdate -expand -group {Execution Stage} /testbench/FunctionName/FunctionName/FunctionName
|
||||
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE
|
||||
add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName
|
||||
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
|
||||
|
@ -115,9 +115,6 @@ module datapath (
|
||||
flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
|
||||
flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW);
|
||||
|
||||
// *** something is not right here. Before the merge I found an issue with the jal instruction not writing
|
||||
// the link address through the alu.
|
||||
// not sure what changed.
|
||||
// handle Store Conditional result if atomic extension supported
|
||||
generate
|
||||
if (`A_SUPPORTED)
|
||||
|
@ -33,20 +33,24 @@ module BTBPredictor
|
||||
)
|
||||
(input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF, StallD, StallE, FlushF, FlushD, FlushE,
|
||||
input logic [`XLEN-1:0] LookUpPC,
|
||||
output logic [`XLEN-1:0] TargetPC,
|
||||
output logic [3:0] InstrClass,
|
||||
output logic [4:0] InstrClass,
|
||||
output logic Valid,
|
||||
// update
|
||||
input logic UpdateEN,
|
||||
input logic [`XLEN-1:0] UpdatePC,
|
||||
input logic [`XLEN-1:0] UpdateTarget,
|
||||
input logic [3:0] UpdateInstrClass
|
||||
input logic [4:0] UpdateInstrClass,
|
||||
input logic UpdateInvalid
|
||||
);
|
||||
|
||||
localparam TotalDepth = 2 ** Depth;
|
||||
logic [TotalDepth-1:0] ValidBits;
|
||||
logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex, LookUpPCIndexQ, UpdatePCIndexQ;
|
||||
logic UpdateENQ;
|
||||
|
||||
|
||||
// hashing function for indexing the PC
|
||||
// We have Depth bits to index, but XLEN bits as the input.
|
||||
@ -58,7 +62,7 @@ module BTBPredictor
|
||||
|
||||
flopenr #(Depth) UpdatePCIndexReg(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(1'b1),
|
||||
.en(~StallE),
|
||||
.d(UpdatePCIndex),
|
||||
.q(UpdatePCIndexQ));
|
||||
|
||||
@ -66,32 +70,53 @@ module BTBPredictor
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset) begin
|
||||
ValidBits <= #1 {TotalDepth{1'b0}};
|
||||
end else if (UpdateEN) begin
|
||||
ValidBits[UpdatePCIndexQ] <= #1 1'b1;
|
||||
end else
|
||||
if (UpdateENQ) begin
|
||||
ValidBits[UpdatePCIndexQ] <= #1 ~ UpdateInvalid;
|
||||
end
|
||||
end
|
||||
assign Valid = ValidBits[LookUpPCIndexQ];
|
||||
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
|
||||
regfile2p1r1w #(10, 1) validMem(.clk(clk),
|
||||
.reset(reset),
|
||||
.RA1(LookUpPCIndexQ),
|
||||
.RD1(Valid),
|
||||
.REN1(1'b1),
|
||||
.WA1(UpdatePCIndexQ),
|
||||
.WD1(1'b1),
|
||||
.WEN1(UpdateEN));
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
flopenr #(1) UpdateENReg(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallF),
|
||||
.d(UpdateEN),
|
||||
.q(UpdateENQ));
|
||||
|
||||
|
||||
flopenr #(Depth) LookupPCIndexReg(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(1'b1),
|
||||
.en(~StallF),
|
||||
.d(LookUpPCIndex),
|
||||
.q(LookUpPCIndexQ));
|
||||
|
||||
assign Valid = ValidBits[LookUpPCIndexQ];
|
||||
|
||||
|
||||
// the BTB contains the target address.
|
||||
// Another optimization may be using a PC relative address.
|
||||
// *** need to add forwarding.
|
||||
|
||||
SRAM2P1R1W #(Depth, `XLEN+4) memory(.clk(clk),
|
||||
SRAM2P1R1W #(Depth, `XLEN+5) memory(.clk(clk),
|
||||
.reset(reset),
|
||||
.RA1(LookUpPCIndex),
|
||||
.RD1({{InstrClass, TargetPC}}),
|
||||
.REN1(1'b1),
|
||||
.REN1(~StallF),
|
||||
.WA1(UpdatePCIndex),
|
||||
.WD1({UpdateInstrClass, UpdateTarget}),
|
||||
.WEN1(UpdateEN),
|
||||
.BitWEN1({4'b0000, {`XLEN{1'b1}}})); // *** definitely not right.
|
||||
.BitWEN1({5'h1F, {`XLEN{1'b1}}})); // *** definitely not right.
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -42,7 +42,7 @@ module RASPredictor
|
||||
logic CounterEn;
|
||||
localparam Depth = $clog2(StackSize);
|
||||
|
||||
logic [StackSize-1:0] PtrD, PtrQ, PtrP1, PtrM1;
|
||||
logic [Depth-1:0] PtrD, PtrQ, PtrP1, PtrM1;
|
||||
logic [StackSize-1:0] [`XLEN-1:0] memory;
|
||||
integer index;
|
||||
|
||||
@ -55,7 +55,7 @@ module RASPredictor
|
||||
// may have to handle a push and an incr at the same time.
|
||||
// *** what happens if jal is executing and there is a return being flushed in Decode?
|
||||
|
||||
flopenr #(StackSize) PTR(.clk(clk),
|
||||
flopenr #(Depth) PTR(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(CounterEn),
|
||||
.d(PtrD),
|
||||
|
@ -47,20 +47,25 @@ module bpred
|
||||
input logic [`XLEN-1:0] PCTargetE, // The branch destination if the branch is taken.
|
||||
input logic [`XLEN-1:0] PCD, // The address the branch predictor took.
|
||||
input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
input logic [3:0] InstrClassE,
|
||||
input logic [4:0] InstrClassE,
|
||||
// Report branch prediction status
|
||||
output logic BPPredWrongE
|
||||
output logic BPPredWrongE,
|
||||
output logic BPPredDirWrongE,
|
||||
output logic BTBPredPCWrongE,
|
||||
output logic RASPredPCWrongE,
|
||||
output logic BPPredClassNonCFIWrongE
|
||||
);
|
||||
|
||||
logic BTBValidF;
|
||||
logic [1:0] BPPredF, BPPredD, BPPredE, UpdateBPPredE;
|
||||
|
||||
logic [3:0] BPInstrClassF, BPInstrClassD, BPInstrClassE;
|
||||
logic [4:0] BPInstrClassF, BPInstrClassD, BPInstrClassE;
|
||||
logic [`XLEN-1:0] BTBPredPCF, RASPCF;
|
||||
logic TargetWrongE;
|
||||
logic FallThroughWrongE;
|
||||
logic PredictionDirWrongE;
|
||||
logic PredictionPCWrongE;
|
||||
logic PredictionInstrClassWrongE;
|
||||
|
||||
logic [`XLEN-1:0] CorrectPCE;
|
||||
|
||||
|
||||
@ -74,7 +79,7 @@ module bpred
|
||||
.Prediction(BPPredF),
|
||||
// update
|
||||
.UpdatePC(PCE),
|
||||
.UpdateEN(InstrClassE[0]),
|
||||
.UpdateEN(InstrClassE[0] & ~StallE),
|
||||
.UpdatePrediction(UpdateBPPredE));
|
||||
|
||||
end else if (`BPTYPE == "BPGLOBAL") begin:Predictor
|
||||
@ -86,7 +91,7 @@ module bpred
|
||||
.Prediction(BPPredF),
|
||||
// update
|
||||
.UpdatePC(PCE),
|
||||
.UpdateEN(InstrClassE[0]),
|
||||
.UpdateEN(InstrClassE[0] & ~StallE),
|
||||
.PCSrcE(PCSrcE),
|
||||
.UpdatePrediction(UpdateBPPredE));
|
||||
end else if (`BPTYPE == "BPGSHARE") begin:Predictor
|
||||
@ -98,7 +103,20 @@ module bpred
|
||||
.Prediction(BPPredF),
|
||||
// update
|
||||
.UpdatePC(PCE),
|
||||
.UpdateEN(InstrClassE[0]),
|
||||
.UpdateEN(InstrClassE[0] & ~StallE),
|
||||
.PCSrcE(PCSrcE),
|
||||
.UpdatePrediction(UpdateBPPredE));
|
||||
end
|
||||
else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
|
||||
|
||||
localHistoryPredictor DirPredictor(.clk(clk),
|
||||
.reset(reset),
|
||||
.*, // Stalls and flushes
|
||||
.LookUpPC(PCNextF),
|
||||
.Prediction(BPPredF),
|
||||
// update
|
||||
.UpdatePC(PCE),
|
||||
.UpdateEN(InstrClassE[0] & ~StallE),
|
||||
.PCSrcE(PCSrcE),
|
||||
.UpdatePrediction(UpdateBPPredE));
|
||||
end
|
||||
@ -132,16 +150,19 @@ module bpred
|
||||
// Part 2 Branch target address prediction
|
||||
// *** For now the BTB will house the direct and indirect targets
|
||||
|
||||
// *** getting to many false positivies from the BTB, we need a partial TAG to reduce this.
|
||||
BTBPredictor TargetPredictor(.clk(clk),
|
||||
.reset(reset),
|
||||
.*, // Stalls and flushes
|
||||
.LookUpPC(PCNextF),
|
||||
.TargetPC(BTBPredPCF),
|
||||
.InstrClass(BPInstrClassF),
|
||||
.Valid(BTBValidF),
|
||||
// update
|
||||
.UpdateEN(InstrClassE[2] | InstrClassE[1] | InstrClassE[0]),
|
||||
.UpdateEN((|InstrClassE | (PredictionInstrClassWrongE)) & ~StallE),
|
||||
.UpdatePC(PCE),
|
||||
.UpdateTarget(PCTargetE),
|
||||
.UpdateInvalid(PredictionInstrClassWrongE),
|
||||
.UpdateInstrClass(InstrClassE));
|
||||
|
||||
// need to forward when updating to the same address as reading.
|
||||
@ -152,9 +173,9 @@ module bpred
|
||||
// *** need to add the logic to restore RAS on flushes. We will use incr for this.
|
||||
RASPredictor RASPredictor(.clk(clk),
|
||||
.reset(reset),
|
||||
.pop(BPInstrClassF[3]),
|
||||
.pop(BPInstrClassF[3] & ~StallF),
|
||||
.popPC(RASPCF),
|
||||
.push(InstrClassE[3]),
|
||||
.push(InstrClassE[4] & ~StallE),
|
||||
.incr(1'b0),
|
||||
.pushPC(PCLinkE));
|
||||
|
||||
@ -180,14 +201,14 @@ module bpred
|
||||
.q(BPPredE));
|
||||
|
||||
// pipeline the class
|
||||
flopenrc #(4) InstrClassRegD(.clk(clk),
|
||||
flopenrc #(5) InstrClassRegD(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallD),
|
||||
.clear(FlushD),
|
||||
.d(BPInstrClassF),
|
||||
.q(BPInstrClassD));
|
||||
|
||||
flopenrc #(4) InstrClassRegE(.clk(clk),
|
||||
flopenrc #(5) InstrClassRegE(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallE),
|
||||
.clear(FlushE),
|
||||
@ -197,12 +218,40 @@ module bpred
|
||||
|
||||
|
||||
// Check the prediction makes execution.
|
||||
|
||||
// first check if the target or fallthrough address matches what was predicted.
|
||||
assign TargetWrongE = PCTargetE != PCD;
|
||||
assign FallThroughWrongE = PCLinkE != PCD;
|
||||
assign PredictionDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0];
|
||||
assign PredictionPCWrongE = PCSrcE ? TargetWrongE : FallThroughWrongE;
|
||||
assign BPPredWrongE = (PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE);
|
||||
// If the target is taken check the target rather than fallthrough. The instruction needs to be a branch if PCSrcE is selected
|
||||
// Remember the bpred can incorrectly predict a non cfi instruction as a branch taken. If the real instruction is non cfi
|
||||
// it must have selected teh fall through.
|
||||
assign PredictionPCWrongE = (PCSrcE & (|InstrClassE) ? TargetWrongE : FallThroughWrongE);
|
||||
|
||||
// The branch direction also need to checked.
|
||||
// However if the direction is wrong then the pc will be wrong. This is only relavent to checking the
|
||||
// accuracy of the direciton prediction.
|
||||
assign BPPredDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0];
|
||||
|
||||
// Finally we need to check if the class is wrong. When the class is wrong the BTB needs to be updated.
|
||||
// Also we want to track this in a performance counter.
|
||||
assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE;
|
||||
|
||||
// We want to output to the instruction fetch if the PC fetched was wrong. If by chance the predictor was wrong about
|
||||
// the direction or class, but correct about the target we don't have the flush the pipeline. However we still
|
||||
// need this information to verify the accuracy of the predictors.
|
||||
|
||||
|
||||
//assign BPPredWrongE = ((PredictionPCWrongE | BPPredDirWrongE) & (|InstrClassE)) | PredictionInstrClassWrongE;
|
||||
|
||||
assign BPPredWrongE = (PredictionPCWrongE & |InstrClassE) | BPPredClassNonCFIWrongE;
|
||||
|
||||
// If we have a jump, jump register or jal or jalr and the PC is wrong we need to increment the performance counter.
|
||||
assign BTBPredPCWrongE = (InstrClassE[4] | InstrClassE[2] | InstrClassE[1]) & PredictionPCWrongE;
|
||||
// similar with RAS
|
||||
assign RASPredPCWrongE = InstrClassE[3] & PredictionPCWrongE;
|
||||
// Finally if the real instruction class is non CFI but the predictor said it was we need to count.
|
||||
assign BPPredClassNonCFIWrongE = PredictionInstrClassWrongE & ~|InstrClassE;
|
||||
|
||||
// Update predictors
|
||||
|
||||
satCounter2 BPDirUpdate(.BrDir(PCSrcE),
|
||||
|
@ -42,22 +42,24 @@ module gsharePredictor
|
||||
|
||||
);
|
||||
|
||||
logic [k-1:0] GHRF, GHRD, GHRE;
|
||||
logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE;
|
||||
logic [k-1:0] GHRF, GHRD, GHRE, GHRENext;
|
||||
//logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE;
|
||||
logic [k-1:0] LookUpPCIndex, UpdatePCIndex;
|
||||
logic [1:0] PredictionMemory;
|
||||
logic DoForwarding, DoForwardingF;
|
||||
logic [1:0] UpdatePredictionF;
|
||||
|
||||
assign GHRENext = {PCSrcE, GHRE[k-1:1]};
|
||||
|
||||
flopenr #(k) GlobalHistoryRegister(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(UpdateEN),
|
||||
.d({PCSrcE, GHRF[k-1:1] }),
|
||||
.d(GHRENext),
|
||||
.q(GHRF));
|
||||
|
||||
|
||||
// for gshare xor the PC with the GHR
|
||||
assign UpdatePCIndex = GHRE ^ UpdatePC[k:1];
|
||||
assign UpdatePCIndex = GHRENext ^ UpdatePC[k:1];
|
||||
assign LookUpPCIndex = GHRF ^ LookUpPC[k:1];
|
||||
// Make Prediction by reading the correct address in the PHT and also update the new address in the PHT
|
||||
// GHR referes to the address that the past k branches points to in the prediction stage
|
||||
@ -66,7 +68,7 @@ module gsharePredictor
|
||||
.reset(reset),
|
||||
.RA1(LookUpPCIndex),
|
||||
.RD1(PredictionMemory),
|
||||
.REN1(1'b1),
|
||||
.REN1(~StallF),
|
||||
.WA1(UpdatePCIndex),
|
||||
.WD1(UpdatePrediction),
|
||||
.WEN1(UpdateEN),
|
||||
@ -92,6 +94,7 @@ module gsharePredictor
|
||||
assign Prediction = DoForwardingF ? UpdatePredictionF : PredictionMemory;
|
||||
|
||||
//pipeline for GHR
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
flopenrc #(k) LookUpDReg(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallD),
|
||||
@ -105,5 +108,21 @@ module gsharePredictor
|
||||
.clear(FlushE),
|
||||
.d(LookUpPCIndexD),
|
||||
.q(LookUpPCIndexE));
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
flopenrc #(k) GHRRegD(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallD),
|
||||
.clear(FlushD),
|
||||
.d(GHRF),
|
||||
.q(GHRD));
|
||||
|
||||
flopenrc #(k) GHRRegE(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallE),
|
||||
.clear(FlushE),
|
||||
.d(GHRD),
|
||||
.q(GHRE));
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -206,8 +206,8 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
|
||||
logic [15:0] SpillDataBlock0;
|
||||
|
||||
|
||||
|
||||
logic FlushDLastCyclen;
|
||||
|
||||
// Happy path signals
|
||||
logic [31:0] AlignedInstrRawD;
|
||||
|
||||
|
@ -27,9 +27,9 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module ifu (
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
|
||||
// Fetch
|
||||
input logic [`XLEN-1:0] InstrInF,
|
||||
input logic InstrAckF,
|
||||
@ -49,8 +49,11 @@ module ifu (
|
||||
input logic [`XLEN-1:0] PrivilegedNextPCM,
|
||||
output logic [31:0] InstrD, InstrM,
|
||||
output logic [`XLEN-1:0] PCM,
|
||||
output logic [3:0] InstrClassM,
|
||||
output logic BPPredWrongM,
|
||||
output logic [4:0] InstrClassM,
|
||||
output logic BPPredDirWrongM,
|
||||
output logic BTBPredPCWrongM,
|
||||
output logic RASPredPCWrongM,
|
||||
output logic BPPredClassNonCFIWrongM,
|
||||
// Writeback
|
||||
// output logic [`XLEN-1:0] PCLinkW,
|
||||
// Faults
|
||||
@ -73,11 +76,14 @@ module ifu (
|
||||
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
|
||||
logic PrivilegedChangePCM;
|
||||
logic IllegalCompInstrD;
|
||||
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCNextPF;
|
||||
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCNextPF, PCPF;
|
||||
logic CompressedF;
|
||||
logic [31:0] InstrRawD, InstrE, InstrW;
|
||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||
logic reset_q; // *** look at this later.
|
||||
logic reset_q; // *** look at this later.
|
||||
|
||||
logic BPPredDirWrongE, BTBPredPCWrongE, RASPredPCWrongE, BPPredClassNonCFIWrongE;
|
||||
|
||||
|
||||
tlb #(.ENTRY_BITS(3), .ITLB(1)) itlb(.TLBAccessType(2'b10), .VirtualAddress(PCF),
|
||||
.PageTableEntryWrite(PageTableEntryF), .PageTypeWrite(PageTypeF),
|
||||
@ -89,7 +95,7 @@ module ifu (
|
||||
// branch predictor signals
|
||||
logic SelBPPredF;
|
||||
logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F, PCNext2F, PCNext3F;
|
||||
logic [3:0] InstrClassD, InstrClassE;
|
||||
logic [4:0] InstrClassD, InstrClassE;
|
||||
|
||||
|
||||
// *** put memory interface on here, InstrF becomes output
|
||||
@ -151,7 +157,7 @@ module ifu (
|
||||
.reset(reset),
|
||||
.StallF(StallF),
|
||||
.StallD(StallD),
|
||||
.StallE(1'b0), // *** may need this eventually
|
||||
.StallE(StallE),
|
||||
.FlushF(FlushF),
|
||||
.FlushD(FlushD),
|
||||
.FlushE(FlushE),
|
||||
@ -164,7 +170,11 @@ module ifu (
|
||||
.PCD(PCD),
|
||||
.PCLinkE(PCLinkE),
|
||||
.InstrClassE(InstrClassE),
|
||||
.BPPredWrongE(BPPredWrongE));
|
||||
.BPPredWrongE(BPPredWrongE),
|
||||
.BPPredDirWrongE(BPPredDirWrongE),
|
||||
.BTBPredPCWrongE(BTBPredPCWrongE),
|
||||
.RASPredPCWrongE(RASPredPCWrongE),
|
||||
.BPPredClassNonCFIWrongE(BPPredClassNonCFIWrongE));
|
||||
// The true correct target is PCTargetE if PCSrcE is 1 else it is the fall through PCLinkE.
|
||||
assign PCCorrectE = PCSrcE ? PCTargetE : PCLinkE;
|
||||
|
||||
@ -189,8 +199,9 @@ module ifu (
|
||||
|
||||
// the branch predictor needs a compact decoding of the instruction class.
|
||||
// *** consider adding in the alternate return address x5 for returns.
|
||||
assign InstrClassD[3] = InstrD[6:0] == 7'h67 && InstrD[19:15] == 5'h01; // return
|
||||
assign InstrClassD[2] = InstrD[6:0] == 7'h67 && InstrD[19:15] != 5'h01; // jump register, but not return
|
||||
assign InstrClassD[4] = (InstrD[6:0] & 7'h77) == 7'h67 && (InstrD[11:07] & 5'h1B) == 5'h01; // jal(r) must link to ra or r5
|
||||
assign InstrClassD[3] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) == 5'h01; // return must link to ra or r5
|
||||
assign InstrClassD[2] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) != 5'h01; // jump register, but not return
|
||||
assign InstrClassD[1] = InstrD[6:0] == 7'h6F; // jump
|
||||
assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch
|
||||
|
||||
@ -217,26 +228,26 @@ module ifu (
|
||||
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||
// flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
|
||||
|
||||
flopenrc #(4) InstrClassRegE(.clk(clk),
|
||||
flopenrc #(5) InstrClassRegE(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallE),
|
||||
.clear(FlushE),
|
||||
.d(InstrClassD),
|
||||
.q(InstrClassE));
|
||||
|
||||
flopenrc #(4) InstrClassRegM(.clk(clk),
|
||||
flopenrc #(5) InstrClassRegM(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallM),
|
||||
.clear(FlushM),
|
||||
.d(InstrClassE),
|
||||
.q(InstrClassM));
|
||||
|
||||
flopenrc #(1) BPPredWrongRegM(.clk(clk),
|
||||
flopenrc #(4) BPPredWrongRegM(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(~StallM),
|
||||
.clear(FlushM),
|
||||
.d(BPPredWrongE),
|
||||
.q(BPPredWrongM));
|
||||
.d({BPPredDirWrongE, BTBPredPCWrongE, RASPredPCWrongE, BPPredClassNonCFIWrongE}),
|
||||
.q({BPPredDirWrongM, BTBPredPCWrongM, RASPredPCWrongM, BPPredClassNonCFIWrongM}));
|
||||
|
||||
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
|
||||
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
|
||||
|
@ -33,13 +33,17 @@ module csr #(parameter
|
||||
UIE_REGW = 12'b0
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic FlushW, StallW,
|
||||
input logic FlushW, StallD, StallE, StallM, StallW,
|
||||
input logic [31:0] InstrM,
|
||||
input logic [`XLEN-1:0] PCM, SrcAM,
|
||||
input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
||||
input logic TimerIntM, ExtIntM, SwIntM,
|
||||
input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic InstrValidW, FloatRegWriteW, LoadStallD,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CauseM, NextFaultMtvalM,
|
||||
output logic [1:0] STATUS_MPP,
|
||||
|
@ -30,15 +30,20 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module csrc (
|
||||
input logic clk, reset,
|
||||
input logic InstrValidW, LoadStallD, CSRMWriteM, BPPredWrongM,
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidW, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM);
|
||||
output logic IllegalCSRCAccessM);
|
||||
|
||||
// create Counter arrays to store address of each counter
|
||||
integer MHPMCOUNTER [`COUNTERS:0];
|
||||
@ -65,11 +70,16 @@ module csrc (
|
||||
logic [`COUNTERS:0] MCOUNTEN;
|
||||
assign MCOUNTEN[0] = 1'b1;
|
||||
assign MCOUNTEN[1] = 1'b0;
|
||||
assign MCOUNTEN[2] = InstrValidW;
|
||||
assign MCOUNTEN[3] = LoadStallD;
|
||||
assign MCOUNTEN[4] = BPPredWrongM;
|
||||
assign MCOUNTEN[5] = InstrClassM[0];
|
||||
assign MCOUNTEN[`COUNTERS:6] = 0;
|
||||
assign MCOUNTEN[2] = InstrValidW & ~StallW;
|
||||
assign MCOUNTEN[3] = LoadStallD & ~StallD;
|
||||
assign MCOUNTEN[4] = BPPredDirWrongM & ~StallM;
|
||||
assign MCOUNTEN[5] = InstrClassM[0] & ~StallM;
|
||||
assign MCOUNTEN[6] = BTBPredPCWrongM & ~StallM;
|
||||
assign MCOUNTEN[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & ~StallM;
|
||||
assign MCOUNTEN[8] = RASPredPCWrongM & ~StallM;
|
||||
assign MCOUNTEN[9] = InstrClassM[3] & ~StallM;
|
||||
assign MCOUNTEN[10] = BPPredClassNonCFIWrongM & ~StallM;
|
||||
assign MCOUNTEN[`COUNTERS:11] = 0;
|
||||
|
||||
genvar j;
|
||||
generate
|
||||
@ -95,7 +105,7 @@ module csrc (
|
||||
// Write / update counters
|
||||
// Only the Machine mode versions of the counter CSRs are writable
|
||||
if (`XLEN==64) begin // 64-bit counters
|
||||
flopr #(64) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]);
|
||||
flopenr #(64) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]);
|
||||
end
|
||||
else begin // 32-bit low and high counters
|
||||
logic [`COUNTERS:0] WriteHPMCOUNTERHM;
|
||||
@ -106,8 +116,8 @@ module csrc (
|
||||
assign NextHPMCOUNTERHM[j] = WriteHPMCOUNTERHM[j] ? CSRWriteValM : HPMCOUNTERPlusM[j][63:32];
|
||||
|
||||
// Counter CSRs
|
||||
flopr #(32) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]);
|
||||
flopr #(32) HPMCOUNTERHreg_j(clk, reset, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]);
|
||||
flopenr #(32) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]);
|
||||
flopenr #(32) HPMCOUNTERHreg_j(clk, reset, ~StallW, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]);
|
||||
end
|
||||
end // end for
|
||||
|
||||
|
@ -33,6 +33,7 @@ module csri #(parameter
|
||||
SIE = 12'h104,
|
||||
SIP = 12'h144) (
|
||||
input logic clk, reset,
|
||||
input logic StallW,
|
||||
input logic CSRMWriteM, CSRSWriteM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic ExtIntM, TimerIntM, SwIntM,
|
||||
@ -60,10 +61,10 @@ module csri #(parameter
|
||||
end
|
||||
|
||||
// Interrupt Write Enables
|
||||
assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP);
|
||||
assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE);
|
||||
assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP);
|
||||
assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE);
|
||||
assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP) && ~StallW;
|
||||
assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE) && ~StallW;
|
||||
assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP) && ~StallW;
|
||||
assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE) && ~StallW;
|
||||
|
||||
// Interrupt Pending and Enable Registers
|
||||
// MEIP, MTIP, MSIP are read-only
|
||||
|
@ -83,6 +83,7 @@ module csrm #(parameter
|
||||
MIDELEG_MASK = {{(`XLEN-12){1'b0}}, 12'h222}
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallW,
|
||||
input logic CSRMWriteM, MTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW,
|
||||
@ -113,34 +114,34 @@ module csrm #(parameter
|
||||
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]};
|
||||
|
||||
// Write machine Mode CSRs
|
||||
assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS);
|
||||
assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC);
|
||||
assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG);
|
||||
assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG);
|
||||
assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH);
|
||||
assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC));
|
||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE));
|
||||
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL));
|
||||
assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0));
|
||||
assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2));
|
||||
assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0));
|
||||
assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1));
|
||||
assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2));
|
||||
assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3));
|
||||
assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4));
|
||||
assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5));
|
||||
assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6));
|
||||
assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7));
|
||||
assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8));
|
||||
assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9));
|
||||
assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10));
|
||||
assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11));
|
||||
assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12));
|
||||
assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13));
|
||||
assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14));
|
||||
assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15));
|
||||
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN);
|
||||
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT);
|
||||
assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS) && ~StallW;
|
||||
assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC) && ~StallW;
|
||||
assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG) && ~StallW;
|
||||
assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG) && ~StallW;
|
||||
assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH) && ~StallW;
|
||||
assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)) && ~StallW;
|
||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)) && ~StallW;
|
||||
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)) && ~StallW;
|
||||
assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW;
|
||||
assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)) && ~StallW;
|
||||
assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)) && ~StallW;
|
||||
assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)) && ~StallW;
|
||||
assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2)) && ~StallW;
|
||||
assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3)) && ~StallW;
|
||||
assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4)) && ~StallW;
|
||||
assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5)) && ~StallW;
|
||||
assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6)) && ~StallW;
|
||||
assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7)) && ~StallW;
|
||||
assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8)) && ~StallW;
|
||||
assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9)) && ~StallW;
|
||||
assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10)) && ~StallW;
|
||||
assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11)) && ~StallW;
|
||||
assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)) && ~StallW;
|
||||
assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)) && ~StallW;
|
||||
assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)) && ~StallW;
|
||||
assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)) && ~StallW;
|
||||
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN) && ~StallW;
|
||||
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT) && ~StallW;
|
||||
|
||||
assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID);
|
||||
|
||||
|
@ -36,6 +36,7 @@ module csrn #(parameter
|
||||
UTVAL = 12'h043,
|
||||
UIP = 12'h044) (
|
||||
input logic clk, reset,
|
||||
input logic StallW,
|
||||
input logic CSRNWriteM, UTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, USTATUS_REGW,
|
||||
@ -56,11 +57,11 @@ module csrn #(parameter
|
||||
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
|
||||
|
||||
// Write enables
|
||||
assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS);
|
||||
assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC);
|
||||
assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC));
|
||||
assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE));
|
||||
assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL));
|
||||
assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS) && ~StallW;
|
||||
assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC) && ~StallW;
|
||||
assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC)) && ~StallW;
|
||||
assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE)) && ~StallW;
|
||||
assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL)) && ~StallW;
|
||||
|
||||
// CSRs
|
||||
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, CSRWriteValM, `RESET_VECTOR, UTVEC_REGW);
|
||||
@ -95,4 +96,4 @@ module csrn #(parameter
|
||||
assign IllegalCSRNAccessM = 1;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
endmodule
|
||||
|
@ -47,6 +47,7 @@ module csrs #(parameter
|
||||
SEDELEG_MASK = ~(ZERO | 3'b111 << 9)
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallW,
|
||||
input logic CSRSWriteM, STrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW,
|
||||
@ -72,14 +73,14 @@ module csrs #(parameter
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW;
|
||||
|
||||
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS);
|
||||
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC);
|
||||
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH);
|
||||
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC));
|
||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE));
|
||||
assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL));
|
||||
assign WriteSATPM = CSRSWriteM && (CSRAdrM == SATP);
|
||||
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN);
|
||||
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW;
|
||||
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW;
|
||||
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH) && ~StallW;
|
||||
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)) && ~StallW;
|
||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)) && ~StallW;
|
||||
assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL)) && ~StallW;
|
||||
assign WriteSATPM = CSRSWriteM && (CSRAdrM == SATP) && ~StallW;
|
||||
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW;
|
||||
|
||||
// CSRs
|
||||
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, ZERO, STVEC_REGW); //busybear: change reset to 0
|
||||
|
@ -32,6 +32,7 @@ module csru #(parameter
|
||||
FRM = 12'h002,
|
||||
FCSR = 12'h003) (
|
||||
input logic clk, reset,
|
||||
input logic StallW,
|
||||
input logic CSRUWriteM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
@ -50,9 +51,9 @@ module csru #(parameter
|
||||
logic [4:0] NextFFLAGSM;
|
||||
|
||||
// Write enables
|
||||
assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR);
|
||||
assign WriteFFLAGSM = CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM ;
|
||||
assign WriteFRMM = CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM;
|
||||
assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR) && ~StallW;
|
||||
assign WriteFFLAGSM = (CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM) && ~StallW;
|
||||
assign WriteFRMM = (CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM) && ~StallW;
|
||||
|
||||
// Write Values
|
||||
assign NextFRMM = WriteFCSRM ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||
@ -81,4 +82,4 @@ module csru #(parameter
|
||||
assign IllegalCSRUAccessM = 1;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
endmodule
|
||||
|
@ -37,8 +37,12 @@ module privileged (
|
||||
output logic [`XLEN-1:0] PrivilegedNextPCM,
|
||||
output logic RetM, TrapM,
|
||||
output logic ITLBFlushF, DTLBFlushM,
|
||||
input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic InstrValidW, FloatRegWriteW, LoadStallD,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic PrivilegedM,
|
||||
input logic ITLBInstrPageFaultF, DTLBLoadPageFaultM, DTLBStorePageFaultM,
|
||||
input logic WalkerInstrPageFaultF, WalkerLoadPageFaultM, WalkerStorePageFaultM,
|
||||
|
@ -37,6 +37,9 @@ module dtim #(parameter BASE=0, RANGE = 65535) (
|
||||
output logic HRESPTim, HREADYTim
|
||||
);
|
||||
|
||||
localparam integer MemStartAddr = BASE>>(1+`XLEN/32);
|
||||
localparam integer MemEndAddr = (RANGE+BASE)>>1+(`XLEN/32);
|
||||
|
||||
logic [`XLEN-1:0] RAM[BASE>>(1+`XLEN/32):(RANGE+BASE)>>1+(`XLEN/32)];
|
||||
logic [31:0] HWADDR, A;
|
||||
logic [`XLEN-1:0] HREADTim0;
|
||||
@ -48,6 +51,7 @@ module dtim #(parameter BASE=0, RANGE = 65535) (
|
||||
logic memread, memwrite;
|
||||
logic [3:0] busycount;
|
||||
|
||||
|
||||
assign initTrans = HREADY & HSELTim & (HTRANS != 2'b00);
|
||||
|
||||
// *** this seems like a weird way to use reset
|
||||
@ -82,12 +86,22 @@ module dtim #(parameter BASE=0, RANGE = 65535) (
|
||||
assign risingHREADYTim = HREADYTim & ~prevHREADYTim;
|
||||
|
||||
// Model memory read and write
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
integer index;
|
||||
|
||||
initial begin
|
||||
for(index = MemStartAddr; index < MemEndAddr; index = index + 1) begin
|
||||
RAM[index] <= {`XLEN{1'b0}};
|
||||
end
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
always_ff @(posedge HCLK) begin
|
||||
HWADDR <= #1 A;
|
||||
HREADTim0 <= #1 RAM[A[31:3]];
|
||||
if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA;
|
||||
if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA;
|
||||
end
|
||||
end else begin
|
||||
always_ff @(posedge HCLK) begin
|
||||
|
@ -134,8 +134,13 @@ module wallypipelinedhart (
|
||||
logic DataStall;
|
||||
logic InstrAckF, MemAckW;
|
||||
|
||||
logic BPPredWrongE, BPPredWrongM;
|
||||
logic [3:0] InstrClassM;
|
||||
logic BPPredWrongE;
|
||||
logic BPPredDirWrongM;
|
||||
logic BTBPredPCWrongM;
|
||||
logic RASPredPCWrongM;
|
||||
logic BPPredClassNonCFIWrongM;
|
||||
|
||||
logic [4:0] InstrClassM;
|
||||
|
||||
|
||||
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache
|
||||
|
@ -27,9 +27,10 @@
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile);
|
||||
module FunctionName(reset, clk, ProgramAddrMapFile, ProgramLabelMapFile);
|
||||
|
||||
input logic reset;
|
||||
input logic clk;
|
||||
input string ProgramAddrMapFile;
|
||||
input string ProgramLabelMapFile;
|
||||
|
||||
@ -38,13 +39,23 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile);
|
||||
string FunctionName;
|
||||
|
||||
|
||||
logic [`XLEN-1:0] pc, FunctionAddr;
|
||||
logic [`XLEN-1:0] PCF, PCD, PCE, FunctionAddr;
|
||||
logic StallD, StallE, FlushD, FlushE;
|
||||
integer ProgramAddrIndex;
|
||||
|
||||
// *** I should look into the system verilog objects instead of signal spy.
|
||||
initial begin
|
||||
$init_signal_spy("/testbench/dut/hart/PCE", "/testbench/functionRadix/function_radix/pc");
|
||||
end
|
||||
assign PCF = testbench.dut.hart.PCF;
|
||||
assign StallD = testbench.dut.hart.StallD;
|
||||
assign StallE = testbench.dut.hart.StallE;
|
||||
assign FlushD = testbench.dut.hart.FlushD;
|
||||
assign FlushE = testbench.dut.hart.FlushE;
|
||||
|
||||
// copy from ifu
|
||||
// when the F and D stages are flushed we need to ensure the PCE is held so that the function name does not
|
||||
// erroneously change.
|
||||
flopenrc #(`XLEN) PCDReg(clk, reset, 1'b0, ~StallD, FlushE & FlushD ? PCE : PCF, PCD);
|
||||
flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, FlushE ? PCE : PCD, PCE);
|
||||
|
||||
|
||||
|
||||
task automatic bin_search_min;
|
||||
input logic [`XLEN-1:0] pc;
|
||||
@ -74,7 +85,7 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile);
|
||||
end else if( array[mid] > pc) begin
|
||||
right = mid -1;
|
||||
end else begin
|
||||
$display("Critical Error in function radix. PC, %x not found.", pc);
|
||||
$display("Critical Error in FunctionName. PC, %x not found.", pc);
|
||||
return;
|
||||
//$stop();
|
||||
end
|
||||
@ -141,8 +152,8 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile);
|
||||
|
||||
end
|
||||
|
||||
always @(pc) begin
|
||||
bin_search_min(pc, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex);
|
||||
always @(PCE) begin
|
||||
bin_search_min(PCE, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex);
|
||||
end
|
||||
|
||||
|
||||
|
@ -338,7 +338,9 @@ module testbench();
|
||||
};
|
||||
|
||||
string testsBP64[] = '{
|
||||
"rv64BP/reg-test", "10000"
|
||||
"rv64BP/simple", "10000",
|
||||
"rv64BP/qsort", "1000000",
|
||||
"rv64BP/sieve", "1000000"
|
||||
};
|
||||
|
||||
string tests64p[] = '{
|
||||
@ -397,7 +399,7 @@ module testbench();
|
||||
// pick tests based on modes supported
|
||||
initial begin
|
||||
if (`XLEN == 64) begin // RV64
|
||||
if (TESTSBP) begin
|
||||
if (`TESTSBP) begin
|
||||
tests = {testsBP64,tests64p};
|
||||
end if (TESTSPERIPH) begin
|
||||
tests = tests64periph;
|
||||
@ -453,17 +455,24 @@ module testbench();
|
||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
|
||||
// initialize tests
|
||||
localparam integer MemStartAddr = `TIMBASE>>(1+`XLEN/32);
|
||||
localparam integer MemEndAddr = (`TIMRANGE+`TIMBASE)>>1+(`XLEN/32);
|
||||
|
||||
initial
|
||||
begin
|
||||
test = 0;
|
||||
totalerrors = 0;
|
||||
testadr = 0;
|
||||
// fill memory with defined values to reduce Xs in simulation
|
||||
// Quick note the memory will need to be initialized. The C library does not
|
||||
// guarantee the initialized reads. For example a strcmp can read 6 byte
|
||||
// strings, but uses a load double to read them in. If the last 2 bytes are
|
||||
// not initialized the compare results in an 'x' which propagates through
|
||||
// the design.
|
||||
if (`XLEN == 32) meminit = 32'hFEDC0123;
|
||||
else meminit = 64'hFEDCBA9876543210;
|
||||
for (i=0; i<=65535; i = i+1) begin
|
||||
//dut.imem.RAM[i] = meminit;
|
||||
// dut.uncore.RAM[i] = meminit;
|
||||
for (i=MemStartAddr; i<MemEndAddr; i = i+1) begin
|
||||
dut.uncore.dtim.RAM[i] = meminit;
|
||||
end
|
||||
// read test vectors into memory
|
||||
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
|
||||
@ -551,10 +560,11 @@ module testbench();
|
||||
end // always @ (negedge clk)
|
||||
|
||||
// track the current function or global label
|
||||
if (DEBUG == 1) begin : functionRadix
|
||||
function_radix function_radix(.reset(reset),
|
||||
.ProgramAddrMapFile(ProgramAddrMapFile),
|
||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||
if (DEBUG == 1) begin : FunctionName
|
||||
FunctionName FunctionName(.reset(reset),
|
||||
.clk(clk),
|
||||
.ProgramAddrMapFile(ProgramAddrMapFile),
|
||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||
end
|
||||
|
||||
// initialize the branch predictor
|
||||
|
Loading…
Reference in New Issue
Block a user