Merge branch 'main' into fpga

This commit is contained in:
Ross Thompson 2021-09-13 09:45:59 -05:00
commit e98a046f9d
11 changed files with 1704 additions and 194 deletions

View File

@ -0,0 +1,112 @@
CEXT := c
CPPEXT := cpp
AEXT := s
SEXT := S
SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\)
OBJEXT := o
DEPEXT := d
SRCDIR := .
BUILDDIR := OBJ
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))
TARGETDIR := bin
TARGET := $(TARGETDIR)/blink-led
ROOT := ..
LIBRARY_DIRS :=
LIBRARY_FILES :=
MARCH :=-march=rv64imfdc
MABI :=-mabi=lp64d
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
LINKER :=$(ROOT)/linker1000.x
AFLAGS =$(MARCH) $(MABI) -W
CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2
AS=riscv64-unknown-elf-as
CC=riscv64-unknown-elf-gcc
AR=riscv64-unknown-elf-ar
#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
mkdir -p ../../imperas-riscv-tests/work/rv64BP/
cp -f $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/

View File

@ -0,0 +1,86 @@
PERIOD = 22000000
#PERIOD = 100
.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
# write to gpio
li x2, 0xFF
la x3, 0x10012000
# +8 is output enable
# +C is output value
addi x4, x3, 8
addi x5, x3, 0xC
# write initial value of 0xFF to GPO
sw x2, 0x0(x5)
# enable output
sw x2, 0x0(x4)
loop:
# delay
li x20, PERIOD/2
delay1:
addi x20, x20, -1
bge x20, x0, delay1
# clear GPO
sw x0, 0x0(x5)
# delay
li x20, PERIOD/2
delay2:
addi x20, x20, -1
bge x20, x0, delay2
# write GPO
sw x2, 0x0(x5)
j loop

244
testsBP/linker1000.x Normal file
View 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*/
. = 0x0000000000001000;
. = 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_*) }
}

View File

