Merge branch 'local-fpga-temp' into local-fpga-support
This commit is contained in:
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -21,7 +21,7 @@
|
|||||||
url = https://github.com/riscv-boom/riscv-boom.git
|
url = https://github.com/riscv-boom/riscv-boom.git
|
||||||
[submodule "generators/sifive-blocks"]
|
[submodule "generators/sifive-blocks"]
|
||||||
path = generators/sifive-blocks
|
path = generators/sifive-blocks
|
||||||
url = https://github.com/sifive/sifive-blocks.git
|
url = https://github.com/abejgonzalez/sifive-blocks.git
|
||||||
[submodule "generators/hwacha"]
|
[submodule "generators/hwacha"]
|
||||||
path = generators/hwacha
|
path = generators/hwacha
|
||||||
url = https://github.com/ucb-bar/hwacha.git
|
url = https://github.com/ucb-bar/hwacha.git
|
||||||
@@ -131,3 +131,6 @@
|
|||||||
[submodule "generators/riscv-sodor"]
|
[submodule "generators/riscv-sodor"]
|
||||||
path = generators/riscv-sodor
|
path = generators/riscv-sodor
|
||||||
url = https://github.com/ucb-bar/riscv-sodor.git
|
url = https://github.com/ucb-bar/riscv-sodor.git
|
||||||
|
[submodule "fpga/fpga-shells"]
|
||||||
|
path = fpga/fpga-shells
|
||||||
|
url = git@github.com:sifive/fpga-shells.git
|
||||||
|
|||||||
@@ -221,3 +221,10 @@ lazy val firechip = conditionalDependsOn(project in file("generators/firechip"))
|
|||||||
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),
|
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),
|
||||||
testOptions in Test += Tests.Argument("-oF")
|
testOptions in Test += Tests.Argument("-oF")
|
||||||
)
|
)
|
||||||
|
lazy val fpga_shells = (project in file("./fpga/fpga-shells"))
|
||||||
|
.dependsOn(rocketchip, sifive_blocks, chipyard)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
lazy val fpga_platforms = (project in file("./fpga"))
|
||||||
|
.dependsOn(chipyard, fpga_shells)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ include $(base_dir)/tools/dromajo/dromajo.mk
|
|||||||
# Returns a list of files in directory $1 with file extension $2.
|
# Returns a list of files in directory $1 with file extension $2.
|
||||||
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o -iname "*.$(2)" -print 2> /dev/null)
|
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o -iname "*.$(2)" -print 2> /dev/null)
|
||||||
|
|
||||||
SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools/iocell)
|
SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools/iocell fpga)
|
||||||
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
|
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
|
||||||
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
|
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
|
||||||
# This assumes no SBT meta-build sources
|
# This assumes no SBT meta-build sources
|
||||||
|
|||||||
1
fpga/.gitignore
vendored
Normal file
1
fpga/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
generated-src
|
||||||
132
fpga/Makefile
Normal file
132
fpga/Makefile
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#########################################################################################
|
||||||
|
# fpga prototype makefile
|
||||||
|
#########################################################################################
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# general path variables
|
||||||
|
#########################################################################################
|
||||||
|
base_dir=$(abspath ..)
|
||||||
|
sim_dir=$(abspath .)
|
||||||
|
|
||||||
|
# do not generate simulation files
|
||||||
|
sim_name := none
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# include shared variables
|
||||||
|
#########################################################################################
|
||||||
|
SUB_PROJECT ?= vcu118
|
||||||
|
|
||||||
|
ifeq ($(SUB_PROJECT),vcu118)
|
||||||
|
SBT_PROJECT ?= fpga_platforms
|
||||||
|
MODEL ?= VCU118FPGATestHarness
|
||||||
|
VLOG_MODEL ?= VCU118FPGATestHarness
|
||||||
|
MODEL_PACKAGE ?= chipyard.fpga.vcu118
|
||||||
|
CONFIG ?= RocketVCU118Config
|
||||||
|
CONFIG_PACKAGE ?= chipyard.fpga.vcu118
|
||||||
|
GENERATOR_PACKAGE ?= chipyard
|
||||||
|
TB ?= none # unused
|
||||||
|
TOP ?= ChipTop
|
||||||
|
BOARD ?= vcu118
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SUB_PROJECT),bringup)
|
||||||
|
SBT_PROJECT ?= fpga_platforms
|
||||||
|
MODEL ?= BringupVCU118FPGATestHarness
|
||||||
|
VLOG_MODEL ?= BringupVCU118FPGATestHarness
|
||||||
|
MODEL_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||||
|
CONFIG ?= RocketBringupConfig
|
||||||
|
CONFIG_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||||
|
GENERATOR_PACKAGE ?= chipyard
|
||||||
|
TB ?= none # unused
|
||||||
|
TOP ?= ChipTop
|
||||||
|
BOARD ?= vcu118
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SUB_PROJECT),arty)
|
||||||
|
# TODO: Fix with Arty
|
||||||
|
SBT_PROJECT ?= fpga_platforms
|
||||||
|
MODEL ?= BringupVCU118FPGATestHarness
|
||||||
|
VLOG_MODEL ?= BringupVCU118FPGATestHarness
|
||||||
|
MODEL_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||||
|
CONFIG ?= RocketBringupConfig
|
||||||
|
CONFIG_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||||
|
GENERATOR_PACKAGE ?= chipyard
|
||||||
|
TB ?= none # unused
|
||||||
|
TOP ?= ChipTop
|
||||||
|
BOARD ?= arty
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(base_dir)/variables.mk
|
||||||
|
|
||||||
|
# default variables to build the arty example
|
||||||
|
# setup the board to use
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
default: $(mcs)
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# misc. directories
|
||||||
|
#########################################################################################
|
||||||
|
fpga_dir := $(base_dir)/fpga/fpga-shells/xilinx
|
||||||
|
fpga_common_script_dir := $(fpga_dir)/common/tcl
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# import other necessary rules and variables
|
||||||
|
#########################################################################################
|
||||||
|
include $(base_dir)/common.mk
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# copy from other directory
|
||||||
|
#########################################################################################
|
||||||
|
all_vsrcs := \
|
||||||
|
$(sim_vsrcs) \
|
||||||
|
$(base_dir)/generators/sifive-blocks/vsrc/SRLatch.v \
|
||||||
|
$(fpga_dir)/common/vsrc/PowerOnResetFPGAOnly.v
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# vivado rules
|
||||||
|
#########################################################################################
|
||||||
|
# combine all sources into single .f
|
||||||
|
synth_list_f := $(build_dir)/$(long_name).vsrcs.f
|
||||||
|
$(synth_list_f): $(sim_common_files) $(all_vsrcs)
|
||||||
|
$(foreach file,$(all_vsrcs),echo "$(file)" >> $@;)
|
||||||
|
cat $(sim_common_files) >> $@
|
||||||
|
|
||||||
|
BIT_FILE := $(build_dir)/obj/$(MODEL).bit
|
||||||
|
$(BIT_FILE): $(synth_list_f)
|
||||||
|
cd $(build_dir); vivado \
|
||||||
|
-nojournal -mode batch \
|
||||||
|
-source $(fpga_common_script_dir)/vivado.tcl \
|
||||||
|
-tclargs \
|
||||||
|
-top-module "$(MODEL)" \
|
||||||
|
-F "$(synth_list_f)" \
|
||||||
|
-ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')" \
|
||||||
|
-board "$(BOARD)"
|
||||||
|
|
||||||
|
.PHONY: bit
|
||||||
|
bit: $(BIT_FILE)
|
||||||
|
|
||||||
|
.PHONY: debug-bitstream
|
||||||
|
debug-bitstream: $(build_dir)/obj/post_synth.dcp
|
||||||
|
cd $(build_dir); vivado \
|
||||||
|
-nojournal -mode batch \
|
||||||
|
-source $(sim_dir)/scripts/run_impl_bitstream.tcl \
|
||||||
|
-tclargs \
|
||||||
|
$(build_dir)/obj/post_synth.dcp \
|
||||||
|
xcvu9p-flga2104-2l-e \
|
||||||
|
$(build_dir)/obj/debug_output
|
||||||
|
|
||||||
|
# Build .mcs
|
||||||
|
MCS_FILE := $(build_dir)/obj/$(MODEL).mcs
|
||||||
|
$(MCS_FILE): $(BIT_FILE)
|
||||||
|
cd $(build_dir); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $<
|
||||||
|
|
||||||
|
.PHONY: mcs
|
||||||
|
mcs: $(MCS_FILE)
|
||||||
|
|
||||||
|
#########################################################################################
|
||||||
|
# general cleanup rules
|
||||||
|
#########################################################################################
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(gen_dir)
|
||||||
1
fpga/fpga-shells
Submodule
1
fpga/fpga-shells
Submodule
Submodule fpga/fpga-shells added at 89a5efec01
45
fpga/scripts/run_impl_bitstream.tcl
Normal file
45
fpga/scripts/run_impl_bitstream.tcl
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#### Command line arguments to this script
|
||||||
|
# argv[0] = absolute path to post_synth checkpoint file
|
||||||
|
# argv[1] = part
|
||||||
|
# argv[2] = output directory
|
||||||
|
|
||||||
|
set synth_checkpoint_file [lindex $argv 0]
|
||||||
|
set part [lindex $argv 1]
|
||||||
|
set output_dir [lindex $argv 2]
|
||||||
|
|
||||||
|
# Set the project part to the part passed into this script
|
||||||
|
set_part ${part}
|
||||||
|
|
||||||
|
# Create output directory if it doesn't exist
|
||||||
|
file mkdir ${output_dir}
|
||||||
|
file mkdir ${output_dir}/reports
|
||||||
|
file mkdir ${output_dir}/outputs
|
||||||
|
|
||||||
|
# Load synthesis checkpoint
|
||||||
|
open_checkpoint ${synth_checkpoint_file}
|
||||||
|
|
||||||
|
# Run implementation and save reports as needed
|
||||||
|
opt_design
|
||||||
|
place_design
|
||||||
|
phys_opt_design
|
||||||
|
write_checkpoint -force ${output_dir}/outputs/post_place
|
||||||
|
report_timing_summary -file ${output_dir}/reports/post_place_timing_summary.rpt
|
||||||
|
report_drc -file ${output_dir}/reports/post_place_drc.rpt
|
||||||
|
|
||||||
|
route_design
|
||||||
|
write_checkpoint -force ${output_dir}/outputs/post_route
|
||||||
|
report_timing_summary -file ${output_dir}/reports/post_route_timing_summary.rpt
|
||||||
|
report_timing -sort_by group -max_paths 100 -path_type summary -file ${output_dir}/reports/post_route_timing.rpt
|
||||||
|
report_clock_utilization -file ${output_dir}/reports/post_route_clock_utilization.rpt
|
||||||
|
report_utilization -file ${output_dir}/reports/post_route_utilization.rpt
|
||||||
|
report_drc -file ${output_dir}/reports/post_route_drc.rpt
|
||||||
|
report_cdc -details -file ${output_dir}/reports/post_route_cdc.rpt
|
||||||
|
report_clock_interaction -file ${output_dir}/reports/post_route_clock_interaction.rpt
|
||||||
|
report_bus_skew -file ${output_dir}/reports/post_route_bus_skew.rpt
|
||||||
|
report_design_analysis -logic_level_distribution -of_timing_paths [get_timing_paths -max_paths 1000 -slack_lesser_than 0] -file ${output_dir}/reports/post_route_timing_violations.rpt
|
||||||
|
|
||||||
|
write_verilog -force ${output_dir}/outputs/post_route.v
|
||||||
|
write_xdc -no_fixed_only -force ${output_dir}/outputs/post_route.xdc
|
||||||
|
|
||||||
|
write_bitstream -force ${output_dir}/outputs/top.bit
|
||||||
|
write_debug_probes -force ${output_dir}/outputs/debug_nets.ltx
|
||||||
75
fpga/scripts/write_mmi.tcl
Normal file
75
fpga/scripts/write_mmi.tcl
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
proc write_mmi {filepath inst} {
|
||||||
|
current_instance
|
||||||
|
current_instance $inst
|
||||||
|
set chn [open $filepath w]
|
||||||
|
puts $chn "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
|
puts $chn "<MemInfo Version=\"1\" Minor=\"0\">"
|
||||||
|
puts $chn "\t<Processor Endianness=\"Little\" InstPath=\"${inst}\">"
|
||||||
|
set brams [dict create]
|
||||||
|
foreach cell [get_cells -hierarchical -filter { PRIMITIVE_GROUP =~ BLOCKRAM }] {
|
||||||
|
set name [get_property RTL_RAM_NAME $cell]
|
||||||
|
dict update brams $name name {
|
||||||
|
dict lappend name cells $cell
|
||||||
|
dict set name size [get_property RTL_RAM_BITS $cell]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proc compare {a b} {
|
||||||
|
set a_addr [get_property bram_addr_begin $a]
|
||||||
|
set b_addr [get_property bram_addr_begin $b]
|
||||||
|
if {$a_addr > $b_addr} {
|
||||||
|
return 1
|
||||||
|
} elseif {$a_addr < $b_addr} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
set a_slice [get_property bram_slice_begin $a]
|
||||||
|
set b_slice [get_property bram_slice_begin $b]
|
||||||
|
if {$a_slice > $b_slice} {
|
||||||
|
return 1
|
||||||
|
} elseif {$a_slice < $b_slice} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
dict for {name desc} $brams {
|
||||||
|
dict with desc {
|
||||||
|
puts $chn "\t\t<AddressSpace Name=\"${name}\" Begin=\"0\" End=\"[expr $size >> 3]\">"
|
||||||
|
puts $chn "\t\t\t<BusBlock>"
|
||||||
|
foreach cell [lsort -command compare $cells] {
|
||||||
|
set type [switch [get_property REF_NAME $cell] \
|
||||||
|
RAMB36E2 {expr {"RAMB32"}} \
|
||||||
|
RAMB36E1 {expr {"RAMB32"}}]
|
||||||
|
set loc [lindex [split [get_property LOC $cell] "_"] 1]
|
||||||
|
set lsb [get_property bram_slice_begin $cell]
|
||||||
|
set msb [get_property bram_slice_end $cell]
|
||||||
|
set addr_bgn [get_property bram_addr_begin $cell]
|
||||||
|
set addr_end [get_property bram_addr_end $cell]
|
||||||
|
puts $chn "\t\t\t\t<BitLane MemType=\"${type}\" Placement=\"${loc}\">"
|
||||||
|
puts $chn "\t\t\t\t\t<DataWidth MSB=\"${msb}\" LSB=\"${lsb}\"/>"
|
||||||
|
puts $chn "\t\t\t\t\t<AddressRange Begin=\"${addr_bgn}\" End=\"${addr_end}\"/>"
|
||||||
|
puts $chn "\t\t\t\t\t<Parity ON=\"false\" NumBits=\"0\"/>"
|
||||||
|
puts $chn "\t\t\t\t</BitLane>"
|
||||||
|
}
|
||||||
|
puts $chn "\t\t\t</BusBlock>"
|
||||||
|
puts $chn "\t\t</AddressSpace>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts $chn "\t</Processor>"
|
||||||
|
puts $chn "\t<Config>"
|
||||||
|
puts $chn "\t\t<Option Name=\"Part\" Val=\"[get_property PART [current_project]]\"/>"
|
||||||
|
puts $chn "\t</Config>"
|
||||||
|
puts $chn "</MemInfo>"
|
||||||
|
close $chn
|
||||||
|
current_instance
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if {$argc != 3} {
|
||||||
|
puts $argc
|
||||||
|
puts {Error: Invalid number of arguments}
|
||||||
|
puts {Usage: write_mmi.tcl checkpoint mmi_file instance}
|
||||||
|
}
|
||||||
|
|
||||||
|
lassign $argv checkpoint mmi_file instance
|
||||||
|
|
||||||
|
open_checkpoint $checkpoint
|
||||||
|
write_mmi $mmi_file $instance
|
||||||
1
fpga/src/main/resources/vcu118/sdboot/.gitignore
vendored
Normal file
1
fpga/src/main/resources/vcu118/sdboot/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
build
|
||||||
39
fpga/src/main/resources/vcu118/sdboot/Makefile
Normal file
39
fpga/src/main/resources/vcu118/sdboot/Makefile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# RISCV environment variable must be set
|
||||||
|
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
BUILD_DIR := $(ROOT_DIR)/build
|
||||||
|
|
||||||
|
CC=$(RISCV)/bin/riscv64-unknown-elf-gcc
|
||||||
|
OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy
|
||||||
|
OBJDUMP=$(RISCV)/bin/riscv64-unknown-elf-objdump
|
||||||
|
CFLAGS=-march=rv64ima -mcmodel=medany -O2 -std=gnu11 -Wall -nostartfiles
|
||||||
|
CFLAGS+= -fno-common -g -DENTROPY=0 -mabi=lp64 -DNONSMP_HART=0
|
||||||
|
CFLAGS+= -I $(ROOT_DIR)/include -I.
|
||||||
|
LFLAGS=-static -nostdlib -L $(ROOT_DIR)/linker -T sdboot.elf.lds
|
||||||
|
|
||||||
|
#PBUS_CLK passed in
|
||||||
|
elf := $(BUILD_DIR)/sdboot.elf
|
||||||
|
$(elf): head.S kprintf.c sd.c
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) -DTL_CLK="$(PBUS_CLK)UL" $(LFLAGS) -o $@ head.S sd.c kprintf.c
|
||||||
|
|
||||||
|
.PHONY: elf
|
||||||
|
elf: $(elf)
|
||||||
|
|
||||||
|
bin := $(BUILD_DIR)/sdboot.bin
|
||||||
|
$(bin): $(elf)
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
$(OBJCOPY) -O binary --change-addresses=-0x10000 $< $@
|
||||||
|
|
||||||
|
.PHONY: bin
|
||||||
|
bin: $(bin)
|
||||||
|
|
||||||
|
dump := $(BUILD_DIR)/sdboot.dump
|
||||||
|
$(dump): $(elf)
|
||||||
|
$(OBJDUMP) -D -S $< > $@
|
||||||
|
|
||||||
|
.PHONY: dump
|
||||||
|
dump: $(dump)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean::
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
9
fpga/src/main/resources/vcu118/sdboot/common.h
Normal file
9
fpga/src/main/resources/vcu118/sdboot/common.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _SDBOOT_COMMON_H
|
||||||
|
#define _SDBOOT_COMMON_H
|
||||||
|
|
||||||
|
#ifndef PAYLOAD_DEST
|
||||||
|
#define PAYLOAD_DEST MEMORY_MEM_ADDR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
21
fpga/src/main/resources/vcu118/sdboot/head.S
Normal file
21
fpga/src/main/resources/vcu118/sdboot/head.S
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#include <platform.h>
|
||||||
|
#include <smp.h>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
.section .text.init
|
||||||
|
.option norvc
|
||||||
|
.globl _prog_start
|
||||||
|
_prog_start:
|
||||||
|
smp_pause(s1, s2)
|
||||||
|
li sp, (PAYLOAD_DEST + 0xffff000)
|
||||||
|
call main
|
||||||
|
smp_resume(s1, s2)
|
||||||
|
csrr a0, mhartid // hartid for next level bootloader
|
||||||
|
la a1, dtb // dtb address for next level bootloader
|
||||||
|
li s1, PAYLOAD_DEST
|
||||||
|
jr s1
|
||||||
|
|
||||||
|
.section .dtb
|
||||||
|
.align 3
|
||||||
|
dtb:
|
||||||
36
fpga/src/main/resources/vcu118/sdboot/include/bits.h
Normal file
36
fpga/src/main/resources/vcu118/sdboot/include/bits.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#ifndef _RISCV_BITS_H
|
||||||
|
#define _RISCV_BITS_H
|
||||||
|
|
||||||
|
#define likely(x) __builtin_expect((x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect((x), 0)
|
||||||
|
|
||||||
|
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
|
||||||
|
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
|
||||||
|
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
|
||||||
|
|
||||||
|
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
|
||||||
|
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
||||||
|
|
||||||
|
#define STR(x) XSTR(x)
|
||||||
|
#define XSTR(x) #x
|
||||||
|
|
||||||
|
#if __riscv_xlen == 64
|
||||||
|
# define SLL32 sllw
|
||||||
|
# define STORE sd
|
||||||
|
# define LOAD ld
|
||||||
|
# define LWU lwu
|
||||||
|
# define LOG_REGBYTES 3
|
||||||
|
#else
|
||||||
|
# define SLL32 sll
|
||||||
|
# define STORE sw
|
||||||
|
# define LOAD lw
|
||||||
|
# define LWU lw
|
||||||
|
# define LOG_REGBYTES 2
|
||||||
|
#endif
|
||||||
|
#define REGBYTES (1 << LOG_REGBYTES)
|
||||||
|
|
||||||
|
#endif
|
||||||
18
fpga/src/main/resources/vcu118/sdboot/include/const.h
Normal file
18
fpga/src/main/resources/vcu118/sdboot/include/const.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
/* Derived from <linux/const.h> */
|
||||||
|
|
||||||
|
#ifndef _SIFIVE_CONST_H
|
||||||
|
#define _SIFIVE_CONST_H
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLER__
|
||||||
|
#define _AC(X,Y) X
|
||||||
|
#define _AT(T,X) X
|
||||||
|
#else
|
||||||
|
#define _AC(X,Y) (X##Y)
|
||||||
|
#define _AT(T,X) ((T)(X))
|
||||||
|
#endif /* !__ASSEMBLER__*/
|
||||||
|
|
||||||
|
#define _BITUL(x) (_AC(1,UL) << (x))
|
||||||
|
#define _BITULL(x) (_AC(1,ULL) << (x))
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_CONST_H */
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef _SIFIVE_CLINT_H
|
||||||
|
#define _SIFIVE_CLINT_H
|
||||||
|
|
||||||
|
|
||||||
|
#define CLINT_MSIP 0x0000
|
||||||
|
#define CLINT_MSIP_size 0x4
|
||||||
|
#define CLINT_MTIMECMP 0x4000
|
||||||
|
#define CLINT_MTIMECMP_size 0x8
|
||||||
|
#define CLINT_MTIME 0xBFF8
|
||||||
|
#define CLINT_MTIME_size 0x8
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_CLINT_H */
|
||||||
24
fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h
Normal file
24
fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef _SIFIVE_GPIO_H
|
||||||
|
#define _SIFIVE_GPIO_H
|
||||||
|
|
||||||
|
#define GPIO_INPUT_VAL (0x00)
|
||||||
|
#define GPIO_INPUT_EN (0x04)
|
||||||
|
#define GPIO_OUTPUT_EN (0x08)
|
||||||
|
#define GPIO_OUTPUT_VAL (0x0C)
|
||||||
|
#define GPIO_PULLUP_EN (0x10)
|
||||||
|
#define GPIO_DRIVE (0x14)
|
||||||
|
#define GPIO_RISE_IE (0x18)
|
||||||
|
#define GPIO_RISE_IP (0x1C)
|
||||||
|
#define GPIO_FALL_IE (0x20)
|
||||||
|
#define GPIO_FALL_IP (0x24)
|
||||||
|
#define GPIO_HIGH_IE (0x28)
|
||||||
|
#define GPIO_HIGH_IP (0x2C)
|
||||||
|
#define GPIO_LOW_IE (0x30)
|
||||||
|
#define GPIO_LOW_IP (0x34)
|
||||||
|
#define GPIO_IOF_EN (0x38)
|
||||||
|
#define GPIO_IOF_SEL (0x3C)
|
||||||
|
#define GPIO_OUTPUT_XOR (0x40)
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_GPIO_H */
|
||||||
31
fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h
Normal file
31
fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef PLIC_H
|
||||||
|
#define PLIC_H
|
||||||
|
|
||||||
|
#include <const.h>
|
||||||
|
|
||||||
|
// 32 bits per source
|
||||||
|
#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL)
|
||||||
|
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
|
||||||
|
// 1 bit per source (1 address)
|
||||||
|
#define PLIC_PENDING_OFFSET _AC(0x1000,UL)
|
||||||
|
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
|
||||||
|
|
||||||
|
//0x80 per target
|
||||||
|
#define PLIC_ENABLE_OFFSET _AC(0x2000,UL)
|
||||||
|
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
|
||||||
|
|
||||||
|
|
||||||
|
#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL)
|
||||||
|
#define PLIC_CLAIM_OFFSET _AC(0x200004,UL)
|
||||||
|
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
|
||||||
|
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
|
||||||
|
|
||||||
|
#define PLIC_MAX_SOURCE 1023
|
||||||
|
#define PLIC_SOURCE_MASK 0x3FF
|
||||||
|
|
||||||
|
#define PLIC_MAX_TARGET 15871
|
||||||
|
#define PLIC_TARGET_MASK 0x3FFF
|
||||||
|
|
||||||
|
#endif /* PLIC_H */
|
||||||
79
fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h
Normal file
79
fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef _SIFIVE_SPI_H
|
||||||
|
#define _SIFIVE_SPI_H
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
|
||||||
|
#define SPI_REG_SCKDIV 0x00
|
||||||
|
#define SPI_REG_SCKMODE 0x04
|
||||||
|
#define SPI_REG_CSID 0x10
|
||||||
|
#define SPI_REG_CSDEF 0x14
|
||||||
|
#define SPI_REG_CSMODE 0x18
|
||||||
|
|
||||||
|
#define SPI_REG_DCSSCK 0x28
|
||||||
|
#define SPI_REG_DSCKCS 0x2a
|
||||||
|
#define SPI_REG_DINTERCS 0x2c
|
||||||
|
#define SPI_REG_DINTERXFR 0x2e
|
||||||
|
|
||||||
|
#define SPI_REG_FMT 0x40
|
||||||
|
#define SPI_REG_TXFIFO 0x48
|
||||||
|
#define SPI_REG_RXFIFO 0x4c
|
||||||
|
#define SPI_REG_TXCTRL 0x50
|
||||||
|
#define SPI_REG_RXCTRL 0x54
|
||||||
|
|
||||||
|
#define SPI_REG_FCTRL 0x60
|
||||||
|
#define SPI_REG_FFMT 0x64
|
||||||
|
|
||||||
|
#define SPI_REG_IE 0x70
|
||||||
|
#define SPI_REG_IP 0x74
|
||||||
|
|
||||||
|
/* Fields */
|
||||||
|
|
||||||
|
#define SPI_SCK_POL 0x1
|
||||||
|
#define SPI_SCK_PHA 0x2
|
||||||
|
|
||||||
|
#define SPI_FMT_PROTO(x) ((x) & 0x3)
|
||||||
|
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
|
||||||
|
#define SPI_FMT_DIR(x) (((x) & 0x1) << 3)
|
||||||
|
#define SPI_FMT_LEN(x) (((x) & 0xf) << 16)
|
||||||
|
|
||||||
|
/* TXCTRL register */
|
||||||
|
#define SPI_TXWM(x) ((x) & 0xffff)
|
||||||
|
/* RXCTRL register */
|
||||||
|
#define SPI_RXWM(x) ((x) & 0xffff)
|
||||||
|
|
||||||
|
#define SPI_IP_TXWM 0x1
|
||||||
|
#define SPI_IP_RXWM 0x2
|
||||||
|
|
||||||
|
#define SPI_FCTRL_EN 0x1
|
||||||
|
|
||||||
|
#define SPI_INSN_CMD_EN 0x1
|
||||||
|
#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
|
||||||
|
#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
|
||||||
|
#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
|
||||||
|
#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
|
||||||
|
#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
|
||||||
|
#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
|
||||||
|
#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
|
||||||
|
|
||||||
|
#define SPI_TXFIFO_FULL (1 << 31)
|
||||||
|
#define SPI_RXFIFO_EMPTY (1 << 31)
|
||||||
|
|
||||||
|
/* Values */
|
||||||
|
|
||||||
|
#define SPI_CSMODE_AUTO 0
|
||||||
|
#define SPI_CSMODE_HOLD 2
|
||||||
|
#define SPI_CSMODE_OFF 3
|
||||||
|
|
||||||
|
#define SPI_DIR_RX 0
|
||||||
|
#define SPI_DIR_TX 1
|
||||||
|
|
||||||
|
#define SPI_PROTO_S 0
|
||||||
|
#define SPI_PROTO_D 1
|
||||||
|
#define SPI_PROTO_Q 2
|
||||||
|
|
||||||
|
#define SPI_ENDIAN_MSB 0
|
||||||
|
#define SPI_ENDIAN_LSB 1
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_SPI_H */
|
||||||
28
fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h
Normal file
28
fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef _SIFIVE_UART_H
|
||||||
|
#define _SIFIVE_UART_H
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
#define UART_REG_TXFIFO 0x00
|
||||||
|
#define UART_REG_RXFIFO 0x04
|
||||||
|
#define UART_REG_TXCTRL 0x08
|
||||||
|
#define UART_REG_RXCTRL 0x0c
|
||||||
|
#define UART_REG_IE 0x10
|
||||||
|
#define UART_REG_IP 0x14
|
||||||
|
#define UART_REG_DIV 0x18
|
||||||
|
|
||||||
|
/* TXCTRL register */
|
||||||
|
#define UART_TXEN 0x1
|
||||||
|
#define UART_TXNSTOP 0x2
|
||||||
|
#define UART_TXWM(x) (((x) & 0xffff) << 16)
|
||||||
|
|
||||||
|
/* RXCTRL register */
|
||||||
|
#define UART_RXEN 0x1
|
||||||
|
#define UART_RXWM(x) (((x) & 0xffff) << 16)
|
||||||
|
|
||||||
|
/* IP register */
|
||||||
|
#define UART_IP_TXWM 0x1
|
||||||
|
#define UART_IP_RXWM 0x2
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_UART_H */
|
||||||
108
fpga/src/main/resources/vcu118/sdboot/include/platform.h
Normal file
108
fpga/src/main/resources/vcu118/sdboot/include/platform.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
#ifndef _EAGLE_PLATFORM_H
|
||||||
|
#define _EAGLE_PLATFORM_H
|
||||||
|
|
||||||
|
#include "const.h"
|
||||||
|
#include "riscv_test_defaults.h"
|
||||||
|
#include "devices/clint.h"
|
||||||
|
#include "devices/gpio.h"
|
||||||
|
#include "devices/plic.h"
|
||||||
|
#include "devices/spi.h"
|
||||||
|
#include "devices/uart.h"
|
||||||
|
|
||||||
|
// Some things missing from the official encoding.h
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
#define MCAUSE_INT 0x80000000UL
|
||||||
|
#define MCAUSE_CAUSE 0x7FFFFFFFUL
|
||||||
|
#else
|
||||||
|
#define MCAUSE_INT 0x8000000000000000UL
|
||||||
|
#define MCAUSE_CAUSE 0x7FFFFFFFFFFFFFFFUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Platform definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// CPU info
|
||||||
|
#define NUM_CORES 1
|
||||||
|
#define GLOBAL_INT_SIZE 38
|
||||||
|
#define GLOBAL_INT_MAX_PRIORITY 7
|
||||||
|
|
||||||
|
// Memory map
|
||||||
|
#define CLINT_CTRL_ADDR _AC(0x2000000,UL)
|
||||||
|
#define CLINT_CTRL_SIZE _AC(0x10000,UL)
|
||||||
|
#define DEBUG_CTRL_ADDR _AC(0x0,UL)
|
||||||
|
#define DEBUG_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define ERROR_MEM_ADDR _AC(0x3000,UL)
|
||||||
|
#define ERROR_MEM_SIZE _AC(0x1000,UL)
|
||||||
|
#define GPIO_CTRL_ADDR _AC(0x64002000,UL)
|
||||||
|
#define GPIO_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define MASKROM_MEM_ADDR _AC(0x10000,UL)
|
||||||
|
#define MASKROM_MEM_SIZE _AC(0x10000,UL)
|
||||||
|
#define MEMORY_MEM_ADDR _AC(0x80000000,UL)
|
||||||
|
#define MEMORY_MEM_SIZE _AC(0x10000000,UL)
|
||||||
|
#define PLIC_CTRL_ADDR _AC(0xc000000,UL)
|
||||||
|
#define PLIC_CTRL_SIZE _AC(0x4000000,UL)
|
||||||
|
#define SPI_CTRL_ADDR _AC(0x64001000,UL)
|
||||||
|
#define SPI_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define SPI1_CTRL_ADDR _AC(0x64004000,UL)
|
||||||
|
#define SPI1_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define TEST_CTRL_ADDR _AC(0x4000,UL)
|
||||||
|
#define TEST_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define UART_CTRL_ADDR _AC(0x64000000,UL)
|
||||||
|
#define UART_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define UART1_CTRL_ADDR _AC(0x64003000,UL)
|
||||||
|
#define UART1_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
#define I2C_CTRL_ADDR _AC(0x64005000,UL)
|
||||||
|
#define I2C_CTRL_SIZE _AC(0x1000,UL)
|
||||||
|
|
||||||
|
// IOF masks
|
||||||
|
|
||||||
|
|
||||||
|
// Interrupt numbers
|
||||||
|
#define UART_INT_BASE 1
|
||||||
|
#define UART1_INT_BASE 2
|
||||||
|
#define I2C_INT_BASE 3
|
||||||
|
#define GPIO_INT_BASE 4
|
||||||
|
#define SPI_INT_BASE 36
|
||||||
|
#define SPI1_INT_BASE 37
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
|
||||||
|
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
|
||||||
|
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
|
||||||
|
// Bulk set bits in `reg` to either 0 or 1.
|
||||||
|
// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7
|
||||||
|
// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7
|
||||||
|
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
|
||||||
|
#define AXI_PCIE_HOST_1_00_A_REG(offset) _REG32(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
|
||||||
|
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
|
||||||
|
#define DEBUG_REG(offset) _REG32(DEBUG_CTRL_ADDR, offset)
|
||||||
|
#define ERROR_REG(offset) _REG32(ERROR_CTRL_ADDR, offset)
|
||||||
|
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
|
||||||
|
#define MASKROM_REG(offset) _REG32(MASKROM_CTRL_ADDR, offset)
|
||||||
|
#define MEMORY_REG(offset) _REG32(MEMORY_CTRL_ADDR, offset)
|
||||||
|
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
|
||||||
|
#define SPI_REG(offset) _REG32(SPI_CTRL_ADDR, offset)
|
||||||
|
#define TEST_REG(offset) _REG32(TEST_CTRL_ADDR, offset)
|
||||||
|
#define UART_REG(offset) _REG32(UART_CTRL_ADDR, offset)
|
||||||
|
#define AXI_PCIE_HOST_1_00_A_REG64(offset) _REG64(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
|
||||||
|
#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset)
|
||||||
|
#define DEBUG_REG64(offset) _REG64(DEBUG_CTRL_ADDR, offset)
|
||||||
|
#define ERROR_REG64(offset) _REG64(ERROR_CTRL_ADDR, offset)
|
||||||
|
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
|
||||||
|
#define MASKROM_REG64(offset) _REG64(MASKROM_CTRL_ADDR, offset)
|
||||||
|
#define MEMORY_REG64(offset) _REG64(MEMORY_CTRL_ADDR, offset)
|
||||||
|
#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset)
|
||||||
|
#define SPI_REG64(offset) _REG64(SPI_CTRL_ADDR, offset)
|
||||||
|
#define SPI1_REG64(offset) _REG64(SPI1_CTRL_ADDR, offset)
|
||||||
|
#define TEST_REG64(offset) _REG64(TEST_CTRL_ADDR, offset)
|
||||||
|
#define UART_REG64(offset) _REG64(UART_CTRL_ADDR, offset)
|
||||||
|
#define UART1_REG64(offset) _REG64(UART1_CTRL_ADDR, offset)
|
||||||
|
#define I2C_REG64(offset) _REG64(I2C_CTRL_ADDR, offset)
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _SIFIVE_PLATFORM_H */
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#ifndef _RISCV_TEST_DEFAULTS_H
|
||||||
|
#define _RISCV_TEST_DEFAULTS_H
|
||||||
|
|
||||||
|
#define TESTNUM x28
|
||||||
|
#define TESTBASE 0x4000
|
||||||
|
|
||||||
|
#define RVTEST_RV32U \
|
||||||
|
.macro init; \
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#define RVTEST_RV64U \
|
||||||
|
.macro init; \
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#define RVTEST_RV32UF \
|
||||||
|
.macro init; \
|
||||||
|
/* If FPU exists, initialize FCSR. */ \
|
||||||
|
csrr t0, misa; \
|
||||||
|
andi t0, t0, 1 << ('F' - 'A'); \
|
||||||
|
beqz t0, 1f; \
|
||||||
|
/* Enable FPU if it exists. */ \
|
||||||
|
li t0, MSTATUS_FS; \
|
||||||
|
csrs mstatus, t0; \
|
||||||
|
fssr x0; \
|
||||||
|
1: ; \
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#define RVTEST_RV64UF \
|
||||||
|
.macro init; \
|
||||||
|
/* If FPU exists, initialize FCSR. */ \
|
||||||
|
csrr t0, misa; \
|
||||||
|
andi t0, t0, 1 << ('F' - 'A'); \
|
||||||
|
beqz t0, 1f; \
|
||||||
|
/* Enable FPU if it exists. */ \
|
||||||
|
li t0, MSTATUS_FS; \
|
||||||
|
csrs mstatus, t0; \
|
||||||
|
fssr x0; \
|
||||||
|
1: ; \
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#define RVTEST_CODE_BEGIN \
|
||||||
|
.section .text.init; \
|
||||||
|
.globl _prog_start; \
|
||||||
|
_prog_start: \
|
||||||
|
init;
|
||||||
|
|
||||||
|
#define RVTEST_CODE_END \
|
||||||
|
unimp
|
||||||
|
|
||||||
|
#define RVTEST_PASS \
|
||||||
|
fence; \
|
||||||
|
li t0, TESTBASE; \
|
||||||
|
li t1, 0x5555; \
|
||||||
|
sw t1, 0(t0); \
|
||||||
|
1: \
|
||||||
|
j 1b;
|
||||||
|
|
||||||
|
#define RVTEST_FAIL \
|
||||||
|
li t0, TESTBASE; \
|
||||||
|
li t1, 0x3333; \
|
||||||
|
slli a0, a0, 16; \
|
||||||
|
add a0, a0, t1; \
|
||||||
|
sw a0, 0(t0); \
|
||||||
|
1: \
|
||||||
|
j 1b;
|
||||||
|
|
||||||
|
#define EXTRA_DATA
|
||||||
|
|
||||||
|
#define RVTEST_DATA_BEGIN \
|
||||||
|
EXTRA_DATA \
|
||||||
|
.align 4; .global begin_signature; begin_signature:
|
||||||
|
|
||||||
|
#define RVTEST_DATA_END \
|
||||||
|
_msg_init: .asciz "RUN\r\n"; \
|
||||||
|
_msg_pass: .asciz "PASS"; \
|
||||||
|
_msg_fail: .asciz "FAIL "; \
|
||||||
|
_msg_end: .asciz "\r\n"; \
|
||||||
|
.align 4; .global end_signature; end_signature:
|
||||||
|
|
||||||
|
#endif /* _RISCV_TEST_DEFAULTS_H */
|
||||||
17
fpga/src/main/resources/vcu118/sdboot/include/sections.h
Normal file
17
fpga/src/main/resources/vcu118/sdboot/include/sections.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#ifndef _SECTIONS_H
|
||||||
|
#define _SECTIONS_H
|
||||||
|
|
||||||
|
extern unsigned char _rom[];
|
||||||
|
extern unsigned char _rom_end[];
|
||||||
|
|
||||||
|
extern unsigned char _ram[];
|
||||||
|
extern unsigned char _ram_end[];
|
||||||
|
|
||||||
|
extern unsigned char _ftext[];
|
||||||
|
extern unsigned char _etext[];
|
||||||
|
extern unsigned char _fbss[];
|
||||||
|
extern unsigned char _ebss[];
|
||||||
|
extern unsigned char _end[];
|
||||||
|
|
||||||
|
#endif /* _SECTIONS_H */
|
||||||
142
fpga/src/main/resources/vcu118/sdboot/include/smp.h
Normal file
142
fpga/src/main/resources/vcu118/sdboot/include/smp.h
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#ifndef SIFIVE_SMP
|
||||||
|
#define SIFIVE_SMP
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
// The maximum number of HARTs this code supports
|
||||||
|
#ifndef MAX_HARTS
|
||||||
|
#define MAX_HARTS 32
|
||||||
|
#endif
|
||||||
|
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4)
|
||||||
|
#define CLINT1_END_HART_IPI CLINT1_CTRL_ADDR + (MAX_HARTS*4)
|
||||||
|
|
||||||
|
// The hart that non-SMP tests should run on
|
||||||
|
#ifndef NONSMP_HART
|
||||||
|
#define NONSMP_HART 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If your test cannot handle multiple-threads, use this:
|
||||||
|
* smp_disable(reg1)
|
||||||
|
*/
|
||||||
|
#define smp_disable(reg1, reg2) \
|
||||||
|
csrr reg1, mhartid ;\
|
||||||
|
li reg2, NONSMP_HART ;\
|
||||||
|
beq reg1, reg2, hart0_entry ;\
|
||||||
|
42: ;\
|
||||||
|
wfi ;\
|
||||||
|
j 42b ;\
|
||||||
|
hart0_entry:
|
||||||
|
|
||||||
|
/* If your test needs to temporarily block multiple-threads, do this:
|
||||||
|
* smp_pause(reg1, reg2)
|
||||||
|
* ... single-threaded work ...
|
||||||
|
* smp_resume(reg1, reg2)
|
||||||
|
* ... multi-threaded work ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define smp_pause(reg1, reg2) \
|
||||||
|
li reg2, 0x8 ;\
|
||||||
|
csrw mie, reg2 ;\
|
||||||
|
li reg1, NONSMP_HART ;\
|
||||||
|
csrr reg2, mhartid ;\
|
||||||
|
bne reg1, reg2, 42f
|
||||||
|
|
||||||
|
#ifdef CLINT1_CTRL_ADDR
|
||||||
|
// If a second CLINT exists, then make sure we:
|
||||||
|
// 1) Trigger a software interrupt on all harts of both CLINTs.
|
||||||
|
// 2) Locate your own hart's software interrupt pending register and clear it.
|
||||||
|
// 3) Wait for all harts on both CLINTs to clear their software interrupt
|
||||||
|
// pending register.
|
||||||
|
// WARNING: This code makes these assumptions, which are only true for Fadu as
|
||||||
|
// of now:
|
||||||
|
// 1) hart0 uses CLINT0 at offset 0
|
||||||
|
// 2) hart2 uses CLINT1 at offset 0
|
||||||
|
// 3) hart3 uses CLINT1 at offset 1
|
||||||
|
// 4) There are no other harts or CLINTs in the system.
|
||||||
|
#define smp_resume(reg1, reg2) \
|
||||||
|
/* Trigger software interrupt on CLINT0 */ \
|
||||||
|
li reg1, CLINT_CTRL_ADDR ;\
|
||||||
|
41: ;\
|
||||||
|
li reg2, 1 ;\
|
||||||
|
sw reg2, 0(reg1) ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b ;\
|
||||||
|
/* Trigger software interrupt on CLINT1 */ \
|
||||||
|
li reg1, CLINT1_CTRL_ADDR ;\
|
||||||
|
41: ;\
|
||||||
|
li reg2, 1 ;\
|
||||||
|
sw reg2, 0(reg1) ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT1_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b ;\
|
||||||
|
/* Wait to receive software interrupt */ \
|
||||||
|
42: ;\
|
||||||
|
wfi ;\
|
||||||
|
csrr reg2, mip ;\
|
||||||
|
andi reg2, reg2, 0x8 ;\
|
||||||
|
beqz reg2, 42b ;\
|
||||||
|
/* Clear own software interrupt bit */ \
|
||||||
|
csrr reg2, mhartid ;\
|
||||||
|
bnez reg2, 41f; \
|
||||||
|
/* hart0 case: Use CLINT0 */ \
|
||||||
|
li reg1, CLINT_CTRL_ADDR ;\
|
||||||
|
slli reg2, reg2, 2 ;\
|
||||||
|
add reg2, reg2, reg1 ;\
|
||||||
|
sw zero, 0(reg2) ;\
|
||||||
|
j 42f; \
|
||||||
|
41: \
|
||||||
|
/* hart 2, 3 case: Use CLINT1 and remap hart IDs to 0 and 1 */ \
|
||||||
|
li reg1, CLINT1_CTRL_ADDR ;\
|
||||||
|
addi reg2, reg2, -2; \
|
||||||
|
slli reg2, reg2, 2 ;\
|
||||||
|
add reg2, reg2, reg1 ;\
|
||||||
|
sw zero, 0(reg2) ; \
|
||||||
|
42: \
|
||||||
|
/* Wait for all software interrupt bits to be cleared on CLINT0 */ \
|
||||||
|
li reg1, CLINT_CTRL_ADDR ;\
|
||||||
|
41: ;\
|
||||||
|
lw reg2, 0(reg1) ;\
|
||||||
|
bnez reg2, 41b ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b; \
|
||||||
|
/* Wait for all software interrupt bits to be cleared on CLINT1 */ \
|
||||||
|
li reg1, CLINT1_CTRL_ADDR ;\
|
||||||
|
41: ;\
|
||||||
|
lw reg2, 0(reg1) ;\
|
||||||
|
bnez reg2, 41b ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT1_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b; \
|
||||||
|
/* End smp_resume() */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define smp_resume(reg1, reg2) \
|
||||||
|
li reg1, CLINT_CTRL_ADDR ;\
|
||||||
|
41: ;\
|
||||||
|
li reg2, 1 ;\
|
||||||
|
sw reg2, 0(reg1) ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b ;\
|
||||||
|
42: ;\
|
||||||
|
wfi ;\
|
||||||
|
csrr reg2, mip ;\
|
||||||
|
andi reg2, reg2, 0x8 ;\
|
||||||
|
beqz reg2, 42b ;\
|
||||||
|
li reg1, CLINT_CTRL_ADDR ;\
|
||||||
|
csrr reg2, mhartid ;\
|
||||||
|
slli reg2, reg2, 2 ;\
|
||||||
|
add reg2, reg2, reg1 ;\
|
||||||
|
sw zero, 0(reg2) ;\
|
||||||
|
41: ;\
|
||||||
|
lw reg2, 0(reg1) ;\
|
||||||
|
bnez reg2, 41b ;\
|
||||||
|
addi reg1, reg1, 4 ;\
|
||||||
|
li reg2, CLINT_END_HART_IPI ;\
|
||||||
|
blt reg1, reg2, 41b
|
||||||
|
|
||||||
|
#endif /* ifdef CLINT1_CTRL_ADDR */
|
||||||
|
|
||||||
|
#endif
|
||||||
75
fpga/src/main/resources/vcu118/sdboot/kprintf.c
Normal file
75
fpga/src/main/resources/vcu118/sdboot/kprintf.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
|
static inline void _kputs(const char *s)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
for (; (c = *s) != '\0'; s++)
|
||||||
|
kputc(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kputs(const char *s)
|
||||||
|
{
|
||||||
|
_kputs(s);
|
||||||
|
kputc('\r');
|
||||||
|
kputc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void kprintf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
bool is_format, is_long, is_char;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
va_start(vl, fmt);
|
||||||
|
is_format = false;
|
||||||
|
is_long = false;
|
||||||
|
is_char = false;
|
||||||
|
while ((c = *fmt++) != '\0') {
|
||||||
|
if (is_format) {
|
||||||
|
switch (c) {
|
||||||
|
case 'l':
|
||||||
|
is_long = true;
|
||||||
|
continue;
|
||||||
|
case 'h':
|
||||||
|
is_char = true;
|
||||||
|
continue;
|
||||||
|
case 'x': {
|
||||||
|
unsigned long n;
|
||||||
|
long i;
|
||||||
|
if (is_long) {
|
||||||
|
n = va_arg(vl, unsigned long);
|
||||||
|
i = (sizeof(unsigned long) << 3) - 4;
|
||||||
|
} else {
|
||||||
|
n = va_arg(vl, unsigned int);
|
||||||
|
i = is_char ? 4 : (sizeof(unsigned int) << 3) - 4;
|
||||||
|
}
|
||||||
|
for (; i >= 0; i -= 4) {
|
||||||
|
long d;
|
||||||
|
d = (n >> i) & 0xF;
|
||||||
|
kputc(d < 10 ? '0' + d : 'a' + d - 10);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
_kputs(va_arg(vl, const char *));
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
kputc(va_arg(vl, int));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
is_format = false;
|
||||||
|
is_long = false;
|
||||||
|
is_char = false;
|
||||||
|
} else if (c == '%') {
|
||||||
|
is_format = true;
|
||||||
|
} else {
|
||||||
|
kputc(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(vl);
|
||||||
|
}
|
||||||
49
fpga/src/main/resources/vcu118/sdboot/kprintf.h
Normal file
49
fpga/src/main/resources/vcu118/sdboot/kprintf.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#ifndef _SDBOOT_KPRINTF_H
|
||||||
|
#define _SDBOOT_KPRINTF_H
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define REG32(p, i) ((p)[(i) >> 2])
|
||||||
|
|
||||||
|
#ifndef UART_CTRL_ADDR
|
||||||
|
#ifndef UART_NUM
|
||||||
|
#define UART_NUM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _CONCAT3(A, B, C) A ## B ## C
|
||||||
|
#define _UART_CTRL_ADDR(UART_NUM) _CONCAT3(UART, UART_NUM, _CTRL_ADDR)
|
||||||
|
#define UART_CTRL_ADDR _UART_CTRL_ADDR(UART_NUM)
|
||||||
|
#endif
|
||||||
|
static volatile uint32_t * const uart = (void *)(UART_CTRL_ADDR);
|
||||||
|
|
||||||
|
static inline void kputc(char c)
|
||||||
|
{
|
||||||
|
volatile uint32_t *tx = ®32(uart, UART_REG_TXFIFO);
|
||||||
|
#ifdef __riscv_atomic
|
||||||
|
int32_t r;
|
||||||
|
do {
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"amoor.w %0, %2, %1\n"
|
||||||
|
: "=r" (r), "+A" (*tx)
|
||||||
|
: "r" (c));
|
||||||
|
} while (r < 0);
|
||||||
|
#else
|
||||||
|
while ((int32_t)(*tx) < 0);
|
||||||
|
*tx = c;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void kputs(const char *);
|
||||||
|
extern void kprintf(const char *, ...);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define dprintf(s, ...) kprintf((s), ##__VA_ARGS__)
|
||||||
|
#define dputs(s) kputs((s))
|
||||||
|
#else
|
||||||
|
#define dprintf(s, ...) do { } while (0)
|
||||||
|
#define dputs(s) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SDBOOT_KPRINTF_H */
|
||||||
5
fpga/src/main/resources/vcu118/sdboot/linker/memory.lds
Normal file
5
fpga/src/main/resources/vcu118/sdboot/linker/memory.lds
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
bootrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000
|
||||||
|
memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000
|
||||||
|
}
|
||||||
80
fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds
Normal file
80
fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
OUTPUT_ARCH("riscv")
|
||||||
|
ENTRY(_prog_start)
|
||||||
|
|
||||||
|
INCLUDE memory.lds
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
text PT_LOAD;
|
||||||
|
data PT_LOAD;
|
||||||
|
bss PT_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
PROVIDE(_ram = ORIGIN(memory_mem));
|
||||||
|
PROVIDE(_ram_end = _ram + LENGTH(memory_mem));
|
||||||
|
|
||||||
|
.text ALIGN((ORIGIN(bootrom_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(bootrom_mem) + 0x0), 8)) {
|
||||||
|
PROVIDE(_ftext = .);
|
||||||
|
*(.text.init)
|
||||||
|
*(.text.unlikely .text.unlikely.*)
|
||||||
|
*(.text .text.* .gnu.linkonce.t.*)
|
||||||
|
PROVIDE(_etext = .);
|
||||||
|
. += 0x40; /* to create a gap between .text and .data b/c ifetch can fetch ahead from .data */
|
||||||
|
} >bootrom_mem :text
|
||||||
|
|
||||||
|
.eh_frame ALIGN((ADDR(.text) + SIZEOF(.text)), 8) : AT(ALIGN((LOADADDR(.text) + SIZEOF(.text)), 8)) {
|
||||||
|
*(.eh_frame)
|
||||||
|
} >bootrom_mem :text
|
||||||
|
|
||||||
|
.srodata ALIGN((ADDR(.eh_frame) + SIZEOF(.eh_frame)), 8) : AT(ALIGN((LOADADDR(.eh_frame) + SIZEOF(.eh_frame)), 8)) ALIGN_WITH_INPUT {
|
||||||
|
*(.srodata.cst16)
|
||||||
|
*(.srodata.cst8)
|
||||||
|
*(.srodata.cst4)
|
||||||
|
*(.srodata.cst2)
|
||||||
|
*(.srodata.*)
|
||||||
|
} >bootrom_mem :data
|
||||||
|
|
||||||
|
.data ALIGN((ADDR(.srodata) + SIZEOF(.srodata)), 8) : AT(ALIGN((LOADADDR(.srodata) + SIZEOF(.srodata)), 8)) ALIGN_WITH_INPUT {
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
*(.tohost) /* TODO: Support sections that aren't explicitly listed in this linker script */
|
||||||
|
} >bootrom_mem :data
|
||||||
|
|
||||||
|
.sdata ALIGN((ADDR(.data) + SIZEOF(.data)), 8) : AT(ALIGN((LOADADDR(.data) + SIZEOF(.data)), 8)) ALIGN_WITH_INPUT {
|
||||||
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
|
} >bootrom_mem :data
|
||||||
|
|
||||||
|
.rodata ALIGN((ADDR(.sdata) + SIZEOF(.sdata)), 8) : AT(ALIGN((LOADADDR(.sdata) + SIZEOF(.sdata)), 8)) ALIGN_WITH_INPUT {
|
||||||
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
|
*(.dtb)
|
||||||
|
} >bootrom_mem :data
|
||||||
|
|
||||||
|
PROVIDE(_data = ADDR(.rodata));
|
||||||
|
PROVIDE(_data_lma = LOADADDR(.rodata));
|
||||||
|
PROVIDE(_edata = .);
|
||||||
|
|
||||||
|
.bss ALIGN((ORIGIN(memory_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(memory_mem) + 0x0), 8)) ALIGN(8) {
|
||||||
|
PROVIDE(_fbss = .);
|
||||||
|
PROVIDE(__global_pointer$ = . + 0x7C0);
|
||||||
|
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
PROVIDE(_ebss = .);
|
||||||
|
} >memory_mem :bss
|
||||||
|
|
||||||
|
PROVIDE(_end = .);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* heap_stack_region_usable_end: (ORIGIN(memory_mem) + LENGTH(memory_mem))
|
||||||
|
* heap_stack_min_size: 4096
|
||||||
|
* heap_stack_max_size: 1048576
|
||||||
|
*/
|
||||||
|
PROVIDE(_sp = ALIGN(MIN((ORIGIN(memory_mem) + LENGTH(memory_mem)), _ebss + 1048576) - 7, 8));
|
||||||
|
PROVIDE(_heap_end = _sp - 2048);
|
||||||
|
|
||||||
|
/* This section is a noop and is only used for the ASSERT */
|
||||||
|
.stack : {
|
||||||
|
ASSERT(_sp >= (_ebss + 4096), "Error: No room left for the heap and stack");
|
||||||
|
}
|
||||||
|
}
|
||||||
236
fpga/src/main/resources/vcu118/sdboot/sd.c
Normal file
236
fpga/src/main/resources/vcu118/sdboot/sd.c
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
|
#define MAX_CORES 8
|
||||||
|
|
||||||
|
// A sector is 512 bytes, so ((1 << 11) * 512) = 1 MiB
|
||||||
|
#define PAYLOAD_SIZE (16 << 11)
|
||||||
|
|
||||||
|
// The sector at which the BBL partition starts
|
||||||
|
#define BBL_PARTITION_START_SECTOR 34
|
||||||
|
|
||||||
|
#ifndef TL_CLK
|
||||||
|
#error Must define TL_CLK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define F_CLK TL_CLK
|
||||||
|
|
||||||
|
static volatile uint32_t * const spi = (void *)(SPI_CTRL_ADDR);
|
||||||
|
|
||||||
|
static inline uint8_t spi_xfer(uint8_t d)
|
||||||
|
{
|
||||||
|
int32_t r;
|
||||||
|
|
||||||
|
REG32(spi, SPI_REG_TXFIFO) = d;
|
||||||
|
do {
|
||||||
|
r = REG32(spi, SPI_REG_RXFIFO);
|
||||||
|
} while (r < 0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t sd_dummy(void)
|
||||||
|
{
|
||||||
|
return spi_xfer(0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
|
||||||
|
{
|
||||||
|
unsigned long n;
|
||||||
|
uint8_t r;
|
||||||
|
|
||||||
|
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
|
||||||
|
sd_dummy();
|
||||||
|
spi_xfer(cmd);
|
||||||
|
spi_xfer(arg >> 24);
|
||||||
|
spi_xfer(arg >> 16);
|
||||||
|
spi_xfer(arg >> 8);
|
||||||
|
spi_xfer(arg);
|
||||||
|
spi_xfer(crc);
|
||||||
|
|
||||||
|
n = 1000;
|
||||||
|
do {
|
||||||
|
r = sd_dummy();
|
||||||
|
if (!(r & 0x80)) {
|
||||||
|
// dprintf("sd:cmd: %hx\r\n", r);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
} while (--n > 0);
|
||||||
|
kputs("sd_cmd: timeout");
|
||||||
|
done:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sd_cmd_end(void)
|
||||||
|
{
|
||||||
|
sd_dummy();
|
||||||
|
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void sd_poweron(void)
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 300000UL);
|
||||||
|
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_OFF;
|
||||||
|
for (i = 10; i > 0; i--) {
|
||||||
|
sd_dummy();
|
||||||
|
}
|
||||||
|
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sd_cmd0(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
dputs("CMD0");
|
||||||
|
rc = (sd_cmd(0x40, 0, 0x95) != 0x01);
|
||||||
|
sd_cmd_end();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sd_cmd8(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
dputs("CMD8");
|
||||||
|
rc = (sd_cmd(0x48, 0x000001AA, 0x87) != 0x01);
|
||||||
|
sd_dummy(); /* command version; reserved */
|
||||||
|
sd_dummy(); /* reserved */
|
||||||
|
rc |= ((sd_dummy() & 0xF) != 0x1); /* voltage */
|
||||||
|
rc |= (sd_dummy() != 0xAA); /* check pattern */
|
||||||
|
sd_cmd_end();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sd_cmd55(void)
|
||||||
|
{
|
||||||
|
sd_cmd(0x77, 0, 0x65);
|
||||||
|
sd_cmd_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sd_acmd41(void)
|
||||||
|
{
|
||||||
|
uint8_t r;
|
||||||
|
dputs("ACMD41");
|
||||||
|
do {
|
||||||
|
sd_cmd55();
|
||||||
|
r = sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */
|
||||||
|
} while (r == 0x01);
|
||||||
|
return (r != 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sd_cmd58(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
dputs("CMD58");
|
||||||
|
rc = (sd_cmd(0x7A, 0, 0xFD) != 0x00);
|
||||||
|
rc |= ((sd_dummy() & 0x80) != 0x80); /* Power up status */
|
||||||
|
sd_dummy();
|
||||||
|
sd_dummy();
|
||||||
|
sd_dummy();
|
||||||
|
sd_cmd_end();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sd_cmd16(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
dputs("CMD16");
|
||||||
|
rc = (sd_cmd(0x50, 0x200, 0x15) != 0x00);
|
||||||
|
sd_cmd_end();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t crc16_round(uint16_t crc, uint8_t data) {
|
||||||
|
crc = (uint8_t)(crc >> 8) | (crc << 8);
|
||||||
|
crc ^= data;
|
||||||
|
crc ^= (uint8_t)(crc >> 4) & 0xf;
|
||||||
|
crc ^= crc << 12;
|
||||||
|
crc ^= (crc & 0xff) << 5;
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPIN_SHIFT 6
|
||||||
|
#define SPIN_UPDATE(i) (!((i) & ((1 << SPIN_SHIFT)-1)))
|
||||||
|
#define SPIN_INDEX(i) (((i) >> SPIN_SHIFT) & 0x3)
|
||||||
|
|
||||||
|
static const char spinner[] = { '-', '/', '|', '\\' };
|
||||||
|
|
||||||
|
static int copy(void)
|
||||||
|
{
|
||||||
|
volatile uint8_t *p = (void *)(PAYLOAD_DEST);
|
||||||
|
long i = PAYLOAD_SIZE;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
dputs("CMD18");
|
||||||
|
kprintf("LOADING ");
|
||||||
|
|
||||||
|
// John: Let's go slow until we get this working
|
||||||
|
//REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 16666666UL);
|
||||||
|
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 5000000UL);
|
||||||
|
if (sd_cmd(0x52, BBL_PARTITION_START_SECTOR, 0xE1) != 0x00) {
|
||||||
|
sd_cmd_end();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
uint16_t crc, crc_exp;
|
||||||
|
long n;
|
||||||
|
|
||||||
|
crc = 0;
|
||||||
|
n = 512;
|
||||||
|
while (sd_dummy() != 0xFE);
|
||||||
|
do {
|
||||||
|
uint8_t x = sd_dummy();
|
||||||
|
*p++ = x;
|
||||||
|
crc = crc16_round(crc, x);
|
||||||
|
} while (--n > 0);
|
||||||
|
|
||||||
|
crc_exp = ((uint16_t)sd_dummy() << 8);
|
||||||
|
crc_exp |= sd_dummy();
|
||||||
|
|
||||||
|
if (crc != crc_exp) {
|
||||||
|
kputs("\b- CRC mismatch ");
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPIN_UPDATE(i)) {
|
||||||
|
kputc('\b');
|
||||||
|
kputc(spinner[SPIN_INDEX(i)]);
|
||||||
|
}
|
||||||
|
} while (--i > 0);
|
||||||
|
sd_cmd_end();
|
||||||
|
|
||||||
|
sd_cmd(0x4C, 0, 0x01);
|
||||||
|
sd_cmd_end();
|
||||||
|
kputs("\b ");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
REG32(uart, UART_REG_TXCTRL) = UART_TXEN;
|
||||||
|
|
||||||
|
kputs("INIT");
|
||||||
|
sd_poweron();
|
||||||
|
if (sd_cmd0() ||
|
||||||
|
sd_cmd8() ||
|
||||||
|
sd_acmd41() ||
|
||||||
|
sd_cmd58() ||
|
||||||
|
sd_cmd16() ||
|
||||||
|
copy()) {
|
||||||
|
kputs("ERROR");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kputs("BOOT");
|
||||||
|
|
||||||
|
__asm__ __volatile__ ("fence.i" : : : "memory");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
34
fpga/src/main/scala/arty/TestHarness.scala
Normal file
34
fpga/src/main/scala/arty/TestHarness.scala
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//package chipyard.fpga.arty
|
||||||
|
//
|
||||||
|
//import chisel3._
|
||||||
|
//import chisel3.experimental.{Analog}
|
||||||
|
//
|
||||||
|
//import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
|
//import freechips.rocketchip.config.{Parameters}
|
||||||
|
//
|
||||||
|
//import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
||||||
|
//
|
||||||
|
//import chipyard.{BuildTop, HasHarnessSignalReferences}
|
||||||
|
//
|
||||||
|
//class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences {
|
||||||
|
//
|
||||||
|
// val ldut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
|
||||||
|
//
|
||||||
|
// // turn IO clock into Reset type
|
||||||
|
// val hReset = Wire(Reset())
|
||||||
|
// hReset := ck_rst
|
||||||
|
//
|
||||||
|
// // default to 32MHz clock
|
||||||
|
// withClockAndReset(clock_32MHz, hReset) {
|
||||||
|
// val dut = Module(ldut.module)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val harnessClock = clock_32MHz
|
||||||
|
// val harnessReset = hReset
|
||||||
|
// val success = false.B
|
||||||
|
// val dutReset = hReset
|
||||||
|
//
|
||||||
|
// // must be after HasHarnessSignalReferences assignments
|
||||||
|
// ldut.harnessFunctions.foreach(_(this))
|
||||||
|
//}
|
||||||
|
//
|
||||||
72
fpga/src/main/scala/arty/e300/Configs.scala
Normal file
72
fpga/src/main/scala/arty/e300/Configs.scala
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
//// See LICENSE for license details.
|
||||||
|
//package chipyard.fpga.arty.e300
|
||||||
|
//
|
||||||
|
//import freechips.rocketchip.config._
|
||||||
|
//import freechips.rocketchip.subsystem._
|
||||||
|
//import freechips.rocketchip.devices.debug._
|
||||||
|
//import freechips.rocketchip.devices.tilelink._
|
||||||
|
//import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase}
|
||||||
|
//import freechips.rocketchip.system._
|
||||||
|
//import freechips.rocketchip.tile._
|
||||||
|
//
|
||||||
|
//import sifive.blocks.devices.mockaon._
|
||||||
|
//import sifive.blocks.devices.gpio._
|
||||||
|
//import sifive.blocks.devices.pwm._
|
||||||
|
//import sifive.blocks.devices.spi._
|
||||||
|
//import sifive.blocks.devices.uart._
|
||||||
|
//import sifive.blocks.devices.i2c._
|
||||||
|
//
|
||||||
|
//import chipyard.{BuildSystem}
|
||||||
|
//
|
||||||
|
//class E300DevKitExtra extends Config((site, here, up) => {
|
||||||
|
// case PeripheryGPIOKey => List(
|
||||||
|
// GPIOParams(address = 0x10012000, width = 32, includeIOF = true))
|
||||||
|
// case PeripheryPWMKey => List(
|
||||||
|
// PWMParams(address = 0x10015000, cmpWidth = 8),
|
||||||
|
// PWMParams(address = 0x10025000, cmpWidth = 16),
|
||||||
|
// PWMParams(address = 0x10035000, cmpWidth = 16))
|
||||||
|
// case PeripherySPIKey => List(
|
||||||
|
// SPIParams(csWidth = 4, rAddress = 0x10024000, defaultSampleDel = 3),
|
||||||
|
// SPIParams(csWidth = 1, rAddress = 0x10034000, defaultSampleDel = 3))
|
||||||
|
// case PeripherySPIFlashKey => List(
|
||||||
|
// SPIFlashParams(
|
||||||
|
// fAddress = 0x20000000,
|
||||||
|
// rAddress = 0x10014000,
|
||||||
|
// defaultSampleDel = 3))
|
||||||
|
// case PeripheryUARTKey => List(
|
||||||
|
// UARTParams(address = 0x10013000),
|
||||||
|
// UARTParams(address = 0x10023000))
|
||||||
|
// case PeripheryI2CKey => List(
|
||||||
|
// I2CParams(address = 0x10016000))
|
||||||
|
// case PeripheryMockAONKey =>
|
||||||
|
// MockAONParams(address = 0x10000000)
|
||||||
|
// case DTSTimebase => BigInt(32768)
|
||||||
|
// case JtagDTMKey => new JtagDTMConfig (
|
||||||
|
// idcodeVersion = 2,
|
||||||
|
// idcodePartNum = 0x000,
|
||||||
|
// idcodeManufId = 0x489,
|
||||||
|
// debugIdleCycles = 5)
|
||||||
|
//})
|
||||||
|
//
|
||||||
|
//class WithE300System extends Config((site, here, up) => {
|
||||||
|
// case BuildSystem => (p: Parameters) => new E300DigitalTop()(p)
|
||||||
|
//})
|
||||||
|
//
|
||||||
|
//class E300ArtyDevKitConfig extends Config(
|
||||||
|
// new WithE300System ++
|
||||||
|
// new WithE300Connections ++
|
||||||
|
// new E300DevKitExtra ++
|
||||||
|
// new chipyard.config.WithBootROM ++
|
||||||
|
// new chipyard.config.WithL2TLBs(1024) ++
|
||||||
|
// new freechips.rocketchip.subsystem.With1TinyCore ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNoMemPort ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNBreakpoints(2) ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithJtagDTM ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNoMMIOPort ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNoSlavePort ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithInclusiveCache ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
|
||||||
|
// new freechips.rocketchip.subsystem.WithIncoherentBusTopology ++
|
||||||
|
// new freechips.rocketchip.system.BaseConfig)
|
||||||
23
fpga/src/main/scala/arty/e300/DigitalTop.scala
Normal file
23
fpga/src/main/scala/arty/e300/DigitalTop.scala
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//package chipyard.fpga.arty.e300
|
||||||
|
//
|
||||||
|
//import chisel3._
|
||||||
|
//
|
||||||
|
//import freechips.rocketchip.subsystem._
|
||||||
|
//import freechips.rocketchip.system._
|
||||||
|
//import freechips.rocketchip.config.Parameters
|
||||||
|
//import freechips.rocketchip.devices.tilelink._
|
||||||
|
//
|
||||||
|
//import chipyard.{DigitalTop, DigitalTopModule}
|
||||||
|
//
|
||||||
|
//// ------------------------------------
|
||||||
|
//// E300 DigitalTop
|
||||||
|
//// ------------------------------------
|
||||||
|
//
|
||||||
|
//class E300DigitalTop(implicit p: Parameters) extends DigitalTop
|
||||||
|
// with sifive.blocks.devices.mockaon.HasPeripheryMockAON
|
||||||
|
//{
|
||||||
|
// override lazy val module = new E300DigitalTopModule(this)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//class E300DigitalTopModule[+L <: E300DigitalTop](l: L) extends DigitalTopModule(l)
|
||||||
|
// with sifive.blocks.devices.mockaon.HasPeripheryMockAONModuleImp
|
||||||
365
fpga/src/main/scala/arty/e300/IOBinders.scala
Normal file
365
fpga/src/main/scala/arty/e300/IOBinders.scala
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
//package chipyard.fpga.arty.e300
|
||||||
|
//
|
||||||
|
//import chisel3._
|
||||||
|
//import chisel3.experimental.{attach, IO}
|
||||||
|
//
|
||||||
|
//import freechips.rocketchip.util._
|
||||||
|
//import freechips.rocketchip.devices.debug._
|
||||||
|
//import freechips.rocketchip.subsystem.{NExtTopInterrupts}
|
||||||
|
//
|
||||||
|
//import sifive.blocks.devices.gpio._
|
||||||
|
//import sifive.blocks.devices.uart._
|
||||||
|
//import sifive.blocks.devices.spi._
|
||||||
|
//import sifive.blocks.devices.pwm._
|
||||||
|
//import sifive.blocks.devices.i2c._
|
||||||
|
//import sifive.blocks.devices.mockaon._
|
||||||
|
//import sifive.blocks.devices.jtag._
|
||||||
|
//import sifive.blocks.devices.pinctrl._
|
||||||
|
//
|
||||||
|
//import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
||||||
|
//import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly}
|
||||||
|
//
|
||||||
|
//import chipsalliance.rocketchip.config._
|
||||||
|
//
|
||||||
|
//import chipyard.iobinders.{OverrideIOBinder, GetSystemParameters}
|
||||||
|
//import chipyard.{HasHarnessSignalReferences}
|
||||||
|
//
|
||||||
|
//class WithE300Connections extends OverrideIOBinder({
|
||||||
|
// (system: HasPeripheryGPIOModuleImp
|
||||||
|
// with HasPeripheryUARTModuleImp
|
||||||
|
// with HasPeripherySPIModuleImp
|
||||||
|
// with HasPeripheryDebugModuleImp
|
||||||
|
// with HasPeripheryPWMModuleImp
|
||||||
|
// with HasPeripherySPIFlashModuleImp
|
||||||
|
// with HasPeripheryMockAONModuleImp
|
||||||
|
// with HasPeripheryI2CModuleImp) => {
|
||||||
|
//
|
||||||
|
// implicit val p: Parameters = GetSystemParameters(system)
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // E300DigitalTop <-> ChipTop connections
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// object PinGen {
|
||||||
|
// def apply(): BasePin = {
|
||||||
|
// val pin = new BasePin()
|
||||||
|
// pin
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val io_jtag = IO(new JTAGPins(() => PinGen(), false)).suggestName("jtag")
|
||||||
|
// val io_gpio = IO(new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0))).suggestName("gpio")
|
||||||
|
// val io_qspi = IO(new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0))).suggestName("qspi")
|
||||||
|
// val io_aon = IO(new MockAONWrapperPins()).suggestName("aon")
|
||||||
|
// val io_jtag_reset = IO(Input(Bool())).suggestName("jtag_reset")
|
||||||
|
// val io_ndreset = IO(Output(Bool())).suggestName("ndreset")
|
||||||
|
//
|
||||||
|
// // This needs to be de-asserted synchronously to the coreClk.
|
||||||
|
// val async_corerst = system.aon.rsts.corerst
|
||||||
|
// // Add in debug-controlled reset.
|
||||||
|
// system.reset := ResetCatchAndSync(system.clock, async_corerst, 20)
|
||||||
|
// Debug.connectDebugClockAndReset(system.debug, system.clock)
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Check for unsupported rocket-chip connections
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// require (p(NExtTopInterrupts) == 0, "No Top-level interrupts supported");
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Build GPIO Pin Mux
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Pin Mux for UART, SPI, PWM
|
||||||
|
// // First convert the System outputs into "IOF" using the respective *GPIOPort
|
||||||
|
// // converters.
|
||||||
|
//
|
||||||
|
// val sys_uart = system.uart
|
||||||
|
// val sys_pwm = system.pwm
|
||||||
|
// val sys_spi = system.spi
|
||||||
|
// val sys_i2c = system.i2c
|
||||||
|
//
|
||||||
|
// val uart_pins = p(PeripheryUARTKey).map { c => Wire(new UARTPins(() => PinGen()))}
|
||||||
|
// val pwm_pins = p(PeripheryPWMKey).map { c => Wire(new PWMPins(() => PinGen(), c))}
|
||||||
|
// val spi_pins = p(PeripherySPIKey).map { c => Wire(new SPIPins(() => PinGen(), c))}
|
||||||
|
// val i2c_pins = p(PeripheryI2CKey).map { c => Wire(new I2CPins(() => PinGen()))}
|
||||||
|
//
|
||||||
|
// (uart_pins zip sys_uart) map {case (p, r) => UARTPinsFromPort(p, r, clock = system.clock, reset = system.reset.asBool, syncStages = 0)}
|
||||||
|
// (pwm_pins zip sys_pwm) map {case (p, r) => PWMPinsFromPort(p, r) }
|
||||||
|
// (spi_pins zip sys_spi) map {case (p, r) => SPIPinsFromPort(p, r, clock = system.clock, reset = system.reset.asBool, syncStages = 0)}
|
||||||
|
// (i2c_pins zip sys_i2c) map {case (p, r) => I2CPinsFromPort(p, r, clock = system.clock, reset = system.reset.asBool, syncStages = 0)}
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Default Pin connections before attaching pinmux
|
||||||
|
//
|
||||||
|
// for (iof_0 <- system.gpio(0).iof_0.get) {
|
||||||
|
// iof_0.default()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for (iof_1 <- system.gpio(0).iof_1.get) {
|
||||||
|
// iof_1.default()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// val iof_0 = system.gpio(0).iof_0.get
|
||||||
|
// val iof_1 = system.gpio(0).iof_1.get
|
||||||
|
//
|
||||||
|
// // SPI1 (0 is the dedicated)
|
||||||
|
// BasePinToIOF(spi_pins(0).cs(0), iof_0(2))
|
||||||
|
// BasePinToIOF(spi_pins(0).dq(0), iof_0(3))
|
||||||
|
// BasePinToIOF(spi_pins(0).dq(1), iof_0(4))
|
||||||
|
// BasePinToIOF(spi_pins(0).sck, iof_0(5))
|
||||||
|
// BasePinToIOF(spi_pins(0).dq(2), iof_0(6))
|
||||||
|
// BasePinToIOF(spi_pins(0).dq(3), iof_0(7))
|
||||||
|
// BasePinToIOF(spi_pins(0).cs(1), iof_0(8))
|
||||||
|
// BasePinToIOF(spi_pins(0).cs(2), iof_0(9))
|
||||||
|
// BasePinToIOF(spi_pins(0).cs(3), iof_0(10))
|
||||||
|
//
|
||||||
|
// // SPI2
|
||||||
|
// BasePinToIOF(spi_pins(1).cs(0), iof_0(26))
|
||||||
|
// BasePinToIOF(spi_pins(1).dq(0), iof_0(27))
|
||||||
|
// BasePinToIOF(spi_pins(1).dq(1), iof_0(28))
|
||||||
|
// BasePinToIOF(spi_pins(1).sck, iof_0(29))
|
||||||
|
// BasePinToIOF(spi_pins(1).dq(2), iof_0(30))
|
||||||
|
// BasePinToIOF(spi_pins(1).dq(3), iof_0(31))
|
||||||
|
//
|
||||||
|
// // I2C
|
||||||
|
// if (p(PeripheryI2CKey).length == 1) {
|
||||||
|
// BasePinToIOF(i2c_pins(0).sda, iof_0(12))
|
||||||
|
// BasePinToIOF(i2c_pins(0).scl, iof_0(13))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // UART0
|
||||||
|
// BasePinToIOF(uart_pins(0).rxd, iof_0(16))
|
||||||
|
// BasePinToIOF(uart_pins(0).txd, iof_0(17))
|
||||||
|
//
|
||||||
|
// // UART1
|
||||||
|
// BasePinToIOF(uart_pins(1).rxd, iof_0(24))
|
||||||
|
// BasePinToIOF(uart_pins(1).txd, iof_0(25))
|
||||||
|
//
|
||||||
|
// //PWM
|
||||||
|
// BasePinToIOF(pwm_pins(0).pwm(0), iof_1(0) )
|
||||||
|
// BasePinToIOF(pwm_pins(0).pwm(1), iof_1(1) )
|
||||||
|
// BasePinToIOF(pwm_pins(0).pwm(2), iof_1(2) )
|
||||||
|
// BasePinToIOF(pwm_pins(0).pwm(3), iof_1(3) )
|
||||||
|
//
|
||||||
|
// BasePinToIOF(pwm_pins(1).pwm(1), iof_1(19))
|
||||||
|
// BasePinToIOF(pwm_pins(1).pwm(0), iof_1(20))
|
||||||
|
// BasePinToIOF(pwm_pins(1).pwm(2), iof_1(21))
|
||||||
|
// BasePinToIOF(pwm_pins(1).pwm(3), iof_1(22))
|
||||||
|
//
|
||||||
|
// BasePinToIOF(pwm_pins(2).pwm(0), iof_1(10))
|
||||||
|
// BasePinToIOF(pwm_pins(2).pwm(1), iof_1(11))
|
||||||
|
// BasePinToIOF(pwm_pins(2).pwm(2), iof_1(12))
|
||||||
|
// BasePinToIOF(pwm_pins(2).pwm(3), iof_1(13))
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Drive actual Pads
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// // Result of Pin Mux
|
||||||
|
// GPIOPinsFromPort(io_gpio, system.gpio(0))
|
||||||
|
//
|
||||||
|
// // Dedicated SPI Pads
|
||||||
|
// SPIPinsFromPort(io_qspi, system.qspi(0), clock = system.clock, reset = system.reset.asBool, syncStages = 3)
|
||||||
|
//
|
||||||
|
// // JTAG Debug Interface
|
||||||
|
// val sjtag = system.debug.get.systemjtag.get
|
||||||
|
// JTAGPinsFromPort(io_jtag, sjtag.jtag)
|
||||||
|
// sjtag.reset := io_jtag_reset
|
||||||
|
// sjtag.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
//
|
||||||
|
// io_ndreset := system.debug.get.ndreset
|
||||||
|
//
|
||||||
|
// // AON Pads -- direct connection is OK because
|
||||||
|
// // EnhancedPin is hard-coded in MockAONPads
|
||||||
|
// // and thus there is no .fromPort method.
|
||||||
|
// io_aon <> system.aon.pins
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Harness Function (ArtyHarness <-> ChipTop)
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// val harnessFn = (baseTh: HasHarnessSignalReferences) => {
|
||||||
|
// baseTh match { case th: ArtyShell =>
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // Clock divider
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// val slow_clock = Wire(Bool())
|
||||||
|
//
|
||||||
|
// // Divide clock by 256, used to generate 32.768 kHz clock for AON block
|
||||||
|
// withClockAndReset(th.clock_8MHz, ~th.mmcm_locked) {
|
||||||
|
// val clockToggleReg = RegInit(false.B)
|
||||||
|
// val (_, slowTick) = chisel3.util.Counter(true.B, 256)
|
||||||
|
// when (slowTick) {clockToggleReg := ~clockToggleReg}
|
||||||
|
// slow_clock := clockToggleReg
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// // DUT
|
||||||
|
// //-----------------------------------------------------------------------
|
||||||
|
// withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||||
|
//
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
// // SPI flash IOBUFs
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// IOBUF(th.qspi_sck, io_qspi.sck)
|
||||||
|
// IOBUF(th.qspi_cs, io_qspi.cs(0))
|
||||||
|
//
|
||||||
|
// IOBUF(th.qspi_dq(0), io_qspi.dq(0))
|
||||||
|
// IOBUF(th.qspi_dq(1), io_qspi.dq(1))
|
||||||
|
// IOBUF(th.qspi_dq(2), io_qspi.dq(2))
|
||||||
|
// IOBUF(th.qspi_dq(3), io_qspi.dq(3))
|
||||||
|
//
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
// // JTAG IOBUFs
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asUInt
|
||||||
|
//
|
||||||
|
// IOBUF(th.jd_5, io_jtag.TMS)
|
||||||
|
// PULLUP(th.jd_5)
|
||||||
|
//
|
||||||
|
// IOBUF(th.jd_4, io_jtag.TDI)
|
||||||
|
// PULLUP(th.jd_4)
|
||||||
|
//
|
||||||
|
// IOBUF(th.jd_0, io_jtag.TDO)
|
||||||
|
//
|
||||||
|
// // mimic putting a pullup on this line (part of reset vote)
|
||||||
|
// th.SRST_n := IOBUF(th.jd_6)
|
||||||
|
// PULLUP(th.jd_6)
|
||||||
|
//
|
||||||
|
// // jtag reset
|
||||||
|
// val jtag_power_on_reset = PowerOnResetFPGAOnly(th.clock_32MHz)
|
||||||
|
// io_jtag_reset := jtag_power_on_reset
|
||||||
|
//
|
||||||
|
// // debug reset
|
||||||
|
// th.dut_ndreset := io_ndreset
|
||||||
|
//
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
// // Assignment to package pins
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
// // Pins IO0-IO13
|
||||||
|
// //
|
||||||
|
// // FTDI UART TX/RX are not connected to th.ck_io[0,1]
|
||||||
|
// // the way they are on Arduino boards. We copy outgoing
|
||||||
|
// // data to both places, switch 3 (sw[3]) determines whether
|
||||||
|
// // input to UART comes from FTDI chip or gpio_16 (shield pin PD0)
|
||||||
|
//
|
||||||
|
// val iobuf_ck0 = Module(new IOBUF())
|
||||||
|
// iobuf_ck0.io.I := io_gpio.pins(16).o.oval
|
||||||
|
// iobuf_ck0.io.T := ~io_gpio.pins(16).o.oe
|
||||||
|
// attach(iobuf_ck0.io.IO, th.ck_io(0)) // UART0 RX
|
||||||
|
//
|
||||||
|
// val iobuf_uart_txd = Module(new IOBUF())
|
||||||
|
// iobuf_uart_txd.io.I := io_gpio.pins(16).o.oval
|
||||||
|
// iobuf_uart_txd.io.T := ~io_gpio.pins(16).o.oe
|
||||||
|
// attach(iobuf_uart_txd.io.IO, th.uart_txd_in)
|
||||||
|
//
|
||||||
|
// // gpio(16) input is shared between FTDI TX pin and the Arduino shield pin using SW[3]
|
||||||
|
// val sw_3_in = IOBUF(th.sw_3)
|
||||||
|
// io_gpio.pins(16).i.ival := Mux(sw_3_in,
|
||||||
|
// iobuf_ck0.io.O & io_gpio.pins(16).o.ie,
|
||||||
|
// iobuf_uart_txd.io.O & io_gpio.pins(16).o.ie)
|
||||||
|
//
|
||||||
|
// IOBUF(th.uart_rxd_out, io_gpio.pins(17))
|
||||||
|
//
|
||||||
|
// // Shield header row 0: PD2-PD7
|
||||||
|
// IOBUF(th.ck_io(2), io_gpio.pins(18))
|
||||||
|
// IOBUF(th.ck_io(3), io_gpio.pins(19)) // PWM1(1)
|
||||||
|
// IOBUF(th.ck_io(4), io_gpio.pins(20)) // PWM1(0)
|
||||||
|
// IOBUF(th.ck_io(5), io_gpio.pins(21)) // PWM1(2)
|
||||||
|
// IOBUF(th.ck_io(6), io_gpio.pins(22)) // PWM1(3)
|
||||||
|
// IOBUF(th.ck_io(7), io_gpio.pins(23))
|
||||||
|
//
|
||||||
|
// // Header row 1: PB0-PB5
|
||||||
|
// IOBUF(th.ck_io(8), io_gpio.pins(0)) // PWM0(0)
|
||||||
|
// IOBUF(th.ck_io(9), io_gpio.pins(1)) // PWM0(1)
|
||||||
|
// IOBUF(th.ck_io(10), io_gpio.pins(2)) // SPI CS(0) / PWM0(2)
|
||||||
|
// IOBUF(th.ck_io(11), io_gpio.pins(3)) // SPI MOSI / PWM0(3)
|
||||||
|
// IOBUF(th.ck_io(12), io_gpio.pins(4)) // SPI MISO
|
||||||
|
// IOBUF(th.ck_io(13), io_gpio.pins(5)) // SPI SCK
|
||||||
|
//
|
||||||
|
// io_gpio.pins(6).i.ival := 0.U
|
||||||
|
// io_gpio.pins(7).i.ival := 0.U
|
||||||
|
// io_gpio.pins(8).i.ival := 0.U
|
||||||
|
//
|
||||||
|
// // Header row 3: A0-A5 (we don't support using them as analog inputs)
|
||||||
|
// // just treat them as regular digital GPIOs
|
||||||
|
// IOBUF(th.ck_io(15), io_gpio.pins(9)) // A1 = CS(2)
|
||||||
|
// IOBUF(th.ck_io(16), io_gpio.pins(10)) // A2 = CS(3) / PWM2(0)
|
||||||
|
// IOBUF(th.ck_io(17), io_gpio.pins(11)) // A3 = PWM2(1)
|
||||||
|
// IOBUF(th.ck_io(18), io_gpio.pins(12)) // A4 = PWM2(2) / SDA
|
||||||
|
// IOBUF(th.ck_io(19), io_gpio.pins(13)) // A5 = PWM2(3) / SCL
|
||||||
|
//
|
||||||
|
// // Mirror outputs of GPIOs with PWM peripherals to RGB LEDs on Arty
|
||||||
|
// // assign RGB LED0 R,G,B inputs = PWM0(1,2,3) when iof_1 is active
|
||||||
|
// IOBUF(th.led0_r, io_gpio.pins(1))
|
||||||
|
// IOBUF(th.led0_g, io_gpio.pins(2))
|
||||||
|
// IOBUF(th.led0_b, io_gpio.pins(3))
|
||||||
|
//
|
||||||
|
// // Note that this is the one which is actually connected on the HiFive/Crazy88
|
||||||
|
// // Board. Same with RGB LED1 R,G,B inputs = PWM1(1,2,3) when iof_1 is active
|
||||||
|
// IOBUF(th.led1_r, io_gpio.pins(19))
|
||||||
|
// IOBUF(th.led1_g, io_gpio.pins(21))
|
||||||
|
// IOBUF(th.led1_b, io_gpio.pins(22))
|
||||||
|
//
|
||||||
|
// // and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active
|
||||||
|
// IOBUF(th.led2_r, io_gpio.pins(11))
|
||||||
|
// IOBUF(th.led2_g, io_gpio.pins(12))
|
||||||
|
// IOBUF(th.led2_b, io_gpio.pins(13))
|
||||||
|
//
|
||||||
|
// // Only 19 out of 20 shield pins connected to GPIO pins
|
||||||
|
// // Shield pin A5 (pin 14) left unconnected
|
||||||
|
// // The buttons are connected to some extra GPIO pins not connected on the
|
||||||
|
// // HiFive1 board
|
||||||
|
// IOBUF(th.btn_0, io_gpio.pins(15))
|
||||||
|
// IOBUF(th.btn_1, io_gpio.pins(30))
|
||||||
|
// IOBUF(th.btn_2, io_gpio.pins(31))
|
||||||
|
//
|
||||||
|
// val iobuf_btn_3 = Module(new IOBUF())
|
||||||
|
// iobuf_btn_3.io.I := ~io_aon.pmu.dwakeup_n.o.oval
|
||||||
|
// iobuf_btn_3.io.T := ~io_aon.pmu.dwakeup_n.o.oe
|
||||||
|
// attach(th.btn_3, iobuf_btn_3.io.IO)
|
||||||
|
// io_aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & io_aon.pmu.dwakeup_n.o.ie
|
||||||
|
//
|
||||||
|
// // UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1
|
||||||
|
// IOBUF(th.ja_0, io_gpio.pins(25)) // UART1 TX
|
||||||
|
// IOBUF(th.ja_1, io_gpio.pins(24)) // UART1 RX
|
||||||
|
//
|
||||||
|
// // SPI2 pins mapped to 6 pin ICSP connector (standard on later
|
||||||
|
// // arduinos) These are connected to some extra GPIO pins not connected
|
||||||
|
// // on the HiFive1 board
|
||||||
|
// IOBUF(th.ck_ss, io_gpio.pins(26))
|
||||||
|
// IOBUF(th.ck_mosi, io_gpio.pins(27))
|
||||||
|
// IOBUF(th.ck_miso, io_gpio.pins(28))
|
||||||
|
// IOBUF(th.ck_sck, io_gpio.pins(29))
|
||||||
|
//
|
||||||
|
// // Use the LEDs for some more useful debugging things
|
||||||
|
// IOBUF(th.led_0, th.ck_rst)
|
||||||
|
// IOBUF(th.led_1, th.SRST_n)
|
||||||
|
// IOBUF(th.led_2, io_aon.pmu.dwakeup_n.i.ival)
|
||||||
|
// IOBUF(th.led_3, io_gpio.pins(14))
|
||||||
|
//
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
// // Unconnected inputs
|
||||||
|
// //---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// io_aon.erst_n.i.ival := ~th.reset_periph
|
||||||
|
// io_aon.lfextclk.i.ival := slow_clock
|
||||||
|
// io_aon.pmu.vddpaden.i.ival := 1.U
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Nil
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Seq((Nil, Nil, Some(harnessFn)))
|
||||||
|
// }
|
||||||
|
//})
|
||||||
|
//
|
||||||
85
fpga/src/main/scala/vcu118/Configs.scala
Normal file
85
fpga/src/main/scala/vcu118/Configs.scala
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package chipyard.fpga.vcu118
|
||||||
|
|
||||||
|
import sys.process._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Config}
|
||||||
|
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
||||||
|
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
||||||
|
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
||||||
|
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet}
|
||||||
|
import freechips.rocketchip.tile.{XLen}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams}
|
||||||
|
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell.{DesignKey}
|
||||||
|
import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
|
||||||
|
|
||||||
|
class WithDefaultPeripherals extends Config((site, here, up) => {
|
||||||
|
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
||||||
|
case PeripherySPIKey => List(SPIParams(rAddress = BigInt(0x64001000L)))
|
||||||
|
case VCU118ShellPMOD => "SDIO"
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithSystemModifications extends Config((site, here, up) => {
|
||||||
|
case DebugModuleKey => None // disable debug module
|
||||||
|
case ExportDebug => up(ExportDebug).copy(protocols = Set(JTAG)) // don't generate HTIF DTS
|
||||||
|
case SystemBusKey => up(SystemBusKey).copy(
|
||||||
|
errorDevice = Some(DevNullParams(
|
||||||
|
Seq(AddressSet(0x3000, 0xfff)),
|
||||||
|
maxAtomic=site(XLen)/8,
|
||||||
|
maxTransfer=128,
|
||||||
|
region = RegionType.TRACKED)))
|
||||||
|
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency =
|
||||||
|
Some(BigDecimal(site(FPGAFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt))
|
||||||
|
case ControlBusKey => up(ControlBusKey, site).copy(
|
||||||
|
errorDevice = None)
|
||||||
|
case DTSTimebase => BigInt(1000000)
|
||||||
|
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
|
||||||
|
// invoke makefile for sdboot
|
||||||
|
val freqMHz = site(FPGAFrequencyKey).toInt * 1000000
|
||||||
|
val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin"
|
||||||
|
require (make.! == 0, "Failed to build bootrom")
|
||||||
|
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin")
|
||||||
|
}
|
||||||
|
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize))))
|
||||||
|
})
|
||||||
|
|
||||||
|
class AbstractVCU118Config extends Config(
|
||||||
|
new WithUART ++
|
||||||
|
new WithSPISDCard ++
|
||||||
|
new WithDDRMem ++
|
||||||
|
new WithUARTIOPassthrough ++
|
||||||
|
new WithSPIIOPassthrough ++
|
||||||
|
new WithTLIOPassthrough ++
|
||||||
|
new WithDefaultPeripherals ++
|
||||||
|
new WithSystemModifications ++ // remove debug module, setup busses, use sdboot bootrom, setup ext. mem. size
|
||||||
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
|
new chipyard.config.WithNoSubsystemDrivenClocks ++
|
||||||
|
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
|
||||||
|
new chipyard.config.WithL2TLBs(1024) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNoSlavePort ++
|
||||||
|
new freechips.rocketchip.subsystem.WithInclusiveCache ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
|
||||||
|
new chipyard.WithMulticlockCoherentBusTopology ++
|
||||||
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
class RocketVCU118Config extends Config(
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
|
new AbstractVCU118Config)
|
||||||
|
|
||||||
|
class BoomVCU118Config extends Config(
|
||||||
|
new WithFPGAFrequency(75) ++
|
||||||
|
new boom.common.WithNLargeBooms(1) ++
|
||||||
|
new AbstractVCU118Config)
|
||||||
|
|
||||||
|
class WithFPGAFrequency(MHz: Double) extends Config((site, here, up) => {
|
||||||
|
case FPGAFrequencyKey => MHz
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithFPGAFreq25MHz extends WithFPGAFrequency(25)
|
||||||
|
class WithFPGAFreq50MHz extends WithFPGAFrequency(50)
|
||||||
|
class WithFPGAFreq75MHz extends WithFPGAFrequency(75)
|
||||||
|
class WithFPGAFreq100MHz extends WithFPGAFrequency(100)
|
||||||
334
fpga/src/main/scala/vcu118/FMCUtil.scala
Normal file
334
fpga/src/main/scala/vcu118/FMCUtil.scala
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
package chipyard.fpga.vcu118
|
||||||
|
|
||||||
|
import scala.collection.immutable.HashMap
|
||||||
|
|
||||||
|
// TODO: was typed by hand, so this needs a once-over before it can be considered trustworthy
|
||||||
|
|
||||||
|
object FMCMap {
|
||||||
|
// Take an FMC pin name and return the VCU118 package pin
|
||||||
|
// See https://www.xilinx.com/support/documentation/boards_and_kits/vcu118/ug1224-vcu118-eval-bd.pdf
|
||||||
|
// Pages 97-98
|
||||||
|
// Omitted pins are not connected to a GPIO
|
||||||
|
def apply(fmcPin: String): String = HashMap(
|
||||||
|
"C10" -> "BD13",
|
||||||
|
"C11" -> "BE13",
|
||||||
|
"C14" -> "BB13",
|
||||||
|
"C15" -> "BB12",
|
||||||
|
"C18" -> "AW8",
|
||||||
|
"C19" -> "AW7",
|
||||||
|
"C22" -> "AP12",
|
||||||
|
"C23" -> "AR12",
|
||||||
|
"C26" -> "AL14",
|
||||||
|
"C27" -> "AM14",
|
||||||
|
"D1" -> "AK35",
|
||||||
|
"D8" -> "BF10",
|
||||||
|
"D9" -> "BF9",
|
||||||
|
"D11" -> "BE14",
|
||||||
|
"D12" -> "BF14",
|
||||||
|
"D14" -> "BA14",
|
||||||
|
"D15" -> "BB14",
|
||||||
|
"D17" -> "AY8",
|
||||||
|
"D18" -> "AY7",
|
||||||
|
"D20" -> "AR14",
|
||||||
|
"D21" -> "AT14",
|
||||||
|
"D23" -> "AN16",
|
||||||
|
"D24" -> "AP16",
|
||||||
|
"D26" -> "AK15",
|
||||||
|
"D27" -> "AL15",
|
||||||
|
"F1" -> "BA7",
|
||||||
|
"G2" -> "AV14",
|
||||||
|
"G3" -> "AV13",
|
||||||
|
"G6" -> "AY9",
|
||||||
|
"G7" -> "BA9",
|
||||||
|
"G9" -> "BD12",
|
||||||
|
"G10" -> "BE12",
|
||||||
|
"G12" -> "BE15",
|
||||||
|
"G13" -> "BF15",
|
||||||
|
"G15" -> "BC14",
|
||||||
|
"G16" -> "BC13",
|
||||||
|
"G18" -> "AV9",
|
||||||
|
"G19" -> "AV8",
|
||||||
|
"G21" -> "AW11",
|
||||||
|
"G22" -> "AY10",
|
||||||
|
"G24" -> "AW13",
|
||||||
|
"G25" -> "AY13",
|
||||||
|
"G27" -> "AT12",
|
||||||
|
"G28" -> "AU12",
|
||||||
|
"G30" -> "AN15",
|
||||||
|
"G31" -> "AP15",
|
||||||
|
"G33" -> "AM13",
|
||||||
|
"G34" -> "AM12",
|
||||||
|
"G36" -> "AK14",
|
||||||
|
"G37" -> "AK13",
|
||||||
|
"H2" -> "BB7",
|
||||||
|
"H4" -> "BC9",
|
||||||
|
"H5" -> "BC8",
|
||||||
|
"H7" -> "BC11",
|
||||||
|
"H8" -> "BD11",
|
||||||
|
"H10" -> "BF12",
|
||||||
|
"H11" -> "BF11",
|
||||||
|
"H13" -> "BC15",
|
||||||
|
"H14" -> "BD15",
|
||||||
|
"H16" -> "BA16",
|
||||||
|
"H17" -> "BA15",
|
||||||
|
"H19" -> "BB16",
|
||||||
|
"H20" -> "BC16",
|
||||||
|
"H22" -> "AW12",
|
||||||
|
"H23" -> "AY12",
|
||||||
|
"H25" -> "AU11",
|
||||||
|
"H26" -> "AV11",
|
||||||
|
"H28" -> "AP13",
|
||||||
|
"H29" -> "AR13",
|
||||||
|
"H31" -> "AV10",
|
||||||
|
"H32" -> "AW10",
|
||||||
|
"H34" -> "AK12",
|
||||||
|
"H35" -> "AL12",
|
||||||
|
"H37" -> "AJ13",
|
||||||
|
"H38" -> "AJ12"
|
||||||
|
)(fmcPin)
|
||||||
|
}
|
||||||
|
|
||||||
|
object FMCPMap {
|
||||||
|
// Take an FMC+ pin name and return the VCU118 package pin
|
||||||
|
// See https://www.xilinx.com/support/documentation/boards_and_kits/vcu118/ug1224-vcu118-eval-bd.pdf
|
||||||
|
// Pages 100-106
|
||||||
|
// Omitted pins are not connected to a GPIO
|
||||||
|
def apply(fmcpPin: String): String = HashMap(
|
||||||
|
"A2" -> "AN45",
|
||||||
|
"A3" -> "AN46",
|
||||||
|
"A6" -> "AL45",
|
||||||
|
"A7" -> "AL45",
|
||||||
|
"A10" -> "AJ45",
|
||||||
|
"A11" -> "AJ46",
|
||||||
|
"A14" -> "W45",
|
||||||
|
"A15" -> "W46",
|
||||||
|
"A18" -> "U45",
|
||||||
|
"A19" -> "U46",
|
||||||
|
"A22" -> "AP42",
|
||||||
|
"A23" -> "AP43",
|
||||||
|
"A26" -> "AM42",
|
||||||
|
"A27" -> "AM43",
|
||||||
|
"A30" -> "AL40",
|
||||||
|
"A31" -> "AL41",
|
||||||
|
"A34" -> "T42",
|
||||||
|
"A35" -> "T43",
|
||||||
|
"A38" -> "P42",
|
||||||
|
"A39" -> "P43",
|
||||||
|
"B4" -> "AF43",
|
||||||
|
"B5" -> "AF44",
|
||||||
|
"B8" -> "AG45",
|
||||||
|
"B9" -> "AG46",
|
||||||
|
"B12" -> "N45",
|
||||||
|
"B13" -> "N46",
|
||||||
|
"B16" -> "R45",
|
||||||
|
"B17" -> "R46",
|
||||||
|
"B24" -> "AJ40",
|
||||||
|
"B25" -> "AJ41",
|
||||||
|
"B28" -> "AK42",
|
||||||
|
"B29" -> "AK43",
|
||||||
|
"B32" -> "K42",
|
||||||
|
"B33" -> "K43",
|
||||||
|
"B36" -> "M42",
|
||||||
|
"B37" -> "M43",
|
||||||
|
"C2" -> "AT42",
|
||||||
|
"C3" -> "AT43",
|
||||||
|
"C6" -> "AR45",
|
||||||
|
"C7" -> "AR46",
|
||||||
|
"C10" -> "AT35",
|
||||||
|
"C11" -> "AT36",
|
||||||
|
"C14" -> "AP35",
|
||||||
|
"C15" -> "AR35",
|
||||||
|
"C18" -> "AG31",
|
||||||
|
"C19" -> "AH31",
|
||||||
|
"C22" -> "R31",
|
||||||
|
"C23" -> "P31",
|
||||||
|
"C26" -> "V33",
|
||||||
|
"C27" -> "V34",
|
||||||
|
"D1" -> "AK35",
|
||||||
|
"D8" -> "AL30",
|
||||||
|
"D9" -> "AL31",
|
||||||
|
"D11" -> "AP38",
|
||||||
|
"D12" -> "AR38",
|
||||||
|
"D14" -> "AJ33",
|
||||||
|
"D15" -> "AK33",
|
||||||
|
"D17" -> "AJ35",
|
||||||
|
"D18" -> "AJ36",
|
||||||
|
"D20" -> "R34",
|
||||||
|
"D21" -> "P34",
|
||||||
|
"D23" -> "Y32",
|
||||||
|
"D24" -> "W32",
|
||||||
|
"D26" -> "V32",
|
||||||
|
"D27" -> "U33",
|
||||||
|
"E2" -> "V15",
|
||||||
|
"E3" -> "U15",
|
||||||
|
"E6" -> "R14",
|
||||||
|
"E7" -> "P14",
|
||||||
|
"E9" -> "W14",
|
||||||
|
"E10" -> "V14",
|
||||||
|
"E12" -> "V13",
|
||||||
|
"E13" -> "U12",
|
||||||
|
"E15" -> "T14",
|
||||||
|
"E16" -> "R13",
|
||||||
|
"E18" -> "M15",
|
||||||
|
"E19" -> "L15",
|
||||||
|
"F1" -> "AM34",
|
||||||
|
"F4" -> "N14",
|
||||||
|
"F5" -> "N13",
|
||||||
|
"F7" -> "AA13",
|
||||||
|
"F8" -> "Y13",
|
||||||
|
"F10" -> "U11",
|
||||||
|
"F11" -> "T11",
|
||||||
|
"F13" -> "T16",
|
||||||
|
"F14" -> "T15",
|
||||||
|
"F16" -> "M13",
|
||||||
|
"F17" -> "M12",
|
||||||
|
"F19" -> "L14",
|
||||||
|
"F20" -> "L13",
|
||||||
|
"G2" -> "P35",
|
||||||
|
"G3" -> "P36",
|
||||||
|
"G6" -> "AL35",
|
||||||
|
"G7" -> "AL36",
|
||||||
|
"G9" -> "AT39",
|
||||||
|
"G10" -> "AT40",
|
||||||
|
"G12" -> "AK29",
|
||||||
|
"G13" -> "AK30",
|
||||||
|
"G15" -> "AH33",
|
||||||
|
"G16" -> "AH34",
|
||||||
|
"G18" -> "AG34",
|
||||||
|
"G19" -> "AH35",
|
||||||
|
"G21" -> "N32",
|
||||||
|
"G22" -> "M32",
|
||||||
|
"G24" -> "N34",
|
||||||
|
"G25" -> "N35",
|
||||||
|
"G27" -> "Y34",
|
||||||
|
"G28" -> "W34",
|
||||||
|
"G30" -> "U35",
|
||||||
|
"G31" -> "T36",
|
||||||
|
"G33" -> "P37",
|
||||||
|
"G34" -> "N37",
|
||||||
|
"G36" -> "L34",
|
||||||
|
"G37" -> "K34",
|
||||||
|
"H2" -> "AM33",
|
||||||
|
"H4" -> "AL32",
|
||||||
|
"H5" -> "AM32",
|
||||||
|
"H7" -> "AJ32",
|
||||||
|
"H8" -> "AK32",
|
||||||
|
"H10" -> "AR37",
|
||||||
|
"H11" -> "AT37",
|
||||||
|
"H13" -> "AP36",
|
||||||
|
"H14" -> "AP37",
|
||||||
|
"H16" -> "AJ30",
|
||||||
|
"H17" -> "AJ31",
|
||||||
|
"H19" -> "AG32",
|
||||||
|
"H20" -> "AG33",
|
||||||
|
"H22" -> "N33",
|
||||||
|
"H23" -> "M33",
|
||||||
|
"H25" -> "M35",
|
||||||
|
"H26" -> "L35",
|
||||||
|
"H28" -> "T34",
|
||||||
|
"H29" -> "T35",
|
||||||
|
"H31" -> "M36",
|
||||||
|
"H32" -> "L36",
|
||||||
|
"H34" -> "N38",
|
||||||
|
"H35" -> "M38",
|
||||||
|
"H37" -> "L33",
|
||||||
|
"H38" -> "K33",
|
||||||
|
"J6" -> "W12",
|
||||||
|
"J7" -> "V12",
|
||||||
|
"J9" -> "AA14",
|
||||||
|
"J10" -> "Y14",
|
||||||
|
"J12" -> "R12",
|
||||||
|
"J13" -> "P12",
|
||||||
|
"J15" -> "M11",
|
||||||
|
"J16" -> "L11",
|
||||||
|
"J18" -> "P15",
|
||||||
|
"J19" -> "N15",
|
||||||
|
"J21" -> "K12",
|
||||||
|
"J22" -> "J12",
|
||||||
|
"K7" -> "AA12",
|
||||||
|
"K8" -> "Y12",
|
||||||
|
"K10" -> "U13",
|
||||||
|
"K11" -> "T13",
|
||||||
|
"K13" -> "V16",
|
||||||
|
"K14" -> "U16",
|
||||||
|
"K16" -> "R11",
|
||||||
|
"K17" -> "P11",
|
||||||
|
"K19" -> "K14",
|
||||||
|
"K20" -> "K13",
|
||||||
|
"K22" -> "K11",
|
||||||
|
"K23" -> "J11",
|
||||||
|
"L4" -> "R40",
|
||||||
|
"L5" -> "R41",
|
||||||
|
"L8" -> "AB38",
|
||||||
|
"L9" -> "AB39",
|
||||||
|
"L12" -> "AF38",
|
||||||
|
"L13" -> "AF39",
|
||||||
|
"L16" -> "AN34",
|
||||||
|
"L17" -> "AN35",
|
||||||
|
"L20" -> "AN33",
|
||||||
|
"L21" -> "AP33",
|
||||||
|
"L24" -> "AK34",
|
||||||
|
"L25" -> "AL34",
|
||||||
|
"L28" -> "AM36",
|
||||||
|
"L29" -> "AN36",
|
||||||
|
"M2" -> "AU45",
|
||||||
|
"M3" -> "AU46",
|
||||||
|
"M6" -> "AW45",
|
||||||
|
"M7" -> "AW46",
|
||||||
|
"M10" -> "BA45",
|
||||||
|
"M11" -> "BA46",
|
||||||
|
"M14" -> "BC45",
|
||||||
|
"M15" -> "BC46",
|
||||||
|
"M18" -> "W40",
|
||||||
|
"M19" -> "W41",
|
||||||
|
"M22" -> "U40",
|
||||||
|
"M23" -> "U41",
|
||||||
|
"M26" -> "H42",
|
||||||
|
"M27" -> "H43",
|
||||||
|
"M30" -> "F42",
|
||||||
|
"M31" -> "F43",
|
||||||
|
"M34" -> "D42",
|
||||||
|
"M35" -> "D43",
|
||||||
|
"M38" -> "B42",
|
||||||
|
"M39" -> "B43",
|
||||||
|
"Y2" -> "AV42",
|
||||||
|
"Y3" -> "AV43",
|
||||||
|
"Y6" -> "BB42",
|
||||||
|
"Y7" -> "BB43",
|
||||||
|
"Y10" -> "AE45",
|
||||||
|
"Y11" -> "AE46",
|
||||||
|
"Y14" -> "AC45",
|
||||||
|
"Y15" -> "AC46",
|
||||||
|
"Y18" -> "AA45",
|
||||||
|
"Y19" -> "AA46",
|
||||||
|
"Y22" -> "Y43",
|
||||||
|
"Y23" -> "Y44",
|
||||||
|
"Y26" -> "AE40",
|
||||||
|
"Y27" -> "AE41",
|
||||||
|
"Y30" -> "AA40",
|
||||||
|
"Y31" -> "AA41",
|
||||||
|
"Y34" -> "J45",
|
||||||
|
"Y35" -> "J46",
|
||||||
|
"Y38" -> "E45",
|
||||||
|
"Y39" -> "E46",
|
||||||
|
"Z1" -> "AM29",
|
||||||
|
"Z4" -> "AY42",
|
||||||
|
"Z5" -> "AY43",
|
||||||
|
"Z8" -> "BD42",
|
||||||
|
"Z9" -> "BD43",
|
||||||
|
"Z12" -> "AD43",
|
||||||
|
"Z13" -> "AD44",
|
||||||
|
"Z16" -> "AB43",
|
||||||
|
"Z17" -> "AB44",
|
||||||
|
"Z20" -> "AN40",
|
||||||
|
"Z21" -> "AN41",
|
||||||
|
"Z24" -> "AG40",
|
||||||
|
"Z25" -> "AG41",
|
||||||
|
"Z28" -> "AC40",
|
||||||
|
"Z29" -> "AC41",
|
||||||
|
"Z32" -> "L45",
|
||||||
|
"Z33" -> "L46",
|
||||||
|
"Z36" -> "G45",
|
||||||
|
"Z37" -> "G46"
|
||||||
|
)(fmcpPin)
|
||||||
|
}
|
||||||
51
fpga/src/main/scala/vcu118/HarnessBinders.scala
Normal file
51
fpga/src/main/scala/vcu118/HarnessBinders.scala
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package chipyard.fpga.vcu118
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{BaseModule}
|
||||||
|
|
||||||
|
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||||
|
import freechips.rocketchip.tilelink.{TLBundle}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
||||||
|
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||||
|
|
||||||
|
import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences}
|
||||||
|
import chipyard.harness.{OverrideHarnessBinder}
|
||||||
|
|
||||||
|
/*** UART ***/
|
||||||
|
class WithUART extends OverrideHarnessBinder({
|
||||||
|
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||||
|
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||||
|
vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*** SPI ***/
|
||||||
|
class WithSPISDCard extends OverrideHarnessBinder({
|
||||||
|
(system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => {
|
||||||
|
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||||
|
vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*** Experimental DDR ***/
|
||||||
|
class WithDDRMem extends OverrideHarnessBinder({
|
||||||
|
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
|
||||||
|
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||||
|
require(ports.size == 1)
|
||||||
|
|
||||||
|
val bundles = vcu118th.vcu118Outer.ddrClient.out.map(_._1)
|
||||||
|
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||||
|
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||||
|
ddrClientBundle <> ports.head
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
52
fpga/src/main/scala/vcu118/IOBinders.scala
Normal file
52
fpga/src/main/scala/vcu118/IOBinders.scala
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package chipyard.fpga.vcu118
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{IO, DataMirror}
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody}
|
||||||
|
import freechips.rocketchip.subsystem.{BaseSubsystem}
|
||||||
|
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||||
|
import freechips.rocketchip.tilelink.{TLBundle}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp}
|
||||||
|
import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice}
|
||||||
|
|
||||||
|
import chipyard.{CanHaveMasterTLMemPort}
|
||||||
|
import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder}
|
||||||
|
|
||||||
|
class WithUARTIOPassthrough extends OverrideIOBinder({
|
||||||
|
(system: HasPeripheryUARTModuleImp) => {
|
||||||
|
val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") }
|
||||||
|
(io_uart_pins_temp zip system.uart).map { case (io, sysio) =>
|
||||||
|
io <> sysio
|
||||||
|
}
|
||||||
|
(io_uart_pins_temp, Nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithSPIIOPassthrough extends OverrideLazyIOBinder({
|
||||||
|
(system: HasPeripherySPI) => {
|
||||||
|
// attach resource to 1st SPI
|
||||||
|
ResourceBinding {
|
||||||
|
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
InModuleBody {
|
||||||
|
system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => {
|
||||||
|
val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") }
|
||||||
|
(io_spi_pins_temp zip system.spi).map { case (io, sysio) =>
|
||||||
|
io <> sysio
|
||||||
|
}
|
||||||
|
(io_spi_pins_temp, Nil)
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithTLIOPassthrough extends OverrideIOBinder({
|
||||||
|
(system: CanHaveMasterTLMemPort) => {
|
||||||
|
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")
|
||||||
|
io_tl_mem_pins_temp <> system.mem_tl
|
||||||
|
(Seq(io_tl_mem_pins_temp), Nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
144
fpga/src/main/scala/vcu118/TestHarness.scala
Normal file
144
fpga/src/main/scala/vcu118/TestHarness.scala
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package chipyard.fpga.vcu118
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{IO}
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell.xilinx._
|
||||||
|
import sifive.fpgashells.ip.xilinx._
|
||||||
|
import sifive.fpgashells.shell._
|
||||||
|
import sifive.fpgashells.clocks._
|
||||||
|
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
|
||||||
|
import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop}
|
||||||
|
import chipyard.iobinders.{HasIOBinders}
|
||||||
|
import chipyard.harness.{ApplyHarnessBinders}
|
||||||
|
|
||||||
|
case object FPGAFrequencyKey extends Field[Double](100.0)
|
||||||
|
|
||||||
|
class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays {
|
||||||
|
|
||||||
|
def dp = designParameters
|
||||||
|
|
||||||
|
val pmod_is_sdio = p(VCU118ShellPMOD) == "SDIO"
|
||||||
|
val jtag_location = Some(if (pmod_is_sdio) "FMC_J2" else "PMOD_J52")
|
||||||
|
|
||||||
|
// Order matters; ddr depends on sys_clock
|
||||||
|
val uart = Overlay(UARTOverlayKey, new UARTVCU118ShellPlacer(this, UARTShellInput()))
|
||||||
|
val sdio = if (pmod_is_sdio) Some(Overlay(SPIOverlayKey, new SDIOVCU118ShellPlacer(this, SPIShellInput()))) else None
|
||||||
|
val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugVCU118ShellPlacer(this, JTAGDebugShellInput(location = jtag_location)))
|
||||||
|
val cjtag = Overlay(cJTAGDebugOverlayKey, new cJTAGDebugVCU118ShellPlacer(this, cJTAGDebugShellInput()))
|
||||||
|
val jtagBScan = Overlay(JTAGDebugBScanOverlayKey, new JTAGDebugBScanVCU118ShellPlacer(this, JTAGDebugBScanShellInput()))
|
||||||
|
val fmc = Overlay(PCIeOverlayKey, new PCIeVCU118FMCShellPlacer(this, PCIeShellInput()))
|
||||||
|
val edge = Overlay(PCIeOverlayKey, new PCIeVCU118EdgeShellPlacer(this, PCIeShellInput()))
|
||||||
|
|
||||||
|
val topDesign = LazyModule(p(BuildTop)(dp))
|
||||||
|
|
||||||
|
// place all clocks in the shell
|
||||||
|
dp(ClockInputOverlayKey).foreach { _.place(ClockInputDesignInput()) }
|
||||||
|
|
||||||
|
/*** Connect/Generate clocks ***/
|
||||||
|
|
||||||
|
// connect to the PLL that will generate multiple clocks
|
||||||
|
val harnessSysPLL = dp(PLLFactoryKey)()
|
||||||
|
sys_clock.get() match {
|
||||||
|
case Some(x : SysClockVCU118PlacedOverlay) => {
|
||||||
|
harnessSysPLL := x.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and connect to the dutClock
|
||||||
|
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
|
||||||
|
val dutWrangler = LazyModule(new ResetWrangler)
|
||||||
|
val dutGroup = ClockGroup()
|
||||||
|
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
|
||||||
|
|
||||||
|
// connect ref clock to dummy sink node
|
||||||
|
ref_clock.get() match {
|
||||||
|
case Some(x : RefClockVCU118PlacedOverlay) => {
|
||||||
|
val sink = ClockSinkNode(Seq(ClockSinkParameters()))
|
||||||
|
sink := x.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** UART ***/
|
||||||
|
|
||||||
|
// 1st UART goes to the VCU118 dedicated UART
|
||||||
|
|
||||||
|
val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head)))
|
||||||
|
dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
|
||||||
|
|
||||||
|
/*** SPI ***/
|
||||||
|
|
||||||
|
// 1st SPI goes to the VCU118 SDIO port
|
||||||
|
|
||||||
|
val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head)))
|
||||||
|
dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb))
|
||||||
|
|
||||||
|
/*** DDR ***/
|
||||||
|
|
||||||
|
val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL))
|
||||||
|
|
||||||
|
// connect 1 mem. channel to the FPGA DDR
|
||||||
|
val inParams = topDesign match { case td: ChipTop =>
|
||||||
|
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
|
||||||
|
lsys.memTLNode.edges.in(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val ddrClient = TLClientNode(Seq(inParams.master))
|
||||||
|
ddrPlaced.overlayOutput.ddr := ddrClient
|
||||||
|
|
||||||
|
// module implementation
|
||||||
|
override lazy val module = new VCU118FPGATestHarnessImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences {
|
||||||
|
|
||||||
|
val vcu118Outer = _outer
|
||||||
|
|
||||||
|
val reset = IO(Input(Bool()))
|
||||||
|
_outer.xdc.addPackagePin(reset, "L19")
|
||||||
|
_outer.xdc.addIOStandard(reset, "LVCMOS12")
|
||||||
|
|
||||||
|
val reset_ibuf = Module(new IBUF)
|
||||||
|
reset_ibuf.io.I := reset
|
||||||
|
|
||||||
|
val sysclk: Clock = _outer.sys_clock.get() match {
|
||||||
|
case Some(x: SysClockVCU118PlacedOverlay) => x.clock
|
||||||
|
}
|
||||||
|
|
||||||
|
val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
|
||||||
|
_outer.sdc.addAsyncPath(Seq(powerOnReset))
|
||||||
|
|
||||||
|
val ereset: Bool = _outer.chiplink.get() match {
|
||||||
|
case Some(x: ChipLinkVCU118PlacedOverlay) => !x.ereset_n
|
||||||
|
case _ => false.B
|
||||||
|
}
|
||||||
|
|
||||||
|
_outer.pllReset := (reset_ibuf.io.O || powerOnReset || ereset)
|
||||||
|
|
||||||
|
// cy stuff
|
||||||
|
val harnessClock = _outer.dutClock.in.head._1.clock
|
||||||
|
val harnessReset = WireInit(_outer.dutClock.in.head._1.reset)
|
||||||
|
val dutReset = harnessReset
|
||||||
|
val success = false.B
|
||||||
|
|
||||||
|
childClock := harnessClock
|
||||||
|
childReset := harnessReset
|
||||||
|
|
||||||
|
// harness binders are non-lazy
|
||||||
|
_outer.topDesign match { case d: HasTestHarnessFunctions =>
|
||||||
|
d.harnessFunctions.foreach(_(this))
|
||||||
|
}
|
||||||
|
_outer.topDesign match { case d: HasIOBinders =>
|
||||||
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
28
fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala
Normal file
28
fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import scala.collection.mutable.{LinkedHashMap}
|
||||||
|
|
||||||
|
object BringupGPIOs {
|
||||||
|
// map of the pin name (akin to die pin name) to (fpga package pin, IOSTANDARD)
|
||||||
|
val pinMapping = LinkedHashMap(
|
||||||
|
// these connect to LEDs and switches on the VCU118 (and use 1.2V)
|
||||||
|
"led0" -> ("AT32", "LVCMOS12"), // 0
|
||||||
|
"led1" -> ("AV34", "LVCMOS12"), // 1
|
||||||
|
"led2" -> ("AY30", "LVCMOS12"), // 2
|
||||||
|
"led3" -> ("BB32", "LVCMOS12"), // 3
|
||||||
|
"led4" -> ("BF32", "LVCMOS12"), // 4
|
||||||
|
"led5" -> ("AU37", "LVCMOS12"), // 5
|
||||||
|
"led6" -> ("AV36", "LVCMOS12"), // 6
|
||||||
|
"led7" -> ("BA37", "LVCMOS12"), // 7
|
||||||
|
"sw0" -> ("B17", "LVCMOS12"), // 8
|
||||||
|
"sw1" -> ("G16", "LVCMOS12"), // 9
|
||||||
|
"sw2" -> ("J16", "LVCMOS12"), // 10
|
||||||
|
"sw3" -> ("D21", "LVCMOS12") // 11
|
||||||
|
)
|
||||||
|
|
||||||
|
// return list of names (ordered)
|
||||||
|
def names: Seq[String] = pinMapping.keys.toSeq
|
||||||
|
|
||||||
|
// return number of GPIOs
|
||||||
|
def width: Int = pinMapping.size
|
||||||
|
}
|
||||||
52
fpga/src/main/scala/vcu118/bringup/Configs.scala
Normal file
52
fpga/src/main/scala/vcu118/bringup/Configs.scala
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import math.min
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Config}
|
||||||
|
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.gpio.{PeripheryGPIOKey, GPIOParams}
|
||||||
|
import sifive.blocks.devices.i2c.{PeripheryI2CKey, I2CParams}
|
||||||
|
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams}
|
||||||
|
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell.{DesignKey}
|
||||||
|
import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
|
||||||
|
|
||||||
|
import chipyard.fpga.vcu118.{RocketVCU118Config, BoomVCU118Config}
|
||||||
|
|
||||||
|
class WithBringupPeripherals extends Config((site, here, up) => {
|
||||||
|
case PeripheryUARTKey => up(PeripheryUARTKey, site) ++ List(UARTParams(address = BigInt(0x64003000L)))
|
||||||
|
case PeripherySPIKey => up(PeripherySPIKey, site) ++ List(SPIParams(rAddress = BigInt(0x64004000L)))
|
||||||
|
case PeripheryI2CKey => List(I2CParams(address = BigInt(0x64005000L)))
|
||||||
|
case PeripheryGPIOKey => {
|
||||||
|
if (BringupGPIOs.width > 0) {
|
||||||
|
require(BringupGPIOs.width <= 64) // currently only support 64 GPIOs (change addrs to get more)
|
||||||
|
val gpioAddrs = Seq(BigInt(0x64002000), BigInt(0x64007000))
|
||||||
|
val maxGPIOSupport = 32 // max gpios supported by SiFive driver (split by 32)
|
||||||
|
List.tabulate(((BringupGPIOs.width - 1)/maxGPIOSupport) + 1)(n => {
|
||||||
|
GPIOParams(address = gpioAddrs(n), width = min(BringupGPIOs.width - maxGPIOSupport*n, maxGPIOSupport))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List.empty[GPIOParams]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithBringupAdditions extends Config(
|
||||||
|
new WithBringupUART ++
|
||||||
|
new WithBringupSPI ++
|
||||||
|
new WithBringupI2C ++
|
||||||
|
new WithBringupGPIO ++
|
||||||
|
new WithI2CIOPassthrough ++
|
||||||
|
new WithGPIOIOPassthrough ++
|
||||||
|
new WithBringupPeripherals)
|
||||||
|
|
||||||
|
class RocketBringupConfig extends Config(
|
||||||
|
new WithBringupPeripherals ++
|
||||||
|
new RocketVCU118Config)
|
||||||
|
|
||||||
|
class BoomBringupConfig extends Config(
|
||||||
|
new WithBringupPeripherals ++
|
||||||
|
new BoomVCU118Config)
|
||||||
147
fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala
Normal file
147
fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{attach}
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell._
|
||||||
|
import sifive.fpgashells.ip.xilinx._
|
||||||
|
import sifive.fpgashells.shell.xilinx._
|
||||||
|
|
||||||
|
import chipyard.fpga.vcu118.{FMCPMap}
|
||||||
|
|
||||||
|
/* Connect the I2C to certain FMC pins */
|
||||||
|
class BringupI2CVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput)
|
||||||
|
extends I2CXilinxPlacedOverlay(name, designInput, shellInput)
|
||||||
|
{
|
||||||
|
shell { InModuleBody {
|
||||||
|
require(shellInput.index == 0) // only support 1 I2C <-> FMC connection
|
||||||
|
val i2cLocations = List(List(FMCPMap("K11"), FMCPMap("E2")))
|
||||||
|
val packagePinsWithPackageIOs = Seq((i2cLocations(shellInput.index)(0), IOPin(io.scl)),
|
||||||
|
(i2cLocations(shellInput.index)(1), IOPin(io.sda)))
|
||||||
|
|
||||||
|
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||||
|
shell.xdc.addPackagePin(io, pin)
|
||||||
|
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||||
|
shell.xdc.addIOB(io)
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupI2CVCU118ShellPlacer(val shell: VCU118ShellBasicOverlays, val shellInput: I2CShellInput)(implicit val valName: ValName)
|
||||||
|
extends I2CShellPlacer[VCU118ShellBasicOverlays]
|
||||||
|
{
|
||||||
|
def place(designInput: I2CDesignInput) = new BringupI2CVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect the UART to certain FMC pins */
|
||||||
|
class BringupUARTVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput)
|
||||||
|
extends UARTXilinxPlacedOverlay(name, designInput, shellInput, true)
|
||||||
|
{
|
||||||
|
shell { InModuleBody {
|
||||||
|
val packagePinsWithPackageIOs = Seq((FMCPMap("E9"), IOPin(io.ctsn.get)), // unused
|
||||||
|
(FMCPMap("E10"), IOPin(io.rtsn.get)), // unused
|
||||||
|
(FMCPMap("C15"), IOPin(io.rxd)),
|
||||||
|
(FMCPMap("C14"), IOPin(io.txd)))
|
||||||
|
|
||||||
|
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||||
|
shell.xdc.addPackagePin(io, pin)
|
||||||
|
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||||
|
shell.xdc.addIOB(io)
|
||||||
|
} }
|
||||||
|
|
||||||
|
// add pullup on ctsn (ctsn is an input that is not used or driven)
|
||||||
|
packagePinsWithPackageIOs take 1 foreach { case (pin, io) => {
|
||||||
|
shell.xdc.addPullup(io)
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupUARTVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: UARTShellInput)(implicit val valName: ValName)
|
||||||
|
extends UARTShellPlacer[VCU118ShellBasicOverlays] {
|
||||||
|
def place(designInput: UARTDesignInput) = new BringupUARTVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect SPI to ADI device */
|
||||||
|
class BringupSPIVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: SPIDesignInput, val shellInput: SPIShellInput)
|
||||||
|
extends SDIOXilinxPlacedOverlay(name, designInput, shellInput)
|
||||||
|
{
|
||||||
|
shell { InModuleBody {
|
||||||
|
val packagePinsWithPackageIOs = Seq((FMCPMap("H37"), IOPin(io.spi_clk)),
|
||||||
|
(FMCPMap("H19"), IOPin(io.spi_cs)),
|
||||||
|
(FMCPMap("H17"), IOPin(io.spi_dat(0))),
|
||||||
|
(FMCPMap("H28"), IOPin(io.spi_dat(1))),
|
||||||
|
(FMCPMap("H29"), IOPin(io.spi_dat(2))),
|
||||||
|
(FMCPMap("H16"), IOPin(io.spi_dat(3))))
|
||||||
|
|
||||||
|
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||||
|
shell.xdc.addPackagePin(io, pin)
|
||||||
|
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||||
|
} }
|
||||||
|
packagePinsWithPackageIOs drop 1 foreach { case (pin, io) => {
|
||||||
|
shell.xdc.addPullup(io)
|
||||||
|
shell.xdc.addIOB(io)
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupSPIVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: SPIShellInput)(implicit val valName: ValName)
|
||||||
|
extends SPIShellPlacer[VCU118ShellBasicOverlays] {
|
||||||
|
def place(designInput: SPIDesignInput) = new BringupSPIVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this to a different location
|
||||||
|
// SPI device description for ADI part
|
||||||
|
class ADISPIDevice(spi: Device, maxMHz: Double = 1) extends SimpleDevice("clkgen", Seq("analog,adi9516-4")) {
|
||||||
|
override def parent = Some(spi)
|
||||||
|
override def describe(resources: ResourceBindings): Description = {
|
||||||
|
val Description(name, mapping) = super.describe(resources)
|
||||||
|
val extra = Map("spi-max-frequency" -> Seq(ResourceInt(maxMHz * 1000000)))
|
||||||
|
Description(name, mapping ++ extra)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect GPIOs to FMC */
|
||||||
|
abstract class GPIOXilinxPlacedOverlay(name: String, di: GPIODesignInput, si: GPIOShellInput)
|
||||||
|
extends GPIOPlacedOverlay(name, di, si)
|
||||||
|
{
|
||||||
|
def shell: XilinxShell
|
||||||
|
|
||||||
|
shell { InModuleBody {
|
||||||
|
(io.gpio zip tlgpioSink.bundle.pins).map { case (ioPin, sinkPin) =>
|
||||||
|
val iobuf = Module(new IOBUF)
|
||||||
|
iobuf.suggestName(s"gpio_iobuf")
|
||||||
|
attach(ioPin, iobuf.io.IO)
|
||||||
|
sinkPin.i.ival := iobuf.io.O
|
||||||
|
iobuf.io.T := !sinkPin.o.oe
|
||||||
|
iobuf.io.I := sinkPin.o.oval
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupGPIOVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String])
|
||||||
|
extends GPIOXilinxPlacedOverlay(name, designInput, shellInput)
|
||||||
|
{
|
||||||
|
shell { InModuleBody {
|
||||||
|
require(gpioNames.length == io.gpio.length)
|
||||||
|
|
||||||
|
val packagePinsWithIOStdWithPackageIOs = (gpioNames zip io.gpio).map { case (name, io) =>
|
||||||
|
val (pin, iostd) = BringupGPIOs.pinMapping(name)
|
||||||
|
(pin, iostd, IOPin(io))
|
||||||
|
}
|
||||||
|
|
||||||
|
packagePinsWithIOStdWithPackageIOs foreach { case (pin, iostd, io) => {
|
||||||
|
shell.xdc.addPackagePin(io, pin)
|
||||||
|
shell.xdc.addIOStandard(io, iostd)
|
||||||
|
if (iostd == "LVCMOS12") { shell.xdc.addDriveStrength(io, "8") }
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupGPIOVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName)
|
||||||
|
extends GPIOShellPlacer[VCU118ShellBasicOverlays] {
|
||||||
|
def place(designInput: GPIODesignInput) = new BringupGPIOVCU118PlacedOverlay(shell, valName.name, designInput, shellInput, gpioNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
64
fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala
Normal file
64
fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{Analog, IO, BaseModule}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
||||||
|
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||||
|
import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp, I2CPort}
|
||||||
|
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
|
||||||
|
|
||||||
|
import chipyard.{HasHarnessSignalReferences}
|
||||||
|
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
||||||
|
|
||||||
|
/*** UART ***/
|
||||||
|
class WithBringupUART extends ComposeHarnessBinder({
|
||||||
|
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||||
|
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||||
|
require(ports.size == 2)
|
||||||
|
|
||||||
|
vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*** SPI ***/
|
||||||
|
class WithBringupSPI extends ComposeHarnessBinder({
|
||||||
|
(system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => {
|
||||||
|
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||||
|
require(ports.size == 2)
|
||||||
|
|
||||||
|
vcu118th.bringupOuter.io_adi_spi_bb.bundle <> ports.last
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*** I2C ***/
|
||||||
|
class WithBringupI2C extends OverrideHarnessBinder({
|
||||||
|
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[I2CPort]) => {
|
||||||
|
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||||
|
require(ports.size == 1)
|
||||||
|
|
||||||
|
vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*** GPIO ***/
|
||||||
|
class WithBringupGPIO extends OverrideHarnessBinder({
|
||||||
|
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => {
|
||||||
|
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||||
|
(vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) =>
|
||||||
|
bb_io.bundle <> dut_io
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
})
|
||||||
29
fpga/src/main/scala/vcu118/bringup/IOBinders.scala
Normal file
29
fpga/src/main/scala/vcu118/bringup/IOBinders.scala
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.experimental.{IO, DataMirror}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp}
|
||||||
|
import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp}
|
||||||
|
|
||||||
|
import chipyard.iobinders.{OverrideIOBinder}
|
||||||
|
|
||||||
|
class WithGPIOIOPassthrough extends OverrideIOBinder({
|
||||||
|
(system: HasPeripheryGPIOModuleImp) => {
|
||||||
|
val io_gpio_pins_temp = system.gpio.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"gpio_$i") }
|
||||||
|
(io_gpio_pins_temp zip system.gpio).map { case (io, sysio) =>
|
||||||
|
io <> sysio
|
||||||
|
}
|
||||||
|
(io_gpio_pins_temp, Nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithI2CIOPassthrough extends OverrideIOBinder({
|
||||||
|
(system: HasPeripheryI2CModuleImp) => {
|
||||||
|
val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") }
|
||||||
|
(io_i2c_pins_temp zip system.i2c).map { case (io, sysio) =>
|
||||||
|
io <> sysio
|
||||||
|
}
|
||||||
|
(io_i2c_pins_temp, Nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
72
fpga/src/main/scala/vcu118/bringup/TestHarness.scala
Normal file
72
fpga/src/main/scala/vcu118/bringup/TestHarness.scala
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package chipyard.fpga.vcu118.bringup
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell.xilinx._
|
||||||
|
import sifive.fpgashells.ip.xilinx._
|
||||||
|
import sifive.fpgashells.shell._
|
||||||
|
import sifive.fpgashells.clocks._
|
||||||
|
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
|
||||||
|
import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp}
|
||||||
|
|
||||||
|
class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness {
|
||||||
|
|
||||||
|
/*** UART ***/
|
||||||
|
|
||||||
|
require(dp(PeripheryUARTKey).size == 2)
|
||||||
|
|
||||||
|
// 2nd UART goes to the FMC UART
|
||||||
|
|
||||||
|
val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput()))
|
||||||
|
|
||||||
|
val io_fmc_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last)))
|
||||||
|
dp(UARTOverlayKey).last.place(UARTDesignInput(io_fmc_uart_bb))
|
||||||
|
|
||||||
|
/*** SPI ***/
|
||||||
|
|
||||||
|
require(dp(PeripherySPIKey).size == 2)
|
||||||
|
|
||||||
|
// 2nd SPI goes to the ADI port
|
||||||
|
|
||||||
|
val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput()))
|
||||||
|
|
||||||
|
val io_adi_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last)))
|
||||||
|
dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_adi_spi_bb))
|
||||||
|
|
||||||
|
/*** I2C ***/
|
||||||
|
|
||||||
|
val i2c = Overlay(I2COverlayKey, new BringupI2CVCU118ShellPlacer(this, I2CShellInput()))
|
||||||
|
|
||||||
|
val io_i2c_bb = BundleBridgeSource(() => (new I2CPort))
|
||||||
|
dp(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb))
|
||||||
|
|
||||||
|
/*** GPIO ***/
|
||||||
|
|
||||||
|
val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => {
|
||||||
|
val maxGPIOSupport = 32 // max gpio per gpio chip
|
||||||
|
val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1))
|
||||||
|
Overlay(GPIOOverlayKey, new BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names))
|
||||||
|
})
|
||||||
|
|
||||||
|
val io_gpio_bb = dp(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) }
|
||||||
|
(dp(GPIOOverlayKey) zip dp(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) =>
|
||||||
|
placer.place(GPIODesignInput(params, io_gpio_bb(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// module implementation
|
||||||
|
override lazy val module = new BringupVCU118FPGATestHarnessImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends VCU118FPGATestHarnessImp(_outer) {
|
||||||
|
val bringupOuter = _outer
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import scala.collection.mutable.{ArrayBuffer}
|
|||||||
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
|
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
|
||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import freechips.rocketchip.config.{Parameters, Field}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||||
import chipyard.iobinders._
|
import chipyard.iobinders._
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
|
|||||||
* drive clock and reset generation
|
* drive clock and reset generation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ChipTop(implicit p: Parameters) extends LazyModule
|
class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope
|
||||||
with HasTestHarnessFunctions with HasIOBinders {
|
with HasTestHarnessFunctions with HasIOBinders {
|
||||||
// The system module specified by BuildSystem
|
// The system module specified by BuildSystem
|
||||||
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
||||||
|
|||||||
@@ -20,12 +20,16 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
|
|||||||
with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART
|
with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART
|
||||||
with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs
|
with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs
|
||||||
with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller
|
with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller
|
||||||
|
with sifive.blocks.devices.spi.HasPeripherySPI // Enables optionally adding the sifive SPI
|
||||||
|
with sifive.blocks.devices.pwm.HasPeripheryPWM // Enables optionally adding the sifive PWM
|
||||||
|
with sifive.blocks.devices.i2c.HasPeripheryI2C // Enables optionally adding the sifive I2C
|
||||||
with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim
|
with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim
|
||||||
with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
|
with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
|
||||||
with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget
|
with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget
|
||||||
with chipyard.example.CanHavePeripheryStreamingFIR // Enables optionally adding the DSPTools FIR example widget
|
with chipyard.example.CanHavePeripheryStreamingFIR // Enables optionally adding the DSPTools FIR example widget
|
||||||
with chipyard.example.CanHavePeripheryStreamingPassthrough // Enables optionally adding the DSPTools streaming-passthrough example widget
|
with chipyard.example.CanHavePeripheryStreamingPassthrough // Enables optionally adding the DSPTools streaming-passthrough example widget
|
||||||
with nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA
|
with nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA
|
||||||
|
with CanHaveMasterTLMemPort
|
||||||
{
|
{
|
||||||
override lazy val module = new DigitalTopModule(this)
|
override lazy val module = new DigitalTopModule(this)
|
||||||
}
|
}
|
||||||
@@ -35,6 +39,48 @@ class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l)
|
|||||||
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
|
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
|
||||||
with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp
|
with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp
|
||||||
with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp
|
with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp
|
||||||
|
with sifive.blocks.devices.spi.HasPeripherySPIModuleImp
|
||||||
|
with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp
|
||||||
|
with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp
|
||||||
with chipyard.example.CanHavePeripheryGCDModuleImp
|
with chipyard.example.CanHavePeripheryGCDModuleImp
|
||||||
with freechips.rocketchip.util.DontTouch
|
with freechips.rocketchip.util.DontTouch
|
||||||
// DOC include end: DigitalTop
|
// DOC include end: DigitalTop
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
/** Adds a TileLink port to the system intended to master an MMIO device bus */
|
||||||
|
trait CanHaveMasterTLMemPort { this: BaseSubsystem =>
|
||||||
|
private val memPortParamsOpt = p(ExtMem)
|
||||||
|
private val portName = "tl_mem"
|
||||||
|
private val device = new MemoryDevice
|
||||||
|
private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1)
|
||||||
|
|
||||||
|
val memTLNode = TLManagerNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels) =>
|
||||||
|
Seq.tabulate(nMemoryChannels) { channel =>
|
||||||
|
val base = AddressSet.misaligned(memPortParams.base, memPortParams.size)
|
||||||
|
val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes))
|
||||||
|
|
||||||
|
TLSlavePortParameters.v1(
|
||||||
|
managers = Seq(TLSlaveParameters.v1(
|
||||||
|
address = base.flatMap(_.intersect(filter)),
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.UNCACHED, // cacheable
|
||||||
|
executable = true,
|
||||||
|
supportsGet = TransferSizes(1, mbus.blockBytes),
|
||||||
|
supportsPutFull = TransferSizes(1, mbus.blockBytes),
|
||||||
|
supportsPutPartial = TransferSizes(1, mbus.blockBytes))),
|
||||||
|
beatBytes = memPortParams.beatBytes)
|
||||||
|
}
|
||||||
|
}).toList.flatten)
|
||||||
|
|
||||||
|
mbus.coupleTo(s"memory_controller_port_named_$portName") {
|
||||||
|
(memTLNode
|
||||||
|
:*= TLBuffer()
|
||||||
|
:*= TLSourceShrinker(1 << idBits)
|
||||||
|
:*= TLWidthWidget(mbus.beatBytes)
|
||||||
|
:*= _)
|
||||||
|
}
|
||||||
|
|
||||||
|
val mem_tl = InModuleBody { memTLNode.makeIOs() }
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import freechips.rocketchip.util.{DontTouch}
|
|||||||
*/
|
*/
|
||||||
class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
|
class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
|
||||||
with HasAsyncExtInterrupts
|
with HasAsyncExtInterrupts
|
||||||
with CanHaveMasterAXI4MemPort
|
|
||||||
with CanHaveMasterAXI4MMIOPort
|
with CanHaveMasterAXI4MMIOPort
|
||||||
with CanHaveSlaveAXI4Port
|
with CanHaveSlaveAXI4Port
|
||||||
{
|
{
|
||||||
|
|||||||
Submodule generators/sifive-blocks updated: c240e629e2...7e2121ee26
@@ -11,6 +11,7 @@ case class GenerateSimConfig(
|
|||||||
sealed trait Simulator
|
sealed trait Simulator
|
||||||
object VerilatorSimulator extends Simulator
|
object VerilatorSimulator extends Simulator
|
||||||
object VCSSimulator extends Simulator
|
object VCSSimulator extends Simulator
|
||||||
|
object NotSimulator extends Simulator
|
||||||
|
|
||||||
trait HasGenerateSimConfig {
|
trait HasGenerateSimConfig {
|
||||||
val parser = new scopt.OptionParser[GenerateSimConfig]("GenerateSimFiles") {
|
val parser = new scopt.OptionParser[GenerateSimConfig]("GenerateSimFiles") {
|
||||||
@@ -22,15 +23,16 @@ trait HasGenerateSimConfig {
|
|||||||
.action((x, c) => x match {
|
.action((x, c) => x match {
|
||||||
case "verilator" => c.copy(simulator = VerilatorSimulator)
|
case "verilator" => c.copy(simulator = VerilatorSimulator)
|
||||||
case "vcs" => c.copy(simulator = VCSSimulator)
|
case "vcs" => c.copy(simulator = VCSSimulator)
|
||||||
|
case "none" => c.copy(simulator = NotSimulator)
|
||||||
case _ => throw new Exception(s"Unrecognized simulator $x")
|
case _ => throw new Exception(s"Unrecognized simulator $x")
|
||||||
})
|
})
|
||||||
.text("Name of simulator to generate files for (verilator, vcs)")
|
.text("Name of simulator to generate files for (verilator, vcs, none)")
|
||||||
|
|
||||||
opt[String]("target-dir")
|
opt[String]("target-dir")
|
||||||
.abbr("td")
|
.abbr("td")
|
||||||
.valueName("<target-directory>")
|
.valueName("<target-directory>")
|
||||||
.action((x, c) => c.copy(targetDir = x))
|
.action((x, c) => c.copy(targetDir = x))
|
||||||
.text("Target director to put files")
|
.text("Target directory to put files")
|
||||||
|
|
||||||
opt[String]("dotFName")
|
opt[String]("dotFName")
|
||||||
.abbr("df")
|
.abbr("df")
|
||||||
@@ -50,6 +52,7 @@ object GenerateSimFiles extends App with HasGenerateSimConfig {
|
|||||||
case VerilatorSimulator => s"-FI ${fname}"
|
case VerilatorSimulator => s"-FI ${fname}"
|
||||||
// vcs pulls headers in with +incdir, doesn't have anything like verilator.h
|
// vcs pulls headers in with +incdir, doesn't have anything like verilator.h
|
||||||
case VCSSimulator => ""
|
case VCSSimulator => ""
|
||||||
|
case _ => ""
|
||||||
}
|
}
|
||||||
} else { // do nothing otherwise
|
} else { // do nothing otherwise
|
||||||
fname
|
fname
|
||||||
@@ -95,15 +98,30 @@ object GenerateSimFiles extends App with HasGenerateSimConfig {
|
|||||||
"/csrc/remote_bitbang.h",
|
"/csrc/remote_bitbang.h",
|
||||||
"/csrc/remote_bitbang.cc",
|
"/csrc/remote_bitbang.cc",
|
||||||
"/vsrc/EICG_wrapper.v",
|
"/vsrc/EICG_wrapper.v",
|
||||||
) ++ (sim match { // simulator specific files to include
|
) ++ (sim match {
|
||||||
case VerilatorSimulator => Seq(
|
case NotSimulator => Seq()
|
||||||
"/csrc/emulator.cc",
|
case _ => Seq(
|
||||||
"/csrc/verilator.h",
|
"/testchipip/csrc/SimSerial.cc",
|
||||||
)
|
"/testchipip/csrc/SimDRAM.cc",
|
||||||
case VCSSimulator => Seq(
|
"/testchipip/csrc/mm.h",
|
||||||
"/vsrc/TestDriver.v",
|
"/testchipip/csrc/mm.cc",
|
||||||
)
|
"/testchipip/csrc/mm_dramsim2.h",
|
||||||
})
|
"/testchipip/csrc/mm_dramsim2.cc",
|
||||||
|
"/csrc/SimDTM.cc",
|
||||||
|
"/csrc/SimJTAG.cc",
|
||||||
|
"/csrc/remote_bitbang.h",
|
||||||
|
"/csrc/remote_bitbang.cc",
|
||||||
|
)
|
||||||
|
}) ++ (sim match { // simulator specific files to include
|
||||||
|
case VerilatorSimulator => Seq(
|
||||||
|
"/csrc/emulator.cc",
|
||||||
|
"/csrc/verilator.h",
|
||||||
|
)
|
||||||
|
case VCSSimulator => Seq(
|
||||||
|
"/vsrc/TestDriver.v",
|
||||||
|
)
|
||||||
|
case _ => Seq()
|
||||||
|
})
|
||||||
|
|
||||||
def writeBootrom(): Unit = {
|
def writeBootrom(): Unit = {
|
||||||
firrtl.FileUtils.makeDirectory("./bootrom/")
|
firrtl.FileUtils.makeDirectory("./bootrom/")
|
||||||
|
|||||||
11
scripts/init-fpga.sh
Executable file
11
scripts/init-fpga.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# exit script if any command fails
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# Enable submodule update for FPGA tools.
|
||||||
|
git config --unset submodule.fpga/fpga-shells.update
|
||||||
|
# Initialize local FPGA tools.
|
||||||
|
git submodule update --init --recursive fpga/fpga-shells
|
||||||
|
# Disable submodule update for FPGA tools.
|
||||||
|
git config submodule.fpga/fpga-shells.update none
|
||||||
@@ -39,6 +39,8 @@ git config submodule.vlsi/hammer-cadence-plugins.update none
|
|||||||
git config submodule.vlsi/hammer-synopsys-plugins.update none
|
git config submodule.vlsi/hammer-synopsys-plugins.update none
|
||||||
git config submodule.vlsi/hammer-mentor-plugins.update none
|
git config submodule.vlsi/hammer-mentor-plugins.update none
|
||||||
git config submodule.software/firemarshal.update none
|
git config submodule.software/firemarshal.update none
|
||||||
|
# Disable updates to the local FPGA tools
|
||||||
|
git config submodule.fpga/fpga-shells.update none
|
||||||
git submodule update --init --recursive #--jobs 8
|
git submodule update --init --recursive #--jobs 8
|
||||||
|
|
||||||
# Un-ignore toolchain submodules
|
# Un-ignore toolchain submodules
|
||||||
|
|||||||
Reference in New Issue
Block a user