diff --git a/.gitignore b/.gitignore index a77e4dac2..6d86993ea 100644 --- a/.gitignore +++ b/.gitignore @@ -198,3 +198,6 @@ sim/verilator/wkdir sim/vcs/logs sim/vcs/wkdir benchmarks/coremark/coremark_results.csv +fpga/zsbl/OBJ/* +fpga/zsbl/bin/* +sim/*.svg diff --git a/fpga/zsbl/linker.x b/fpga/zsbl/linker.x new file mode 100644 index 000000000..f448109cc --- /dev/null +++ b/fpga/zsbl/linker.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*/ + . = 0x0000000000000000; + . = ALIGN(0x0); + .init : { + *(.init) + } + _start_end = .; + + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", _start_end); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf64.em. */ + *(.gnu.warning) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : + { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + . = DATA_SEGMENT_RELRO_END (0, .); + .data : + { + __DATA_BEGIN__ = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + __SDATA_BEGIN__ = .; + *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .sbss : + { + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(64 / 8); + __BSS_END__ = .; + __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, + MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800)); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/linux/buildroot-config-src/buildroot-2023.05.1/main.config b/linux/buildroot-config-src/buildroot-2023.05.1/main.config index 348922670..3ea431c02 100644 --- a/linux/buildroot-config-src/buildroot-2023.05.1/main.config +++ b/linux/buildroot-config-src/buildroot-2023.05.1/main.config @@ -134,7 +134,7 @@ BR2_GCC_VERSION_12_X=y BR2_GCC_VERSION="12.3.0" BR2_EXTRA_GCC_CONFIG_OPTIONS="" BR2_TOOLCHAIN_BUILDROOT_CXX=y -# BR2_TOOLCHAIN_BUILDROOT_FORTRAN is not set +BR2_TOOLCHAIN_BUILDROOT_FORTRAN=y # BR2_GCC_ENABLE_OPENMP is not set # BR2_GCC_ENABLE_GRAPHITE is not set BR2_PACKAGE_HOST_GDB_ARCH_SUPPORTS=y @@ -152,6 +152,7 @@ BR2_TOOLCHAIN_SUPPORTS_VARIADIC_MI_THUNK=y BR2_USE_WCHAR=y BR2_ENABLE_LOCALE=y BR2_INSTALL_LIBSTDCPP=y +BR2_TOOLCHAIN_HAS_FORTRAN=y BR2_TOOLCHAIN_HAS_THREADS=y BR2_TOOLCHAIN_HAS_THREADS_DEBUG=y BR2_TOOLCHAIN_HAS_THREADS_NPTL=y @@ -1086,10 +1087,6 @@ BR2_PACKAGE_PROVIDES_HOST_LUAINTERPRETER="host-lua" # BR2_PACKAGE_MICROPYTHON is not set # BR2_PACKAGE_MOARVM is not set BR2_PACKAGE_HOST_MONO_ARCH_SUPPORTS=y - -# -# octave needs a toolchain w/ C++ and fortran, gcc >= 4.8 -# BR2_PACKAGE_HOST_OPENJDK_BIN_ARCH_SUPPORTS=y # BR2_PACKAGE_PERL is not set BR2_PACKAGE_PHP_ARCH_SUPPORTS=y @@ -1731,10 +1728,7 @@ BR2_PACKAGE_LIBCAMERA_ARCH_SUPPORTS=y # BR2_PACKAGE_ACE is not set # BR2_PACKAGE_APR is not set # BR2_PACKAGE_APR_UTIL is not set - -# -# armadillo needs a toolchain w/ fortran, C++ -# +# BR2_PACKAGE_ARMADILLO is not set # BR2_PACKAGE_ATF is not set # BR2_PACKAGE_AVRO_C is not set # BR2_PACKAGE_BCTOOLBOX is not set @@ -1782,10 +1776,7 @@ BR2_PACKAGE_GOBJECT_INTROSPECTION_ARCH_SUPPORTS=y BR2_PACKAGE_JEMALLOC_ARCH_SUPPORTS=y # BR2_PACKAGE_JEMALLOC is not set BR2_PACKAGE_LAPACK_ARCH_SUPPORTS=y - -# -# lapack/blas needs a toolchain w/ fortran -# +# BR2_PACKAGE_LAPACK is not set BR2_PACKAGE_LIBABSEIL_CPP_ARCH_SUPPORTS=y # BR2_PACKAGE_LIBABSEIL_CPP is not set # BR2_PACKAGE_LIBARGTABLE2 is not set diff --git a/sim/run-imperas-linux.sh b/sim/questa/run-imperas-linux.sh similarity index 73% rename from sim/run-imperas-linux.sh rename to sim/questa/run-imperas-linux.sh index 65e4826fb..7192adb81 100755 --- a/sim/run-imperas-linux.sh +++ b/sim/questa/run-imperas-linux.sh @@ -7,4 +7,4 @@ export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=100" #export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000" #export OTHERFLAGS="" -vsim -c -do "do wally-linux-imperas.do buildroot buildroot $::env(RISCV) 0 0 0" +vsim -c -do "do questa/wally-linux-imperas.do buildroot buildroot $::env(RISCV) 0 0 0" diff --git a/src/uncore/uart_apb.sv b/src/uncore/uart_apb.sv index eeecb7ea5..c3f8bb31c 100644 --- a/src/uncore/uart_apb.sv +++ b/src/uncore/uart_apb.sv @@ -60,7 +60,7 @@ module uart_apb import cvw::*; #(parameter cvw_t P) ( else assign PRDATA = {Dout, Dout, Dout, Dout}; logic BAUDOUTb; // loop tx clock BAUDOUTb back to rx clock RCLK - uartPC16550D #(P.UART_PRESCALE) u( + uartPC16550D #(P.UART_PRESCALE) uartPC( // Processor Interface .PCLK, .PRESETn, .A(entry), .Din, diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 22e0a35fc..97099d0e2 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -139,7 +139,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( end else begin : gpio assign GPIOOUT = 0; assign GPIOEN = 0; assign GPIOIntr = 0; end - if (P.UART_SUPPORTED == 1) begin : uart + if (P.UART_SUPPORTED == 1) begin : uartgen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uart_apb #(P) uart( .PCLK, .PRESETn, .PSEL(PSEL[3]), .PADDR(PADDR[2:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, .PRDATA(PRDATA[3]), .PREADY(PREADY[3]), diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index d82a5c0d4..8e223f858 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -79,7 +79,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( ); // instantiate uncore if a bus interface exists - if (P.BUS_SUPPORTED) begin : uncore + if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uncore #(P) uncore(.HCLK, .HRESETn, .TIMECLK, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC, diff --git a/testbench/testbench.sv b/testbench/testbench.sv index cd7a6ad3b..e16a265ea 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -443,10 +443,10 @@ module testbench; string romfilename, sdcfilename; romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"}; sdcfilename = {"../testbench/sdc/ramdisk2.hex"}; - //$readmemh(romfilename, dut.uncore.uncore.bootrom.bootrom.memory.ROM); + //$readmemh(romfilename, dut.uncoregen.uncore.bootrom.bootrom.memory.ROM); //$readmemh(sdcfilename, sdcard.sdcard.FLASHmem); // shorten sdc timers for simulation - //dut.uncore.uncore.sdc.SDC.LimitTimers = 1; + //dut.uncoregen.uncore.sdc.SDC.LimitTimers = 1; end end end else if (P.IROM_SUPPORTED) begin @@ -460,13 +460,13 @@ module testbench; if (LoadMem) begin if (TEST == "buildroot") begin memFile = $fopen(bootmemfilename, "rb"); - readResult = $fread(dut.uncore.uncore.bootrom.bootrom.memory.ROM, memFile); + readResult = $fread(dut.uncoregen.uncore.bootrom.bootrom.memory.ROM, memFile); $fclose(memFile); memFile = $fopen(memfilename, "rb"); - readResult = $fread(dut.uncore.uncore.ram.ram.memory.RAM, memFile); + readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.RAM, memFile); $fclose(memFile); end else - $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); + $readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.RAM); if (TEST == "embench") $display("Read memfile %s", memfilename); end if (CopyRAM) begin @@ -475,7 +475,7 @@ module testbench; EndIndex = (end_signature_addr >> LogXLEN) + 8; BaseIndex = P.UNCORE_RAM_BASE >> LogXLEN; for(ShadowIndex = StartIndex; ShadowIndex <= EndIndex; ShadowIndex++) begin - testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.uncore.uncore.ram.ram.memory.RAM[ShadowIndex - BaseIndex]; + testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.uncoregen.uncore.ram.ram.memory.RAM[ShadowIndex - BaseIndex]; end end end @@ -503,7 +503,7 @@ module testbench; always @(posedge clk) if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory) for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1) - dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = 0; + dut.uncoregen.uncore.ram.ram.memory.RAM[adrindex] = 0; //////////////////////////////////////////////////////////////////////////////// // Actual hardware @@ -594,12 +594,14 @@ module testbench; end // Append UART output to file for tests - always @(posedge clk) begin - if (P.UART_SUPPORTED & TEST == "buildroot") begin - if (~dut.uncore.uncore.uart.uart.MEMWb & dut.uncore.uncore.uart.uart.u.A == 3'b000 & ~dut.uncore.uncore.uart.uart.u.DLAB) begin - memFile = $fopen(uartoutfilename, "ab"); - $fwrite(memFile, "%c", dut.uncore.uncore.uart.uart.u.Din); - $fclose(memFile); + if (P.UART_SUPPORTED) begin: uart_logger + always @(posedge clk) begin + if (TEST == "buildroot") begin + if (~dut.uncoregen.uncore.uartgen.uart.MEMWb & dut.uncoregen.uncore.uartgen.uart.uartPC.A == 3'b000 & ~dut.uncoregen.uncore.uartgen.uart.uartPC.DLAB) begin + memFile = $fopen(uartoutfilename, "ab"); + $fwrite(memFile, "%c", dut.uncoregen.uncore.uartgen.uart.uartPC.Din); + $fclose(memFile); + end end end end @@ -875,8 +877,10 @@ end // ************************************** // ***** BUG BUG BUG make sure RT undoes this. //if (P.DTIM_SUPPORTED) sig = testbench.dut.core.lsu.dtim.dtim.ram.RAM[testadrNoBase+i]; - //else if (P.UNCORE_RAM_SUPPORTED) sig = testbench.dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i]; - //if (P.UNCORE_RAM_SUPPORTED) sig = testbench.dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i]; + + //else if (P.UNCORE_RAM_SUPPORTED) sig = testbench.dut.uncoregen.uncore.ram.ram.memory.RAM[testadrNoBase+i]; + if (P.UNCORE_RAM_SUPPORTED) sig = testbench.dut.uncoregen.uncore.ram.ram.memory.RAM[testadrNoBase+i]; + //if (P.UNCORE_RAM_SUPPORTED) sig = testbench.dut.uncoregen.uncore.ram.ram.memory.RAM[testadrNoBase+i]; //$display("signature[%h] = %h sig = %h", i, signature[i], sig); //if (signature[i] !== sig & (signature[i] !== testbench.DCacheFlushFSM.ShadowRAM[testadr+i])) begin if (signature[i] !== testbench.DCacheFlushFSM.ShadowRAM[testadr+i]) begin