@ -17,10 +17,10 @@
onbreak {resume} onbreak {resume}
# create library # create library
if [file exists work-arch] { if [file exists work_arch_$2] {
vdel -all vdel -lib work_arch_$2 -all
} }
vlib work-arch vlib work_arch_$2
# compile source files # compile source files
# suppress spurious warnngs about # suppress spurious warnngs about
@ -30,13 +30,14 @@ vlib work-arch
# default to config/rv64ic, but allow this to be overridden at the command line. For example: # default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined.do ../config/rv32ic # do wally-pipelined.do ../config/rv32ic
switch $argc { switch $argc {
0 {vlog +incdir+../config/rv64ic +incdir+../config/shared ../testbench/testbench-arch.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583} 0 {vlog -work work_arch_$2 +incdir+../config/rv64ic +incdir+../config/shared ../testbench/testbench-arch.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583}
1 {vlog +incdir+$1 +incdir+../config/shared ../testbench/testbench-arch.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583} 1 {vlog -work work_arch_$2 +incdir+$1 +incdir+../config/shared ../testbench/testbench-arch.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583}
2 {vlog -work work_arch_$2 +incdir+$1 +incdir+../config/shared ../testbench/testbench-arch.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583}
} }
# start and run simulation # start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals # remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work-arch.testbench -o workopt vopt +acc work_arch_$2.testbench -work work_arch_$2 -o workopt_arch
vsim workopt vsim -lib work_arch_$2 workopt_arch
view wave view wave
-- display input and output signals as hexidecimal values -- display input and output signals as hexidecimal values

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////
//
// Written: David Harris
// Modified: 11 September 2021
//
// Purpose: Recurrence-based SRT Division and Square Root
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
module fpudivsqrtrecur (
input logic clk,
input logic reset,
input logic FlushM, // flush the memory stage
input logic StallM, // stall memory stage
input logic FDivSqrtStart, // start a computation
input logic FmtE, // precision 1 = double 0 = single
input logic FDivE, FSqrtE,
input logic [2:0] FrmM, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
input logic XSgnE, YSgnE, // input signs - execute stage
input logic [`NE-1:0] XExpE, YExpE, // input exponents - execute stage
input logic [`NF:0] XManE, YManE, // input mantissa - execute stage
input logic XDenormE, YDenormE, // is denorm
input logic XZeroE, YZeroE, // is zero - execute stage
input logic XNaNE, YNaNE, // is NaN
input logic XSNaNE, YSNaNE, // is signaling NaN
input logic XInfE, YInfE, ZInfE, // is infinity
input logic [10:0] BiasE, // bias (max exponent/2) ***parameterize in unpacking unit
output logic FDviSqrtBusy, FDivSqrtDone, //currently occpied, or done with operation
output logic [`FLEN-1:0] FDivSqrtResM, // result
output logic [4:0] FDivSqrtFlgM // flags
);
logic FDivSqrtResSgn;
logic [`FLEN-1:0] FDivSqrtRecurRes;
// Radix-2 SRT Division and Square Root
// Special Cases
// *** shift to handle denorms in hardware
assign FDivSqrtResSign = FDivE & (XSgnE ^ YSgnE); // Sign is negative for division if inputs have opposite signs
always_comb begin
if (FSqrtE & XSgnE | FDivE & XZeroE & YZeroE | XNaNE | FDivE & YNaNE) FDivSqrtResM = 0; // ***replace with NAN; // *** which one
else if (FDivE & YZeroE | XInfE) FDivSqrtResM = {FDivSqrtResSgn, `NE'b1, `NF'b0}; // infinity
else if (FDivE & YInfE) FDivSqrtResM = {FDivSqrtResSgn, `NE'b0, `NF'b0}; // zero
else FDivSqrtResM = FDivSqrtRecurRes;
end
// *** handle early termination in the special cases
// *** handle signaling NANs
endmodule

View File

@ -0,0 +1,100 @@
///////////////////////////////////////////
//
// Written: David Harris
// Modified: 11 September 2021
//
// Purpose: Recurrence-based SRT Division and Square Root
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
// Bit counts:
// Inputs are originally normalized floating point numbers with NF fractional bits and a leading 1 integer bit
// x is right shifted by up to 2 to be in the range of 1/4 <= x < 1/2 for divide, 1/4 <= x < 1 for sqrt
// Hence, x now has NF+2 fractional bits and 0 integer bits
// d is right shifted by 1 to be in the range of 1/2 <= d < 1. It thus has NF+1 fractional bits and 0 integer bits
// q is eventually in the range of 1/4 < q < 1 and hence needs NF+2 bits to keep NF bits when normalized, plus some*** more bits for rounding
// The partial
/*
module fpudivsqrtrecurcore (
input logic clk,
input logic reset,
input logic start, // start a computation
input logic busy, // computation running
input logic fmt, // precision 1 = double 0 = single
input logic [`NF+1:0] x, // in range 1/4 <= x < 1/2 for divide, 1/4 <=x < 1 for sqrt
input logic [`NF+1:0] din, // in range 1/2 <= d < 1 for divide
input logic FDiv, FSqrt, // *** not yet used
output logic [`FLEN-1:0] FDivSqrtRecurRes // result
);
assign FDivSqrtRecurRes = 0;
logic [***] d, ws, wsout, wsnext, wc, wcout, wcnext;
logic [1:0] q; // 00 = 0, 01 = 1, 10 = -1
// Radix-2 SRT Division
// registers for divisor and partial remainder
flopen #(NF+1) dreg(clk, start, din, d);
mux2 #(NF+1) wsmux(wsout, x, start, wsnext);
flopen #(NF+1) wsreg(clk, busy, wsnext, ws);
mux2 #(NF+1) wcmux(wcout, 0, start, wcnext);
flopen #(NF+1) wcreg(clk, busy, wcnext, wc);
// quotient selection
qsel qsel(ws[***4bits], wc[***], q);
// partial remainder update
always_comb begin // select -d * q to add to partial remainder
if (q[1]) dq = d;
else if (q[0]) dq = ~d;
else dq = 0;
end
csa #(***) csa(ws, wc, dq, q[1], wsout, wcout);
endmodule
*/
/*
module csa #(parameter N=4) (
input logic [N-1:0] sin, cin, ain,
input logic carry,
output logic [N-1:0] sum, cout
);
logic [N-1:0] c;
assign c = {cin[N-2:0], carry}; // shift carries left and inject optional 1 into lsb
assign sum = sin ^ ain ^ c;
assign cout = sin & ain | sin & c | ain & c;
endmodule
*/
module qsel( // radix 2 SRT division quotient selection
input logic [3:0] wc, ws,
output logic [1:0] q
);
endmodule

View File

@ -0,0 +1,76 @@
///////////////////////////////////////////
// intdiv_restoring.sv
//
// Written: David_Harris@hmc.edu 12 September 2021
// Modified:
//
// Purpose: Restoring integer division using a shift register a subtractor
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
module intdiv_restoring (
input logic clk,
input logic reset,
input logic signedDivide,
input logic start,
input logic [`XLEN-1:0] X, D,
output logic busy, done,
output logic [`XLEN-1:0] Q, REM
);
logic [`XLEN-1:0] W, Win, Wshift, Wprime, Wnext, XQ, XQin, XQshift;
logic qi; // curent quotient bit
localparam STEPBITS = $clog2(`XLEN);
logic [STEPBITS:0] step;
logic div0;
// restoring division
mux2 #(`XLEN) wmux(W, 0, start, Win);
mux2 #(`XLEN) xmux(0, X, start, XQin);
assign {Wshift, XQshift} = {Win[`XLEN-2:0], XQin, qi};
assign {qi, Wprime} = Wshift - D; // subtractor, carry out determines quotient bit
mux2 #(`XLEN) wrestoremux(Wshift, Wprime, qi, Wnext);
flopen #(`XLEN) wreg(clk, busy, Wnext, W);
flopen #(`XLEN) xreg(clk, busy, XQshift, XQ);
// outputs
// *** sign extension, handling W instructions
assign div0 = (D == 0);
mux2 #(`XLEN) qmux(XQ, {`XLEN{1'b1}}, div0, Q); // Q taken from XQ register, or all 1s when dividing by zero
mux2 #(`XLEN) remmux(W, X, div0, REM); // REM taken from W register, or from X when dividing by zero
// busy logic
always_ff @(posedge clk)
if (start) begin
busy = 1; done = 0; step = 0;
end else if (busy) begin
step = step + 1;
if (step[STEPBITS] | div0) begin // *** early terminate on division by 0
step = 0;
busy = 0;
done = 1;
end
end else if (done) begin
done = 0;
end
endmodule // muldiv

View File

@ -51,7 +51,7 @@ module muldiv (
logic enable_q; logic enable_q;
logic [2:0] Funct3E_Q; logic [2:0] Funct3E_Q;
logic div0error; logic div0error; // ***unused
logic [`XLEN-1:0] N, D; logic [`XLEN-1:0] N, D;
logic [`XLEN-1:0] Num0, Den0; logic [`XLEN-1:0] Num0, Den0;
@ -89,11 +89,13 @@ module muldiv (
assign signedDivide = (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]); assign signedDivide = (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]);
intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, signedDivide); intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, signedDivide);
//intdiv_restoring div(.clk, .reset, .signedDivide, .start(startDivideE), .X(N), .D(D), .busy(DivBusyE), .done(DivDoneE), .Q(QuotE), .REM(RemE));
// Added for debugging of start signal for divide // Added for debugging of start signal for divide
assign startDivideE = MulDivE&DivStartE&~DivBusyE; assign startDivideE = MulDivE&DivStartE&~DivBusyE;
// capture the start control signals since they are not held constant. // capture the start control signals since they are not held constant.
// *** appears to be unused
flopenrc #(3) funct3ereg (.d(Funct3E), flopenrc #(3) funct3ereg (.d(Funct3E),
.q(Funct3E_Q), .q(Funct3E_Q),
.en(DivStartE), .en(DivStartE),
@ -114,7 +116,7 @@ module muldiv (
3'b111: PrelimResultE = RemE; 3'b111: PrelimResultE = RemE;
endcase // case (Funct3E) endcase // case (Funct3E)
// Start Divide process // Start Divide process. This simplifies to DivStartE = Funct3E[2];
always_comb always_comb
case (Funct3E) case (Funct3E)
3'b000: DivStartE = 1'b0; 3'b000: DivStartE = 1'b0;

View File

@ -79,6 +79,7 @@ module uartPC16550D(
logic [9:0] rxshiftreg; logic [9:0] rxshiftreg;
logic [10:0] rxfifo[15:0]; logic [10:0] rxfifo[15:0];
logic [7:0] txfifo[15:0]; logic [7:0] txfifo[15:0];
logic [4:0] rxfifotailunwrapped;
logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel; logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel;
logic [3:0] rxfifoentries, txfifoentries; logic [3:0] rxfifoentries, txfifoentries;
logic [3:0] rxbitsexpected, txbitsexpected; logic [3:0] rxbitsexpected, txbitsexpected;
@ -95,6 +96,7 @@ module uartPC16550D(
logic [8:0] rxdata9; logic [8:0] rxdata9;
logic [7:0] rxdata; logic [7:0] rxdata;
logic [15:0] RXerrbit, rxfullbit; logic [15:0] RXerrbit, rxfullbit;
logic [31:0] rxfullbitunwrapped;
// transmit data // transmit data
logic [7:0] TXHR, nexttxdata; logic [7:0] TXHR, nexttxdata;
@ -289,14 +291,21 @@ module uartPC16550D(
// detect any errors in rx fifo // detect any errors in rx fifo
// although rxfullbit looks like a combinational loop, in one bit rxfifotail == i and breaks the loop // although rxfullbit looks like a combinational loop, in one bit rxfifotail == i and breaks the loop
// tail is normally higher than head, but might wrap around. unwrapped variable adds 16 to eliminate wrapping
generate generate
assign rxfifotailunwrapped = rxfifotail < rxfifohead ? {1'b1, rxfifotail} : {1'b0, rxfifotail};
genvar i; genvar i;
for (i=0; i<32; i++) begin:rxfull
if (i == 0) assign rxfullbitunwrapped[i] = (rxfifohead==0) & (rxfifotail != 0);
else assign rxfullbitunwrapped[i] = ({1'b0,rxfifohead}==i | rxfullbitunwrapped[i-1]) & (rxfifotailunwrapped != i);
end
for (i=0; i<16; i++) begin:rx for (i=0; i<16; i++) begin:rx
assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set? assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set?
if (i > 0) assign rxfullbit[i] = rxfullbitunwrapped[i] | rxfullbitunwrapped[i+16];
/* if (i > 0)
assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i); assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i);
else else
assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i); assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/
end end
endgenerate endgenerate
assign rxfifohaserr = |(RXerrbit & rxfullbit); assign rxfifohaserr = |(RXerrbit & rxfullbit);

View File

@ -160,6 +160,28 @@ string tests32f[] = '{
"rv64a/WALLY-LRSC", "2110" "rv64a/WALLY-LRSC", "2110"
}; };
string tests64priv[] = '{
"rv64i_m/privilege/ebreak", "2090",
"rv64i_m/privilege/ecall", "2090",
"rv64i_m/privilege/misalign-beq-01", "20a0",
"rv64i_m/privilege/misalign-bge-01", "20a0",
"rv64i_m/privilege/misalign-bgeu-01", "20a0",
"rv64i_m/privilege/misalign-blt-01", "20a0",
"rv64i_m/privilege/misalign-bltu-01", "20a0",
"rv64i_m/privilege/misalign-bne-01", "20a0",
"rv64i_m/privilege/misalign-jal-01", "20a0",
"rv64i_m/privilege/misalign-ld-01", "20a0",
"rv64i_m/privilege/misalign-lh-01", "20a0",
"rv64i_m/privilege/misalign-lhu-01", "20a0",
"rv64i_m/privilege/misalign-lw-01", "20a0",
"rv64i_m/privilege/misalign-lwu-01", "20a0",
"rv64i_m/privilege/misalign-sd-01", "20a0",
"rv64i_m/privilege/misalign-sh-01", "20a0",
"rv64i_m/privilege/misalign-sw-01", "20a0",
"rv64i_m/privilege/misalign1-jalr-01", "20a0",
"rv64i_m/privilege/misalign2-jalr-01", "20a0"
};
string tests64m[] = '{ string tests64m[] = '{
"rv64i_m/M/div-01", "9010", "rv64i_m/M/div-01", "9010",
"rv64i_m/M/divu-01", "a010", "rv64i_m/M/divu-01", "a010",
@ -212,10 +234,6 @@ string tests32f[] = '{
"rv64i_m/C/cxor-01", "8010" "rv64i_m/C/cxor-01", "8010"
}; };
string tests64iNOc[] = {
"rv64i/I-MISALIGN_JMP-01","2000"
};
string tests64i[] = '{ string tests64i[] = '{
"rv64i_m/I/add-01", "9010", "rv64i_m/I/add-01", "9010",
"rv64i_m/I/addi-01", "6010", "rv64i_m/I/addi-01", "6010",
@ -269,189 +287,106 @@ string tests32f[] = '{
"rv64i_m/I/xori-01", "6010" "rv64i_m/I/xori-01", "6010"
}; };
string tests32a[] = '{ string tests32priv[] = '{
"rv32a/WALLY-AMO", "2110", "rv32i_m/privilege/ebreak", "2090",
"rv32a/WALLY-LRSC", "2110" "rv32i_m/privilege/ecall", "2090",
}; "rv32i_m/privilege/misalign-beq-01", "20a0",
"rv32i_m/privilege/misalign-bge-01", "20a0",
"rv32i_m/privilege/misalign-bgeu-01", "20a0",
"rv32i_m/privilege/misalign-blt-01", "20a0",
"rv32i_m/privilege/misalign-bltu-01", "20a0",
"rv32i_m/privilege/misalign-bne-01", "20a0",
"rv32i_m/privilege/misalign-jal-01", "20a0",
"rv32i_m/privilege/misalign-lh-01", "20a0",
"rv32i_m/privilege/misalign-lhu-01", "20a0",
"rv32i_m/privilege/misalign-lw-01", "20a0",
"rv32i_m/privilege/misalign-lwu-01", "20a0",
"rv32i_m/privilege/misalign-sh-01", "20a0",
"rv32i_m/privilege/misalign-sw-01", "20a0",
"rv32i_m/privilege/misalign1-jalr-01", "20a0",
"rv32i_m/privilege/misalign2-jalr-01", "20a0"
};
string tests32m[] = '{ string tests32m[] = '{
"rv32m/I-MUL-01", "2000", "rv32i_m/M/div-01", "9010",
"rv32m/I-MULH-01", "2000", "rv32i_m/M/divu-01", "a010",
"rv32m/I-MULHSU-01", "2000", "rv32i_m/M/mul-01", "9010",
"rv32m/I-MULHU-01", "2000", "rv32i_m/M/mulh-01", "9010",
"rv32m/I-DIV-01", "2000", "rv32i_m/M/mulhsu-01", "9010",
"rv32m/I-DIVU-01", "2000", "rv32i_m/M/mulhu-01", "a010",
"rv32m/I-REM-01", "2000", "rv32i_m/M/rem-01", "9010",
"rv32m/I-REMU-01", "2000" "rv32i_m/M/remu-01", "a010",
}; };
string tests32ic[] = '{ string tests32ic[] = '{
"rv32ic/I-C-ADD-01", "2000", "rv32i_m/C/cadd-01", "8010",
"rv32ic/I-C-ADDI-01", "2000", "rv32i_m/C/caddi-01", "4010",
"rv32ic/I-C-AND-01", "2000", "rv32i_m/C/caddi16sp-01", "2010",
"rv32ic/I-C-ANDI-01", "2000", "rv32i_m/C/caddi4spn-01", "2010",
"rv32ic/I-C-BEQZ-01", "2000", "rv32i_m/C/cand-01", "8010",
"rv32ic/I-C-BNEZ-01", "2000", "rv32i_m/C/candi-01", "4010",
"rv32ic/I-C-EBREAK-01", "2000", "rv32i_m/C/cbeqz-01", "4010",
"rv32ic/I-C-J-01", "2000", "rv32i_m/C/cbnez-01", "5010",
"rv32ic/I-C-JALR-01", "3000", "rv32i_m/C/cebreak-01", "2070",
"rv32ic/I-C-JR-01", "3000", "rv32i_m/C/cj-01", "3010",
"rv32ic/I-C-LI-01", "2000", "rv32i_m/C/cjal-01", "",
"rv32ic/I-C-LUI-01", "2000", "rv32i_m/C/cjalr-01", "2010",
"rv32ic/I-C-LW-01", "2110", "rv32i_m/C/cjr-01", "2010",
"rv32ic/I-C-LWSP-01", "2110", "rv32i_m/C/cli-01", "2010",
"rv32ic/I-C-MV-01", "2000", "rv32i_m/C/clui-01", "2010",
"rv32ic/I-C-NOP-01", "2000", "rv32i_m/C/clw-01", "2010",
"rv32ic/I-C-OR-01", "2000", "rv32i_m/C/clwsp-01", "2010",
"rv32ic/I-C-SLLI-01", "2000", "rv32i_m/C/cmv-01", "2010",
"rv32ic/I-C-SRAI-01", "2000", "rv32i_m/C/cnop-01", "2010",
"rv32ic/I-C-SRLI-01", "2000", "rv32i_m/C/cor-01", "8010",
"rv32ic/I-C-SUB-01", "2000", "rv32i_m/C/cslli-01", "2010",
"rv32ic/I-C-SW-01", "2000", "rv32i_m/C/csrai-01", "2010",
"rv32ic/I-C-SWSP-01", "2000", "rv32i_m/C/csrli-01", "2010",
"rv32ic/I-C-XOR-01", "2000" "rv32i_m/C/csub-01", "8010",
"rv32i_m/C/csw-01", "3010",
"rv32i_m/C/cswsp-01", "3010",
"rv32i_m/C/cxor-01", "8010"
}; };
string tests32iNOc[] = { string tests32i[] = '{
"rv32i/I-MISALIGN_JMP-01","2000" "rv32i_m/I/add-01", "9010",
}; "rv32i_m/I/addi-01", "6010",
"rv32i_m/I/and-01", "9010",
string tests32i[] = { "rv32i_m/I/andi-01", "6010",
//"rv32i/WALLY-PIPELINE-100K", "10a800", "rv32i_m/I/auipc-01", "2010",
"rv32i/I-ADD-01", "2000", "rv32i_m/I/beq-01", "47010",
"rv32i/I-ADDI-01","2000", "rv32i_m/I/bge-01", "47010",
"rv32i/I-AND-01","2000", "rv32i_m/I/bgeu-01", "56010",
"rv32i/I-ANDI-01","2000", "rv32i_m/I/blt-01", "4d010",
"rv32i/I-AUIPC-01","2000", "rv32i_m/I/bltu-01", "57010",
"rv32i/I-BEQ-01","3000", "rv32i_m/I/bne-01", "43010",
"rv32i/I-BGE-01","3000", "rv32i_m/I/fence-01", "2010",
"rv32i/I-BGEU-01","3000", "rv32i_m/I/jal-01", "122010",
"rv32i/I-BLT-01","3000", "rv32i_m/I/jalr-01", "2010",
"rv32i/I-BLTU-01","3000", "rv32i_m/I/lb-align-01", "2010",
"rv32i/I-BNE-01","3000", "rv32i_m/I/lbu-align-01", "2010",
"rv32i/I-DELAY_SLOTS-01","2000", "rv32i_m/I/lh-align-01", "2010",
"rv32i/I-EBREAK-01","2000", "rv32i_m/I/lhu-align-01", "2010",
"rv32i/I-ECALL-01","2000", "rv32i_m/I/lui-01", "2010",
"rv32i/I-ENDIANESS-01","2010", "rv32i_m/I/lw-align-01", "2010",
"rv32i/I-IO-01","2030rv", "rv32i_m/I/or-01", "9010",
"rv32i/I-JAL-01","3000", "rv32i_m/I/ori-01", "6010",
"rv32i/I-JALR-01","3000", "rv32i_m/I/sb-align-01", "3010",
"rv32i/I-LB-01","3020", "rv32i_m/I/sh-align-01", "3010",
"rv32i/I-LBU-01","3020", "rv32i_m/I/sll-01", "3010",
"rv32i/I-LH-01","3050", "rv32i_m/I/slli-01", "2010",
"rv32i/I-LHU-01","3050", "rv32i_m/I/slt-01", "9010",
"rv32i/I-LUI-01","2000", "rv32i_m/I/slti-01", "6010",
"rv32i/I-LW-01","3110", "rv32i_m/I/sltiu-01", "6010",
"rv32i/I-MISALIGN_LDST-01","2010", "rv32i_m/I/sltu-01", "a010",
"rv32i/I-NOP-01","2000", "rv32i_m/I/sra-01", "3010",
"rv32i/I-OR-01","2000", "rv32i_m/I/srai-01", "2010",
"rv32i/I-ORI-01","2000", "rv32i_m/I/srl-01", "3010",
"rv32i/I-RF_size-01","2000", "rv32i_m/I/srli-01", "2010",
"rv32i/I-RF_width-01","2000", "rv32i_m/I/sub-01", "9010",
"rv32i/I-RF_x0-01","2010", "rv32i_m/I/sw-align-01", "3010",
"rv32i/I-SB-01","3000", "rv32i_m/I/xor-01", "9010",
"rv32i/I-SH-01","3000", "rv32i_m/I/xori-01", "6010"
"rv32i/I-SLL-01","2000",
"rv32i/I-SLLI-01","2000",
"rv32i/I-SLT-01","2000",
"rv32i/I-SLTI-01","2000",
"rv32i/I-SLTIU-01","2000",
"rv32i/I-SLTU-01","2000",
"rv32i/I-SRA-01","2000",
"rv32i/I-SRAI-01","2000",
"rv32i/I-SRL-01","2000",
"rv32i/I-SRLI-01","2000",
"rv32i/I-SUB-01","2000",
"rv32i/I-SW-01","3000",
"rv32i/I-XOR-01","2000",
"rv32i/I-XORI-01","2000",
"rv32i/WALLY-ADD", "3000",
"rv32i/WALLY-SUB", "3000",
"rv32i/WALLY-ADDI", "2000",
"rv32i/WALLY-ANDI", "2000",
"rv32i/WALLY-ORI", "2000",
"rv32i/WALLY-XORI", "2000",
"rv32i/WALLY-SLTI", "2000",
"rv32i/WALLY-SLTIU", "2000",
"rv32i/WALLY-SLLI", "2000",
"rv32i/WALLY-SRLI", "2000",
"rv32i/WALLY-SRAI", "2000",
"rv32i/WALLY-LOAD", "11c00",
"rv32i/WALLY-SUB", "3000",
"rv32i/WALLY-STORE", "2000",
"rv32i/WALLY-JAL", "3000",
"rv32i/WALLY-JALR", "2000",
"rv32i/WALLY-BEQ" ,"4000",
"rv32i/WALLY-BNE", "4000 ",
"rv32i/WALLY-BLTU", "4000 ",
"rv32i/WALLY-BLT", "4000",
"rv32i/WALLY-BGE", "4000 ",
"rv32i/WALLY-BGEU", "4000 ",
"rv32i/WALLY-CSRRW", "3000",
"rv32i/WALLY-CSRRS", "3000",
"rv32i/WALLY-CSRRC", "4000",
"rv32i/WALLY-CSRRWI", "3000",
"rv32i/WALLY-CSRRSI", "3000",
"rv32i/WALLY-CSRRCI", "3000"
};
string testsBP64[] = '{
"rv64BP/simple", "10000",
"rv64BP/mmm", "1000000",
"rv64BP/linpack_bench", "1000000",
"rv64BP/sieve", "1000000",
"rv64BP/qsort", "1000000",
"rv64BP/dhrystone", "1000000"
};
string tests64p[] = '{
"rv64p/WALLY-MSTATUS", "2000",
"rv64p/WALLY-MCAUSE", "3000",
"rv64p/WALLY-SCAUSE", "2000",
"rv64p/WALLY-MEPC", "5000",
"rv64p/WALLY-SEPC", "4000",
"rv64p/WALLY-MTVAL", "6000",
"rv64p/WALLY-STVAL", "4000",
"rv64p/WALLY-MTVEC", "2000",
"rv64p/WALLY-STVEC", "2000",
"rv64p/WALLY-MARCHID", "4000",
"rv64p/WALLY-MIMPID", "4000",
"rv64p/WALLY-MHARTID", "4000",
"rv64p/WALLY-MVENDORID", "4000",
"rv64p/WALLY-MIE", "3000",
"rv64p/WALLY-MEDELEG", "4000",
"rv64p/WALLY-IP", "2000",
"rv64p/WALLY-CSR-PERMISSIONS-M", "5000",
"rv64p/WALLY-CSR-PERMISSIONS-S", "3000"
};
string tests32p[] = '{
"rv32p/WALLY-MSTATUS", "2000",
"rv32p/WALLY-MCAUSE", "3000",
"rv32p/WALLY-SCAUSE", "2000",
"rv32p/WALLY-MEPC", "5000",
"rv32p/WALLY-SEPC", "4000",
"rv32p/WALLY-MTVAL", "5000",
"rv32p/WALLY-STVAL", "4000",
"rv32p/WALLY-MARCHID", "4000",
"rv32p/WALLY-MIMPID", "4000",
"rv32p/WALLY-MHARTID", "4000",
"rv32p/WALLY-MVENDORID", "4000",
"rv32p/WALLY-MTVEC", "2000",
"rv32p/WALLY-STVEC", "2000",
"rv32p/WALLY-MIE", "3000",
"rv32p/WALLY-MEDELEG", "4000",
"rv32p/WALLY-IP", "3000",
"rv32p/WALLY-CSR-PERMISSIONS-M", "5000",
"rv32p/WALLY-CSR-PERMISSIONS-S", "3000"
};
string tests64periph[] = '{
"rv64i-periph/WALLY-PERIPH", "2000"
};
string tests32periph[] = '{
"rv32i-periph/WALLY-PLIC", "2080"
}; };
string tests[]; string tests[];
@ -490,7 +425,7 @@ string tests32f[] = '{
else if (TESTSPRIV) else if (TESTSPRIV)
tests = tests64p; tests = tests64p;
else begin else begin
tests = {tests64i}; tests = {tests64priv, tests64i};
// tests = {tests64p,tests64i, tests64periph}; // tests = {tests64p,tests64i, tests64periph};
if (`C_SUPPORTED) tests = {tests, tests64ic}; if (`C_SUPPORTED) tests = {tests, tests64ic};
// else tests = {tests, tests64iNOc}; // else tests = {tests, tests64iNOc};
@ -720,7 +655,7 @@ module riscvassertions();
assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS) else $error("ICACHE_BLOCKLENINBITS must be a power of 2"); assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS) else $error("ICACHE_BLOCKLENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
assert (`ICACHE_NUMWAYS == 1 || `MEM_ICACHE == 0) else $error("Multiple Instruction Cache ways not yet implemented"); assert (`ICACHE_NUMWAYS == 1 || `MEM_ICACHE == 0) else $warning("Multiple Instruction Cache ways not yet implemented");
assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES) else $error("ITLB_ENTRIES must be a power of 2"); assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES) else $error("ITLB_ENTRIES must be a power of 2");
assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES) else $error("DTLB_ENTRIES must be a power of 2"); assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES) else $error("DTLB_ENTRIES must be a power of 2");
assert (`TIM_RANGE >= 56'h07FFFFFF) else $error("Some regression tests will fail if TIM_RANGE is less than 56'h07FFFFFF"); assert (`TIM_RANGE >= 56'h07FFFFFF) else $error("Some regression tests will fail if TIM_RANGE is less than 56'h07FFFFFF");

View File

@ -0,0 +1,876 @@
///////////////////////////////////////////
// testbench-imperas.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
// Applies test programs from the Imperas suite
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
module testbench();
parameter DEBUG = 0;
parameter TESTSPERIPH = 0; // set to 0 for regression
parameter TESTSPRIV = 0; // set to 0 for regression
logic clk;
logic reset;
parameter SIGNATURESIZE = 5000000;
int test, i, errors, totalerrors;
logic [31:0] sig32[0:SIGNATURESIZE];
logic [`XLEN-1:0] signature[0:SIGNATURESIZE];
logic [`XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
logic [`XLEN-1:0] meminit;
string tests32mmu[] = '{
"rv32mmu/WALLY-MMU-SV32", "3000"
//"rv32mmu/WALLY-PMA", "3000",
//"rv32mmu/WALLY-PMA", "3000"
};
string tests64mmu[] = '{
"rv64mmu/WALLY-MMU-SV48", "3000",
"rv64mmu/WALLY-MMU-SV39", "3000"
//"rv64mmu/WALLY-PMA", "3000",
//"rv64mmu/WALLY-PMA", "3000"
};
string tests32f[] = '{
"rv32f/I-FADD-S-01", "2000",
"rv32f/I-FCLASS-S-01", "2000",
"rv32f/I-FCVT-S-W-01", "2000",
"rv32f/I-FCVT-S-WU-01", "2000",
"rv32f/I-FCVT-W-S-01", "2000",
"rv32f/I-FCVT-WU-S-01", "2000",
"rv32f/I-FDIV-S-01", "2000",
"rv32f/I-FEQ-S-01", "2000",
"rv32f/I-FLE-S-01", "2000",
"rv32f/I-FLT-S-01", "2000",
"rv32f/I-FMADD-S-01", "2000",
"rv32f/I-FMAX-S-01", "2000",
"rv32f/I-FMIN-S-01", "2000",
"rv32f/I-FMSUB-S-01", "2000",
"rv32f/I-FMUL-S-01", "2000",
"rv32f/I-FMV-W-X-01", "2000",
"rv32f/I-FMV-X-W-01", "2000",
"rv32f/I-FNMADD-S-01", "2000",
"rv32f/I-FNMSUB-S-01", "2000",
"rv32f/I-FSGNJ-S-01", "2000",
"rv32f/I-FSGNJN-S-01", "2000",
"rv32f/I-FSGNJX-S-01", "2000",
"rv32f/I-FSQRT-S-01", "2000",
"rv32f/I-FSW-01", "2000",
"rv32f/I-FLW-01", "2110",
"rv32f/I-FSUB-S-01", "2000"
};
string tests64f[] = '{
"rv64f/I-FLW-01", "2110",
"rv64f/I-FMV-W-X-01", "2000",
"rv64f/I-FMV-X-W-01", "2000",
"rv64f/I-FSW-01", "2000",
"rv64f/I-FCLASS-S-01", "2000",
"rv64f/I-FADD-S-01", "2000",
// "rv64f/I-FCVT-S-L-01", "2000",
// "rv64f/I-FCVT-S-LU-01", "2000",
// "rv64f/I-FCVT-S-W-01", "2000",
// "rv64f/I-FCVT-S-WU-01", "2000",
"rv64f/I-FCVT-L-S-01", "2000",
"rv64f/I-FCVT-LU-S-01", "2000",
"rv64f/I-FCVT-W-S-01", "2000",
"rv64f/I-FCVT-WU-S-01", "2000",
"rv64f/I-FDIV-S-01", "2000",
"rv64f/I-FEQ-S-01", "2000",
"rv64f/I-FLE-S-01", "2000",
"rv64f/I-FLT-S-01", "2000",
"rv64f/I-FMADD-S-01", "2000",
"rv64f/I-FMAX-S-01", "2000",
"rv64f/I-FMIN-S-01", "2000",
"rv64f/I-FMSUB-S-01", "2000",
"rv64f/I-FMUL-S-01", "2000",
"rv64f/I-FNMADD-S-01", "2000",
"rv64f/I-FNMSUB-S-01", "2000",
"rv64f/I-FSGNJ-S-01", "2000",
"rv64f/I-FSGNJN-S-01", "2000",
"rv64f/I-FSGNJX-S-01", "2000",
"rv64f/I-FSQRT-S-01", "2000",
"rv64f/I-FSUB-S-01", "2000"
};
string tests64d[] = '{
"rv64d/I-FSD-01", "2000",
"rv64d/I-FLD-01", "2420",
"rv64d/I-FMV-X-D-01", "2000",
"rv64d/I-FMV-D-X-01", "2000",
"rv64d/I-FDIV-D-01", "2000",
"rv64d/I-FNMADD-D-01", "2000",
"rv64d/I-FNMSUB-D-01", "2000",
"rv64d/I-FMSUB-D-01", "2000",
"rv64d/I-FMAX-D-01", "2000",
"rv64d/I-FMIN-D-01", "2000",
"rv64d/I-FLE-D-01", "2000",
"rv64d/I-FLT-D-01", "2000",
"rv64d/I-FEQ-D-01", "2000",
"rv64d/I-FADD-D-01", "2000",
"rv64d/I-FCLASS-D-01", "2000",
"rv64d/I-FMADD-D-01", "2000",
"rv64d/I-FMUL-D-01", "2000",
"rv64d/I-FSGNJ-D-01", "2000",
"rv64d/I-FSGNJN-D-01", "2000",
"rv64d/I-FSGNJX-D-01", "2000",
"rv64d/I-FSQRT-D-01", "2000",
"rv64d/I-FSUB-D-01", "2000",
// "rv64d/I-FCVT-D-L-01", "2000",
// "rv64d/I-FCVT-D-LU-01", "2000",
"rv64d/I-FCVT-D-S-01", "2000",
// "rv64d/I-FCVT-D-W-01", "2000",
// "rv64d/I-FCVT-D-WU-01", "2000",
"rv64d/I-FCVT-L-D-01", "2000",
"rv64d/I-FCVT-LU-D-01", "2000",
"rv64d/I-FCVT-S-D-01", "2000",
"rv64d/I-FCVT-W-D-01", "2000",
"rv64d/I-FCVT-WU-D-01", "2000"
};
string tests64a[] = '{
"rv64a/WALLY-AMO", "2110",
"rv64a/WALLY-LRSC", "2110"
};
string tests64m[] = '{
"rv64m/I-MUL-01", "3000",
"rv64m/I-MULH-01", "3000",
"rv64m/I-MULHSU-01", "3000",
"rv64m/I-MULHU-01", "3000",
"rv64m/I-MULW-01", "3000",
"rv64m/I-DIV-01", "3000",
"rv64m/I-DIVU-01", "3000",
"rv64m/I-DIVUW-01", "3000",
"rv64m/I-DIVW-01", "3000",
"rv64m/I-REM-01", "3000",
"rv64m/I-REMU-01", "3000",
"rv64m/I-REMUW-01", "3000",
"rv64m/I-REMW-01", "3000"
};
string tests64ic[] = '{
"rv64ic/I-C-ADD-01", "3000",
"rv64ic/I-C-ADDI-01", "3000",
"rv64ic/I-C-ADDIW-01", "3000",
"rv64ic/I-C-ADDW-01", "3000",
"rv64ic/I-C-AND-01", "3000",
"rv64ic/I-C-ANDI-01", "3000",
"rv64ic/I-C-BEQZ-01", "3000",
"rv64ic/I-C-BNEZ-01", "3000",
"rv64ic/I-C-EBREAK-01", "2000",
"rv64ic/I-C-J-01", "3000",
"rv64ic/I-C-JALR-01", "4000",
"rv64ic/I-C-JR-01", "4000",
"rv64ic/I-C-LD-01", "3420",
"rv64ic/I-C-LDSP-01", "3420",
"rv64ic/I-C-LI-01", "3000",
"rv64ic/I-C-LUI-01", "2000",
"rv64ic/I-C-LW-01", "3110",
"rv64ic/I-C-LWSP-01", "3110",
"rv64ic/I-C-MV-01", "3000",
"rv64ic/I-C-NOP-01", "2000",
"rv64ic/I-C-OR-01", "3000",
"rv64ic/I-C-SD-01", "3000",
"rv64ic/I-C-SDSP-01", "3000",
"rv64ic/I-C-SLLI-01", "3000",
"rv64ic/I-C-SRAI-01", "3000",
"rv64ic/I-C-SRLI-01", "3000",
"rv64ic/I-C-SUB-01", "3000",
"rv64ic/I-C-SUBW-01", "3000",
"rv64ic/I-C-SW-01", "3000",
"rv64ic/I-C-SWSP-01", "3000",
"rv64ic/I-C-XOR-01", "3000"
};
string tests64iNOc[] = {
"rv64i/I-MISALIGN_JMP-01","2000"
};
string tests64i[] = '{
//"rv64i/WALLY-PIPELINE-100K", "f7ff0",
"rv64i/I-ADD-01", "3000",
"rv64i/I-ADDI-01", "3000",
"rv64i/I-ADDIW-01", "3000",
"rv64i/I-ADDW-01", "3000",
"rv64i/I-AND-01", "3000",
"rv64i/I-ANDI-01", "3000",
"rv64i/I-AUIPC-01", "3000",
"rv64i/I-BEQ-01", "4000",
"rv64i/I-BGE-01", "4000",
"rv64i/I-BGEU-01", "4000",
"rv64i/I-BLT-01", "4000",
"rv64i/I-BLTU-01", "4000",
"rv64i/I-BNE-01", "4000",
"rv64i/I-DELAY_SLOTS-01", "2000",
"rv64i/I-EBREAK-01", "2000",
"rv64i/I-ECALL-01", "2000",
"rv64i/I-ENDIANESS-01", "2010",
"rv64i/I-IO-01", "2050",
"rv64i/I-JAL-01", "3000",
"rv64i/I-JALR-01", "4000",
"rv64i/I-LB-01", "4020",
"rv64i/I-LBU-01", "4020",
"rv64i/I-LD-01", "4420",
"rv64i/I-LH-01", "4050",
"rv64i/I-LHU-01", "4050",
"rv64i/I-LUI-01", "2000",
"rv64i/I-LW-01", "4110",
"rv64i/I-LWU-01", "4110",
"rv64i/I-MISALIGN_LDST-01", "2010",
"rv64i/I-NOP-01", "2000",
"rv64i/I-OR-01", "3000",
"rv64i/I-ORI-01", "3000",
"rv64i/I-RF_size-01", "2000",
"rv64i/I-RF_width-01", "2000",
"rv64i/I-RF_x0-01", "2010",
"rv64i/I-SB-01", "4000",
"rv64i/I-SD-01", "4000",
"rv64i/I-SH-01", "4000",
"rv64i/I-SLL-01", "3000",
"rv64i/I-SLLI-01", "3000",
"rv64i/I-SLLIW-01", "3000",
"rv64i/I-SLLW-01", "3000",
"rv64i/I-SLT-01", "3000",
"rv64i/I-SLTI-01", "3000",
"rv64i/I-SLTIU-01", "3000",
"rv64i/I-SLTU-01", "3000",
"rv64i/I-SRA-01", "3000",
"rv64i/I-SRAI-01", "3000",
"rv64i/I-SRAIW-01", "3000",
"rv64i/I-SRAW-01", "3000",
"rv64i/I-SRL-01", "3000",
"rv64i/I-SRLI-01", "3000",
"rv64i/I-SRLIW-01", "3000",
"rv64i/I-SRLW-01", "3000",
"rv64i/I-SUB-01", "3000",
"rv64i/I-SUBW-01", "3000",
"rv64i/I-SW-01", "4000",
"rv64i/I-XOR-01", "3000",
"rv64i/I-XORI-01", "3000",
"rv64i/WALLY-ADD", "4000",
"rv64i/WALLY-SUB", "4000",
"rv64i/WALLY-ADDI", "3000",
"rv64i/WALLY-ANDI", "3000",
"rv64i/WALLY-ORI", "3000",
"rv64i/WALLY-XORI", "3000",
"rv64i/WALLY-SLTI", "3000",
"rv64i/WALLY-SLTIU", "3000",
"rv64i/WALLY-SLLI", "3000",
"rv64i/WALLY-SRLI", "3000",
"rv64i/WALLY-SRAI", "3000",
"rv64i/WALLY-JAL", "4000",
"rv64i/WALLY-JALR", "3000",
"rv64i/WALLY-STORE", "3000",
"rv64i/WALLY-ADDIW", "3000",
"rv64i/WALLY-SLLIW", "3000",
"rv64i/WALLY-SRLIW", "3000",
"rv64i/WALLY-SRAIW", "3000",
"rv64i/WALLY-ADDW", "4000",
"rv64i/WALLY-SUBW", "4000",
"rv64i/WALLY-SLLW", "3000",
"rv64i/WALLY-SRLW", "3000",
"rv64i/WALLY-SRAW", "3000",
"rv64i/WALLY-BEQ" ,"5000",
"rv64i/WALLY-BNE", "5000 ",
"rv64i/WALLY-BLTU", "5000 ",
"rv64i/WALLY-BLT", "5000",
"rv64i/WALLY-BGE", "5000 ",
"rv64i/WALLY-BGEU", "5000 ",
"rv64i/WALLY-CSRRW", "4000",
"rv64i/WALLY-CSRRS", "4000",
"rv64i/WALLY-CSRRC", "5000",
"rv64i/WALLY-CSRRWI", "4000",
"rv64i/WALLY-CSRRSI", "4000",
"rv64i/WALLY-CSRRCI", "4000"
};
string tests32a[] = '{
"rv32a/WALLY-AMO", "2110",
"rv32a/WALLY-LRSC", "2110"
};
string tests32m[] = '{
"rv32m/I-MUL-01", "2000",
"rv32m/I-MULH-01", "2000",
"rv32m/I-MULHSU-01", "2000",
"rv32m/I-MULHU-01", "2000",
"rv32m/I-DIV-01", "2000",
"rv32m/I-DIVU-01", "2000",
"rv32m/I-REM-01", "2000",
"rv32m/I-REMU-01", "2000"
};
string tests32ic[] = '{
"rv32ic/I-C-ADD-01", "2000",
"rv32ic/I-C-ADDI-01", "2000",
"rv32ic/I-C-AND-01", "2000",
"rv32ic/I-C-ANDI-01", "2000",
"rv32ic/I-C-BEQZ-01", "2000",
"rv32ic/I-C-BNEZ-01", "2000",
"rv32ic/I-C-EBREAK-01", "2000",
"rv32ic/I-C-J-01", "2000",
"rv32ic/I-C-JALR-01", "3000",
"rv32ic/I-C-JR-01", "3000",
"rv32ic/I-C-LI-01", "2000",
"rv32ic/I-C-LUI-01", "2000",
"rv32ic/I-C-LW-01", "2110",
"rv32ic/I-C-LWSP-01", "2110",
"rv32ic/I-C-MV-01", "2000",
"rv32ic/I-C-NOP-01", "2000",
"rv32ic/I-C-OR-01", "2000",
"rv32ic/I-C-SLLI-01", "2000",
"rv32ic/I-C-SRAI-01", "2000",
"rv32ic/I-C-SRLI-01", "2000",
"rv32ic/I-C-SUB-01", "2000",
"rv32ic/I-C-SW-01", "2000",
"rv32ic/I-C-SWSP-01", "2000",
"rv32ic/I-C-XOR-01", "2000"
};
string tests32iNOc[] = {
"rv32i/I-MISALIGN_JMP-01","2000"
};
string tests32i[] = {
//"rv32i/WALLY-PIPELINE-100K", "10a800",
"rv32i/I-ADD-01", "2000",
"rv32i/I-ADDI-01","2000",
"rv32i/I-AND-01","2000",
"rv32i/I-ANDI-01","2000",
"rv32i/I-AUIPC-01","2000",
"rv32i/I-BEQ-01","3000",
"rv32i/I-BGE-01","3000",
"rv32i/I-BGEU-01","3000",
"rv32i/I-BLT-01","3000",
"rv32i/I-BLTU-01","3000",
"rv32i/I-BNE-01","3000",
"rv32i/I-DELAY_SLOTS-01","2000",
"rv32i/I-EBREAK-01","2000",
"rv32i/I-ECALL-01","2000",
"rv32i/I-ENDIANESS-01","2010",
"rv32i/I-IO-01","2030rv",
"rv32i/I-JAL-01","3000",
"rv32i/I-JALR-01","3000",
"rv32i/I-LB-01","3020",
"rv32i/I-LBU-01","3020",
"rv32i/I-LH-01","3050",
"rv32i/I-LHU-01","3050",
"rv32i/I-LUI-01","2000",
"rv32i/I-LW-01","3110",
"rv32i/I-MISALIGN_LDST-01","2010",
"rv32i/I-NOP-01","2000",
"rv32i/I-OR-01","2000",
"rv32i/I-ORI-01","2000",
"rv32i/I-RF_size-01","2000",
"rv32i/I-RF_width-01","2000",
"rv32i/I-RF_x0-01","2010",
"rv32i/I-SB-01","3000",
"rv32i/I-SH-01","3000",
"rv32i/I-SLL-01","2000",
"rv32i/I-SLLI-01","2000",
"rv32i/I-SLT-01","2000",
"rv32i/I-SLTI-01","2000",
"rv32i/I-SLTIU-01","2000",
"rv32i/I-SLTU-01","2000",
"rv32i/I-SRA-01","2000",
"rv32i/I-SRAI-01","2000",
"rv32i/I-SRL-01","2000",
"rv32i/I-SRLI-01","2000",
"rv32i/I-SUB-01","2000",
"rv32i/I-SW-01","3000",
"rv32i/I-XOR-01","2000",
"rv32i/I-XORI-01","2000",
"rv32i/WALLY-ADD", "3000",
"rv32i/WALLY-SUB", "3000",
"rv32i/WALLY-ADDI", "2000",
"rv32i/WALLY-ANDI", "2000",
"rv32i/WALLY-ORI", "2000",
"rv32i/WALLY-XORI", "2000",
"rv32i/WALLY-SLTI", "2000",
"rv32i/WALLY-SLTIU", "2000",
"rv32i/WALLY-SLLI", "2000",
"rv32i/WALLY-SRLI", "2000",
"rv32i/WALLY-SRAI", "2000",
"rv32i/WALLY-LOAD", "11c00",
"rv32i/WALLY-SUB", "3000",
"rv32i/WALLY-STORE", "2000",
"rv32i/WALLY-JAL", "3000",
"rv32i/WALLY-JALR", "2000",
"rv32i/WALLY-BEQ" ,"4000",
"rv32i/WALLY-BNE", "4000 ",
"rv32i/WALLY-BLTU", "4000 ",
"rv32i/WALLY-BLT", "4000",
"rv32i/WALLY-BGE", "4000 ",
"rv32i/WALLY-BGEU", "4000 ",
"rv32i/WALLY-CSRRW", "3000",
"rv32i/WALLY-CSRRS", "3000",
"rv32i/WALLY-CSRRC", "4000",
"rv32i/WALLY-CSRRWI", "3000",
"rv32i/WALLY-CSRRSI", "3000",
"rv32i/WALLY-CSRRCI", "3000"
};
string testsBP64[] = '{
"rv64BP/blink-led", "10000"
/* -----\/----- EXCLUDED -----\/-----
"rv64BP/simple", "10000",
"rv64BP/mmm", "1000000",
"rv64BP/linpack_bench", "1000000",
"rv64BP/sieve", "1000000",
"rv64BP/qsort", "1000000",
"rv64BP/dhrystone", "1000000"
-----/\----- EXCLUDED -----/\----- */
};
string tests64p[] = '{
"rv64p/WALLY-MSTATUS", "2000",
"rv64p/WALLY-MCAUSE", "3000",
"rv64p/WALLY-SCAUSE", "2000",
"rv64p/WALLY-MEPC", "5000",
"rv64p/WALLY-SEPC", "4000",
"rv64p/WALLY-MTVAL", "6000",
"rv64p/WALLY-STVAL", "4000",
"rv64p/WALLY-MTVEC", "2000",
"rv64p/WALLY-STVEC", "2000",
"rv64p/WALLY-MARCHID", "4000",
"rv64p/WALLY-MIMPID", "4000",
"rv64p/WALLY-MHARTID", "4000",
"rv64p/WALLY-MVENDORID", "4000",
"rv64p/WALLY-MIE", "3000",
"rv64p/WALLY-MEDELEG", "4000",
"rv64p/WALLY-IP", "2000",
"rv64p/WALLY-CSR-PERMISSIONS-M", "5000",
"rv64p/WALLY-CSR-PERMISSIONS-S", "3000"
};
string tests32p[] = '{
"rv32p/WALLY-MSTATUS", "2000",
"rv32p/WALLY-MCAUSE", "3000",
"rv32p/WALLY-SCAUSE", "2000",
"rv32p/WALLY-MEPC", "5000",
"rv32p/WALLY-SEPC", "4000",
"rv32p/WALLY-MTVAL", "5000",
"rv32p/WALLY-STVAL", "4000",
"rv32p/WALLY-MARCHID", "4000",
"rv32p/WALLY-MIMPID", "4000",
"rv32p/WALLY-MHARTID", "4000",
"rv32p/WALLY-MVENDORID", "4000",
"rv32p/WALLY-MTVEC", "2000",
"rv32p/WALLY-STVEC", "2000",
"rv32p/WALLY-MIE", "3000",
"rv32p/WALLY-MEDELEG", "4000",
"rv32p/WALLY-IP", "3000",
"rv32p/WALLY-CSR-PERMISSIONS-M", "5000",
"rv32p/WALLY-CSR-PERMISSIONS-S", "3000"
};
string tests64periph[] = '{
"rv64i-periph/WALLY-PERIPH", "2000"
};
string tests32periph[] = '{
"rv32i-periph/WALLY-PLIC", "2080"
};
string tests[];
string ProgramAddrMapFile, ProgramLabelMapFile;
logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic [31:0] HADDR;
logic [`AHBW-1:0] HWDATA;
logic HWRITE;
logic [2:0] HSIZE;
logic [2:0] HBURST;
logic [3:0] HPROT;
logic [1:0] HTRANS;
logic HMASTLOCK;
logic HCLK, HRESETn;
logic [`XLEN-1:0] PCW;
logic DCacheFlushDone, DCacheFlushStart;
flopenr #(`XLEN) PCWReg(clk, reset, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.InstrM, InstrW);
// check assertions for a legal configuration
riscvassertions riscvassertions();
logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS);
// pick tests based on modes supported
initial begin
if (`XLEN == 64) begin // RV64
if (`TESTSBP) begin
tests = testsBP64;
// testsbp should not run the other tests. It starts at address 0 rather than
// 0x8000_0000, the next if must remain an else if.
end else if (TESTSPERIPH)
tests = tests64periph;
else if (TESTSPRIV)
tests = tests64p;
else begin
tests = {tests64p,tests64i, tests64periph};
if (`C_SUPPORTED) tests = {tests, tests64ic};
else tests = {tests, tests64iNOc};
if (`M_SUPPORTED) tests = {tests, tests64m};
if (`F_SUPPORTED) tests = {tests64f, tests};
if (`D_SUPPORTED) tests = {tests64d, tests};
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
if (`A_SUPPORTED) tests = {tests64a, tests};
end
//tests = {tests64a, tests};
end else begin // RV32
// *** add the 32 bit bp tests
if (TESTSPERIPH)
tests = tests32periph;
else if (TESTSPRIV)
tests = tests32p;
else begin
tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
else tests = {tests, tests32iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
if (`F_SUPPORTED) tests = {tests32f, tests};
if (`MEM_VIRTMEM) tests = {tests32mmu, tests};
if (`A_SUPPORTED) tests = {tests32a, tests};
end
end
end
string signame, memfilename, romfilename;
logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
logic UARTSin, UARTSout;
// instantiate device to be tested
assign GPIOPinsIn = 0;
assign UARTSin = 1;
assign HREADYEXT = 1;
assign HRESPEXT = 0;
assign HRDATAEXT = 0;
wallypipelinedsoc dut(.*);
// Track names of instructions
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.icache.FinalInstrRawF,
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests
localparam integer MemStartAddr = `TIM_BASE>>(1+`XLEN/32);
localparam integer MemEndAddr = (`TIM_RANGE+`TIM_BASE)>>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;
// *** broken because DTIM also drives RAM
/* -----\/----- EXCLUDED -----\/-----
if (`TESTSBP) begin
for (i=MemStartAddr; i<MemEndAddr; i = i+1) begin
dut.uncore.dtim.RAM[i] = meminit;
end
end
-----/\----- EXCLUDED -----/\----- */
// read test vectors into memory
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
romfilename = {"../../imperas-riscv-tests/work/rv64BP/blink-led.memfile"};
$readmemh(memfilename, dut.uncore.dtim.RAM);
$readmemh(romfilename, dut.uncore.bootdtim.bootdtim.RAM);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
$display("Read memfile %s", memfilename);
reset = 1; # 42; reset = 0;
end
// generate clock to sequence tests
always
begin
clk = 1; # 5; clk = 0; # 5;
end
// check results
always @(negedge clk)
begin
/* -----\/----- EXCLUDED -----\/-----
if (dut.hart.priv.EcallFaultM &&
(dut.hart.ieu.dp.regf.rf[3] == 1 ||
(dut.hart.ieu.dp.regf.we3 &&
dut.hart.ieu.dp.regf.a3 == 3 &&
dut.hart.ieu.dp.regf.wd3 == 1))) begin
-----/\----- EXCLUDED -----/\----- */
if (DCacheFlushDone) begin
//$display("Code ended with ecall with gp = 1");
#600; // give time for instructions in pipeline to finish
// clear signature to prevent contamination from previous tests
for(i=0; i<SIGNATURESIZE; i=i+1) begin
sig32[i] = 'bx;
end
// read signature, reformat in 64 bits if necessary
signame = {"../../imperas-riscv-tests/work/", tests[test], ".signature.output"};
$readmemh(signame, sig32);
i = 0;
while (i < SIGNATURESIZE) begin
if (`XLEN == 32) begin
signature[i] = sig32[i];
i = i+1;
end else begin
signature[i/2] = {sig32[i+1], sig32[i]};
i = i + 2;
end
if (sig32[i-1] === 'bx) begin
if (i == 1) begin
i = SIGNATURESIZE+1; // flag empty file
$display(" Error: empty test file");
end else i = SIGNATURESIZE; // skip over the rest of the x's for efficiency
end
end
// Check errors
errors = (i == SIGNATURESIZE+1); // error if file is empty
i = 0;
testadr = (`TIM_BASE+tests[test+1].atohex())/(`XLEN/8);
/* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin
//$display("signature[%h] = %h", i, signature[i]);
if (signature[i] !== dut.uncore.dtim.RAM[testadr+i] &&
(signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin
if (signature[i+4] !== 'bx || signature[i] !== 32'hFFFFFFFF) begin
// report errors unless they are garbage at the end of the sim
// kind of hacky test for garbage right now
errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (TIM) = %h, signature = %h",
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], dut.uncore.dtim.RAM[testadr+i], signature[i]);
$stop;//***debug
end
end
i = i + 1;
end
/* verilator lint_on INFINITELOOP */
if (errors == 0) begin
$display("%s succeeded. Brilliant!!!", tests[test]);
end
else begin
$display("%s failed with %d errors. :(", tests[test], errors);
totalerrors = totalerrors+1;
end
test = test + 2;
if (test == tests.size()) begin
if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
else $display("FAIL: %d test programs had errors", totalerrors);
$stop;
end
else begin
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.uncore.dtim.RAM);
$display("Read memfile %s", memfilename);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
reset = 1; # 17; reset = 0;
end
end
end // always @ (negedge clk)
// track the current function or global label
if (DEBUG == 1) begin : FunctionName
FunctionName FunctionName(.reset(reset),
.clk(clk),
.ProgramAddrMapFile(ProgramAddrMapFile),
.ProgramLabelMapFile(ProgramLabelMapFile));
end
assign DCacheFlushStart = dut.hart.priv.EcallFaultM &&
(dut.hart.ieu.dp.regf.rf[3] == 1 ||
(dut.hart.ieu.dp.regf.we3 &&
dut.hart.ieu.dp.regf.a3 == 3 &&
dut.hart.ieu.dp.regf.wd3 == 1));
DCacheFlushFSM DCacheFlushFSM(.clk(clk),
.reset(reset),
.start(DCacheFlushStart),
.done(DCacheFlushDone));
generate
// initialize the branch predictor
if (`BPRED_ENABLED == 1) begin : bpred
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
end
end
endgenerate
endmodule
module riscvassertions();
// Legal number of PMP entries are 0, 16, or 64
initial begin
assert (`PMP_ENTRIES == 0 || `PMP_ENTRIES==16 || `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64");
assert (`F_SUPPORTED || ~`D_SUPPORTED) else $error("Can't support double without supporting float");
assert (`XLEN == 64 || ~`D_SUPPORTED) else $error("Wally does not yet support D extensions on RV32");
assert (`DCACHE_WAYSIZEINBYTES <= 4096 || `MEM_DCACHE == 0 || `MEM_VIRTMEM == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`DCACHE_BLOCKLENINBITS >= 128 || `MEM_DCACHE == 0) else $error("DCACHE_BLOCKLENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_BLOCKLENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_BLOCKLENINBITS must be smaller than way size");
assert (`ICACHE_WAYSIZEINBYTES <= 4096 || `MEM_ICACHE == 0 || `MEM_VIRTMEM == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`ICACHE_BLOCKLENINBITS >= 32 || `MEM_ICACHE == 0) else $error("ICACHE_BLOCKLENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_BLOCKLENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_BLOCKLENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_BLOCKLENINBITS) == `DCACHE_BLOCKLENINBITS) else $error("DCACHE_BLOCKLENINBITS must be a power of 2");
assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS) else $error("ICACHE_BLOCKLENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
assert (`ICACHE_NUMWAYS == 1 || `MEM_ICACHE == 0) else $warning("Multiple Instruction Cache ways not yet implemented");
assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES) else $error("ITLB_ENTRIES must be a power of 2");
assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES) else $error("DTLB_ENTRIES must be a power of 2");
assert (`TIM_RANGE >= 56'h07FFFFFF) else $error("Some regression tests will fail if TIM_RANGE is less than 56'h07FFFFFF");
end
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
module DCacheFlushFSM
(input logic clk,
input logic reset,
input logic start,
output logic done);
localparam integer numlines = testbench.dut.hart.lsu.dcache.NUMLINES;
localparam integer numways = testbench.dut.hart.lsu.dcache.NUMWAYS;
localparam integer blockbytelen = testbench.dut.hart.lsu.dcache.BLOCKBYTELEN;
localparam integer numwords = testbench.dut.hart.lsu.dcache.BLOCKLEN/`XLEN;
localparam integer lognumlines = $clog2(numlines);
localparam integer logblockbytelen = $clog2(blockbytelen);
localparam integer lognumways = $clog2(numways);
localparam integer tagstart = lognumlines + logblockbytelen;
genvar index, way, cacheWord;
logic [`XLEN-1:0] CacheData [numways-1:0] [numlines-1:0] [numwords-1:0];
logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [numwords-1:0];
logic CacheValid [numways-1:0] [numlines-1:0] [numwords-1:0];
logic CacheDirty [numways-1:0] [numlines-1:0] [numwords-1:0];
logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [numwords-1:0];
genvar adr;
logic [`XLEN-1:0] ShadowRAM[`TIM_BASE>>(1+`XLEN/32):(`TIM_RANGE+`TIM_BASE)>>1+(`XLEN/32)];
generate
for(index = 0; index < numlines; index++) begin
for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < numwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart),
.logblockbytelen(logblockbytelen))
copyShadow(.clk,
.start,
.tag(testbench.dut.hart.lsu.dcache.MemWay[way].CacheTagMem.StoredData[index]),
.valid(testbench.dut.hart.lsu.dcache.MemWay[way].ValidBits[index]),
.dirty(testbench.dut.hart.lsu.dcache.MemWay[way].DirtyBits[index]),
.data(testbench.dut.hart.lsu.dcache.MemWay[way].word[cacheWord].CacheDataMem.StoredData[index]),
.index(index),
.cacheWord(cacheWord),
.CacheData(CacheData[way][index][cacheWord]),
.CacheAdr(CacheAdr[way][index][cacheWord]),
.CacheTag(CacheTag[way][index][cacheWord]),
.CacheValid(CacheValid[way][index][cacheWord]),
.CacheDirty(CacheDirty[way][index][cacheWord]));
end
end
end
endgenerate
integer i, j, k;
always @(posedge clk) begin
if (start) begin #1
#1
for(i = 0; i < numlines; i++) begin
for(j = 0; j < numways; j++) begin
for(k = 0; k < numwords; k++) begin
if (CacheValid[j][i][k] && CacheDirty[j][i][k]) begin
ShadowRAM[CacheAdr[j][i][k] >> $clog2(`XLEN/8)] = CacheData[j][i][k];
end
end
end
end
end
end
flop #(1) doneReg(.clk(clk),
.d(start),
.q(done));
endmodule
module copyShadow
#(parameter tagstart, logblockbytelen)
(input logic clk,
input logic start,
input logic [`PA_BITS-1:tagstart] tag,
input logic valid, dirty,
input logic [`XLEN-1:0] data,
input logic [32-1:0] index,
input logic [32-1:0] cacheWord,
output logic [`XLEN-1:0] CacheData,
output logic [`PA_BITS-1:0] CacheAdr,
output logic [`XLEN-1:0] CacheTag,
output logic CacheValid,
output logic CacheDirty);
always_ff @(posedge clk) begin
if(start) begin
CacheTag = tag;
CacheValid = valid;
CacheDirty = dirty;
CacheData = data;
CacheAdr = (tag << tagstart) + (index << logblockbytelen) + (cacheWord << $clog2(`XLEN/8));
end
end
endmodule