diff --git a/testsBP/fpga-blink-led/Makefile b/testsBP/fpga-blink-led/Makefile new file mode 100644 index 000000000..df7544416 --- /dev/null +++ b/testsBP/fpga-blink-led/Makefile @@ -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/ diff --git a/testsBP/fpga-blink-led/blink-led.s b/testsBP/fpga-blink-led/blink-led.s new file mode 100644 index 000000000..f3a5d66b7 --- /dev/null +++ b/testsBP/fpga-blink-led/blink-led.s @@ -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 + + + diff --git a/testsBP/linker1000.x b/testsBP/linker1000.x new file mode 100644 index 000000000..4156c6571 --- /dev/null +++ b/testsBP/linker1000.x @@ -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_*) } +} diff --git a/wally-pipelined/regression/wally-arch.do b/wally-pipelined/regression/wally-arch.do index bfa93c254..2eb08b91e 100644 --- a/wally-pipelined/regression/wally-arch.do +++ b/wally-pipelined/regression/wally-arch.do @@ -17,10 +17,10 @@ onbreak {resume} # create library -if [file exists work-arch] { - vdel -all +if [file exists work_arch_$2] { + vdel -lib work_arch_$2 -all } -vlib work-arch +vlib work_arch_$2 # compile source files # 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: # do wally-pipelined.do ../config/rv32ic switch $argc { - 0 {vlog +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} + 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 -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 # remove +acc flag for faster sim during regressions if there is no need to access internal signals -vopt +acc work-arch.testbench -o workopt -vsim workopt +vopt +acc work_arch_$2.testbench -work work_arch_$2 -o workopt_arch +vsim -lib work_arch_$2 workopt_arch view wave -- display input and output signals as hexidecimal values diff --git a/wally-pipelined/src/fpu/fpudivsqrtrecur.sv b/wally-pipelined/src/fpu/fpudivsqrtrecur.sv new file mode 100644 index 000000000..0d1b89ff2 --- /dev/null +++ b/wally-pipelined/src/fpu/fpudivsqrtrecur.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/fpu/fpudivsqrtrecurcore.sv b/wally-pipelined/src/fpu/fpudivsqrtrecurcore.sv new file mode 100644 index 000000000..3f6fe67d9 --- /dev/null +++ b/wally-pipelined/src/fpu/fpudivsqrtrecurcore.sv @@ -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 + + + diff --git a/wally-pipelined/src/muldiv/intdiv_restoring.sv b/wally-pipelined/src/muldiv/intdiv_restoring.sv new file mode 100644 index 000000000..9571ba721 --- /dev/null +++ b/wally-pipelined/src/muldiv/intdiv_restoring.sv @@ -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 + + diff --git a/wally-pipelined/src/muldiv/muldiv.sv b/wally-pipelined/src/muldiv/muldiv.sv index 7288229c5..714f7ebe7 100644 --- a/wally-pipelined/src/muldiv/muldiv.sv +++ b/wally-pipelined/src/muldiv/muldiv.sv @@ -51,7 +51,7 @@ module muldiv ( logic enable_q; logic [2:0] Funct3E_Q; - logic div0error; + logic div0error; // ***unused logic [`XLEN-1:0] N, D; 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]); 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 assign startDivideE = MulDivE&DivStartE&~DivBusyE; // capture the start control signals since they are not held constant. + // *** appears to be unused flopenrc #(3) funct3ereg (.d(Funct3E), .q(Funct3E_Q), .en(DivStartE), @@ -114,7 +116,7 @@ module muldiv ( 3'b111: PrelimResultE = RemE; endcase // case (Funct3E) - // Start Divide process + // Start Divide process. This simplifies to DivStartE = Funct3E[2]; always_comb case (Funct3E) 3'b000: DivStartE = 1'b0; diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index 23d580880..bf688d1bb 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -79,6 +79,7 @@ module uartPC16550D( logic [9:0] rxshiftreg; logic [10:0] rxfifo[15:0]; logic [7:0] txfifo[15:0]; + logic [4:0] rxfifotailunwrapped; logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel; logic [3:0] rxfifoentries, txfifoentries; logic [3:0] rxbitsexpected, txbitsexpected; @@ -95,6 +96,7 @@ module uartPC16550D( logic [8:0] rxdata9; logic [7:0] rxdata; logic [15:0] RXerrbit, rxfullbit; + logic [31:0] rxfullbitunwrapped; // transmit data logic [7:0] TXHR, nexttxdata; @@ -289,14 +291,21 @@ module uartPC16550D( // detect any errors in rx fifo // 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 + assign rxfifotailunwrapped = rxfifotail < rxfifohead ? {1'b1, rxfifotail} : {1'b0, rxfifotail}; 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 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); else - assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i); + assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/ end endgenerate assign rxfifohaserr = |(RXerrbit & rxfullbit); diff --git a/wally-pipelined/testbench/testbench-arch.sv b/wally-pipelined/testbench/testbench-arch.sv index f200c7189..93d981754 100644 --- a/wally-pipelined/testbench/testbench-arch.sv +++ b/wally-pipelined/testbench/testbench-arch.sv @@ -160,6 +160,28 @@ string tests32f[] = '{ "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[] = '{ "rv64i_m/M/div-01", "9010", "rv64i_m/M/divu-01", "a010", @@ -212,10 +234,6 @@ string tests32f[] = '{ "rv64i_m/C/cxor-01", "8010" }; - string tests64iNOc[] = { - "rv64i/I-MISALIGN_JMP-01","2000" - }; - string tests64i[] = '{ "rv64i_m/I/add-01", "9010", "rv64i_m/I/addi-01", "6010", @@ -269,189 +287,106 @@ string tests32f[] = '{ "rv64i_m/I/xori-01", "6010" }; - string tests32a[] = '{ - "rv32a/WALLY-AMO", "2110", - "rv32a/WALLY-LRSC", "2110" - }; + string tests32priv[] = '{ + "rv32i_m/privilege/ebreak", "2090", + "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[] = '{ - "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" - }; + "rv32i_m/M/div-01", "9010", + "rv32i_m/M/divu-01", "a010", + "rv32i_m/M/mul-01", "9010", + "rv32i_m/M/mulh-01", "9010", + "rv32i_m/M/mulhsu-01", "9010", + "rv32i_m/M/mulhu-01", "a010", + "rv32i_m/M/rem-01", "9010", + "rv32i_m/M/remu-01", "a010", + }; 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" + "rv32i_m/C/cadd-01", "8010", + "rv32i_m/C/caddi-01", "4010", + "rv32i_m/C/caddi16sp-01", "2010", + "rv32i_m/C/caddi4spn-01", "2010", + "rv32i_m/C/cand-01", "8010", + "rv32i_m/C/candi-01", "4010", + "rv32i_m/C/cbeqz-01", "4010", + "rv32i_m/C/cbnez-01", "5010", + "rv32i_m/C/cebreak-01", "2070", + "rv32i_m/C/cj-01", "3010", + "rv32i_m/C/cjal-01", "", + "rv32i_m/C/cjalr-01", "2010", + "rv32i_m/C/cjr-01", "2010", + "rv32i_m/C/cli-01", "2010", + "rv32i_m/C/clui-01", "2010", + "rv32i_m/C/clw-01", "2010", + "rv32i_m/C/clwsp-01", "2010", + "rv32i_m/C/cmv-01", "2010", + "rv32i_m/C/cnop-01", "2010", + "rv32i_m/C/cor-01", "8010", + "rv32i_m/C/cslli-01", "2010", + "rv32i_m/C/csrai-01", "2010", + "rv32i_m/C/csrli-01", "2010", + "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[] = { - "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/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 tests32i[] = '{ + "rv32i_m/I/add-01", "9010", + "rv32i_m/I/addi-01", "6010", + "rv32i_m/I/and-01", "9010", + "rv32i_m/I/andi-01", "6010", + "rv32i_m/I/auipc-01", "2010", + "rv32i_m/I/beq-01", "47010", + "rv32i_m/I/bge-01", "47010", + "rv32i_m/I/bgeu-01", "56010", + "rv32i_m/I/blt-01", "4d010", + "rv32i_m/I/bltu-01", "57010", + "rv32i_m/I/bne-01", "43010", + "rv32i_m/I/fence-01", "2010", + "rv32i_m/I/jal-01", "122010", + "rv32i_m/I/jalr-01", "2010", + "rv32i_m/I/lb-align-01", "2010", + "rv32i_m/I/lbu-align-01", "2010", + "rv32i_m/I/lh-align-01", "2010", + "rv32i_m/I/lhu-align-01", "2010", + "rv32i_m/I/lui-01", "2010", + "rv32i_m/I/lw-align-01", "2010", + "rv32i_m/I/or-01", "9010", + "rv32i_m/I/ori-01", "6010", + "rv32i_m/I/sb-align-01", "3010", + "rv32i_m/I/sh-align-01", "3010", + "rv32i_m/I/sll-01", "3010", + "rv32i_m/I/slli-01", "2010", + "rv32i_m/I/slt-01", "9010", + "rv32i_m/I/slti-01", "6010", + "rv32i_m/I/sltiu-01", "6010", + "rv32i_m/I/sltu-01", "a010", + "rv32i_m/I/sra-01", "3010", + "rv32i_m/I/srai-01", "2010", + "rv32i_m/I/srl-01", "3010", + "rv32i_m/I/srli-01", "2010", + "rv32i_m/I/sub-01", "9010", + "rv32i_m/I/sw-align-01", "3010", + "rv32i_m/I/xor-01", "9010", + "rv32i_m/I/xori-01", "6010" }; string tests[]; @@ -490,7 +425,7 @@ string tests32f[] = '{ else if (TESTSPRIV) tests = tests64p; else begin - tests = {tests64i}; + tests = {tests64priv, tests64i}; // tests = {tests64p,tests64i, tests64periph}; if (`C_SUPPORTED) tests = {tests, tests64ic}; // 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(`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 $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(`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"); diff --git a/wally-pipelined/testbench/testbench-fpga.sv b/wally-pipelined/testbench/testbench-fpga.sv new file mode 100644 index 000000000..fbe13cf45 --- /dev/null +++ b/wally-pipelined/testbench/testbench-fpga.sv @@ -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= 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 +