Merge branch 'local-fpga-temp' into local-fpga-support

This commit is contained in:
abejgonzalez
2020-11-05 11:01:56 -08:00
50 changed files with 3002 additions and 17 deletions

5
.gitmodules vendored
View File

@@ -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

View File

@@ -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)

View File

@@ -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
View File

@@ -0,0 +1 @@
generated-src

132
fpga/Makefile Normal file
View 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

Submodule fpga/fpga-shells added at 89a5efec01

View 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

View 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

View File

@@ -0,0 +1 @@
build

View 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)

View File

@@ -0,0 +1,9 @@
#ifndef _SDBOOT_COMMON_H
#define _SDBOOT_COMMON_H
#ifndef PAYLOAD_DEST
#define PAYLOAD_DEST MEMORY_MEM_ADDR
#endif
#endif

View 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:

View 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

View 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 */

View File

@@ -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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View File

@@ -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 */

View 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 */

View 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

View 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);
}

View 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 = &REG32(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 */

View File

@@ -0,0 +1,5 @@
MEMORY
{
bootrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000
memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000
}

View 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");
}
}

View 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;
}

View 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))
//}
//

View 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)

View 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

View 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)))
// }
//})
//

View 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)

View 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)
}

View 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
}
})

View 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)
}
})

View 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)
}
}

View 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
}

View 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)

View 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)
}

View 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
}
})

View 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)
}
})

View 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
}

View File

@@ -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")

View File

@@ -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() }
}

View File

@@ -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
{ {

View File

@@ -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
View 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

View File

@@ -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