From a8834c77669e978658f24610e0743306bc4ce1cd Mon Sep 17 00:00:00 2001 From: James Dunn Date: Wed, 2 Sep 2020 12:48:44 -0700 Subject: [PATCH 01/28] First draft of local FPGA support, targeting ARTY. Able to build verilog and bitfile for Rocket + Chipyard GCD example. To test, add GCD mixin to fpga/src/main/scala/arty/Config.scala, run make -f Makefile.e300artydevkit verilog and make -f Makefile.e300artydevkit mcs in fpga directory. Output will be in fpga/build. --- .gitmodules | 3 + build.sbt | 7 + fpga/Makefile.e300artydevkit | 23 +++ fpga/bootrom/xip/Makefile | 45 ++++++ fpga/bootrom/xip/xip.S | 16 ++ fpga/common.mk | 119 +++++++++++++++ fpga/fpga-shells | 1 + fpga/src/main/scala/arty/Config.scala | 65 ++++++++ fpga/src/main/scala/arty/FPGAChip.scala | 193 ++++++++++++++++++++++++ fpga/src/main/scala/arty/Platform.scala | 178 ++++++++++++++++++++++ fpga/src/main/scala/arty/System.scala | 51 +++++++ 11 files changed, 701 insertions(+) create mode 100644 fpga/Makefile.e300artydevkit create mode 100644 fpga/bootrom/xip/Makefile create mode 100644 fpga/bootrom/xip/xip.S create mode 100644 fpga/common.mk create mode 160000 fpga/fpga-shells create mode 100644 fpga/src/main/scala/arty/Config.scala create mode 100644 fpga/src/main/scala/arty/FPGAChip.scala create mode 100644 fpga/src/main/scala/arty/Platform.scala create mode 100644 fpga/src/main/scala/arty/System.scala diff --git a/.gitmodules b/.gitmodules index aab9a8f7..ea3cb2c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -128,3 +128,6 @@ [submodule "tools/dromajo/dromajo-src"] path = tools/dromajo/dromajo-src url = https://github.com/riscv-boom/dromajo.git +[submodule "fpga/fpga-shells"] + path = fpga/fpga-shells + url = git@github.com:sifive/fpga-shells.git diff --git a/build.sbt b/build.sbt index 5d642c1d..31bb3f88 100644 --- a/build.sbt +++ b/build.sbt @@ -217,3 +217,10 @@ lazy val firechip = conditionalDependsOn(project in file("generators/firechip")) testGrouping in Test := isolateAllTests( (definedTests in Test).value ), testOptions in Test += Tests.Argument("-oF") ) +lazy val fpgaShells = (project in file("./fpga/fpga-shells")) + .dependsOn(rocketchip, sifive_blocks) + .settings(commonSettings) + +lazy val freedomPlatforms = (project in file("./fpga")) + .dependsOn(chipyard, fpgaShells) + .settings(commonSettings) diff --git a/fpga/Makefile.e300artydevkit b/fpga/Makefile.e300artydevkit new file mode 100644 index 00000000..5f5c595b --- /dev/null +++ b/fpga/Makefile.e300artydevkit @@ -0,0 +1,23 @@ +# See LICENSE for license details. +base_dir=$(abspath ..) +BUILD_DIR := $(base_dir)/fpga/builds/e300artydevkit +FPGA_DIR := $(base_dir)/fpga/fpga-shells/xilinx +MODEL := E300ArtyDevKitFPGAChip +PROJECT := sifive.freedom.everywhere.e300artydevkit +export CONFIG_PROJECT := sifive.freedom.everywhere.e300artydevkit +export CONFIG := E300ArtyDevKitConfig +export BOARD := arty +export BOOTROM_DIR := $(base_dir)/fpga/bootrom/xip + +rocketchip_dir := $(base_dir)/generators/rocket-chip +sifiveblocks_dir := $(base_dir)/generators/sifive-blocks +VSRCS := \ + $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ + $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ + $(rocketchip_dir)/src/main/resources/vsrc/EICG_wrapper.v \ + $(sifiveblocks_dir)/vsrc/SRLatch.v \ + $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ + $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ + $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v + +include common.mk diff --git a/fpga/bootrom/xip/Makefile b/fpga/bootrom/xip/Makefile new file mode 100644 index 00000000..57f94d49 --- /dev/null +++ b/fpga/bootrom/xip/Makefile @@ -0,0 +1,45 @@ +# RISCV environment variable must be set + +CC=$(RISCV)/bin/riscv64-unknown-elf-gcc +OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy +CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g +LFLAGS=-static -nostdlib + +dtb := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dtb +$(dtb): $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dts + dtc -I dts -O dtb -o $@ $< + +.PHONY: dtb +dtb: $(dtb) + +elf := $(BUILD_DIR)/xip.elf +$(elf): xip.S $(dtb) + $(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $< + +.PHONY: elf +elf: $(elf) + +bin := $(BUILD_DIR)/xip.bin +$(bin): $(elf) + $(OBJCOPY) -O binary $< $@ + +.PHONY: bin +bin: $(bin) + +hex := $(BUILD_DIR)/xip.hex +$(hex): $(bin) + od -t x4 -An -w4 -v $< > $@ + +.PHONY: hex +hex: $(hex) + +romgen := $(BUILD_DIR)/rom.v +$(romgen): $(hex) + $(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ + +.PHONY: romgen +romgen: $(romgen) + +.PHONY: clean +clean:: + rm -rf $(hex) $(elf) diff --git a/fpga/bootrom/xip/xip.S b/fpga/bootrom/xip/xip.S new file mode 100644 index 00000000..7445f4c9 --- /dev/null +++ b/fpga/bootrom/xip/xip.S @@ -0,0 +1,16 @@ +// See LICENSE for license details. +// Execute in place +// Jump directly to XIP_TARGET_ADDR + + .section .text.init + .option norvc + .globl _start +_start: + csrr a0, mhartid + la a1, dtb + li t0, XIP_TARGET_ADDR + jr t0 + + .section .rodata +dtb: + .incbin DEVICE_TREE diff --git a/fpga/common.mk b/fpga/common.mk new file mode 100644 index 00000000..5466ed7b --- /dev/null +++ b/fpga/common.mk @@ -0,0 +1,119 @@ +# See LICENSE for license details. + +# Required variables: +# - MODEL +# - PROJECT +# - CONFIG_PROJECT +# - CONFIG +# - BUILD_DIR +# - FPGA_DIR + +# Optional variables: +# - EXTRA_FPGA_VSRCS + +# export to bootloader +export ROMCONF=$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.conf + +# export to fpga-shells +export FPGA_TOP_SYSTEM=$(MODEL) +export FPGA_BUILD_DIR=$(BUILD_DIR)/$(FPGA_TOP_SYSTEM) +export fpga_common_script_dir=$(FPGA_DIR)/common/tcl +export fpga_board_script_dir=$(FPGA_DIR)/$(BOARD)/tcl + +export BUILD_DIR + +EXTRA_FPGA_VSRCS ?= +PATCHVERILOG ?= "" +BOOTROM_DIR ?= "" + +base_dir=$(abspath ..) +export rocketchip_dir := $(base_dir)/generators/rocket-chip +SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar ++2.12.10 +SBT_PROJECT ?= chipyard +firrtl_dir := $(base_dir)/tools/firrtl + +# Build firrtl.jar and put it where chisel3 can find it. +FIRRTL_JAR := $(base_dir)/lib/firrtl.jar +FIRRTL ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp $(FIRRTL_JAR) firrtl.Driver + +$(FIRRTL_JAR): $(shell find $(firrtl_dir)/src/main/scala -iname "*.scala") + $(MAKE) -C $(firrtl_dir) SBT="$(SBT)" root_dir=$(firrtl_dir) build-scala + mkdir -p $(base_dir)/lib + cp $(firrtl_dir)/utils/bin/firrtl.jar $(FIRRTL_JAR) + +# Build .fir +long_name := $(CONFIG_PROJECT).$(CONFIG) +firrtl := $(BUILD_DIR)/$(long_name).fir +$(firrtl): $(shell find $(base_dir) -name '*.scala') $(FIRRTL_JAR) + mkdir -p $(dir $@) + cd $(base_dir) && $(SBT) "project freedomPlatforms" \ + "runMain chipyard.Generator \ + --target-dir $(BUILD_DIR) \ + --name $(long_name) \ + --top-module $(PROJECT).$(MODEL) \ + --legacy-configs $(CONFIG_PROJECT).$(CONFIG)" + +.PHONY: firrtl +firrtl: $(firrtl) + +# Build .v +verilog := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v +$(verilog): $(firrtl) $(FIRRTL_JAR) + $(FIRRTL) -i $(firrtl) -o $@ -X verilog +ifneq ($(PATCHVERILOG),"") + $(PATCHVERILOG) +endif + +.PHONY: verilog +verilog: $(verilog) + +romgen := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v +$(romgen): $(verilog) +ifneq ($(BOOTROM_DIR),"") + $(MAKE) -C $(BOOTROM_DIR) romgen + mv $(BUILD_DIR)/rom.v $@ +endif + +.PHONY: romgen +romgen: $(romgen) + +f := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F +$(f): + echo $(VSRCS) > $@ + +bit := $(BUILD_DIR)/obj/$(MODEL).bit +$(bit): $(romgen) $(f) + cd $(BUILD_DIR); vivado \ + -nojournal -mode batch \ + -source $(fpga_common_script_dir)/vivado.tcl \ + -tclargs \ + -top-module "$(MODEL)" \ + -F "$(f)" \ + -ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.vivado.tcl')" \ + -board "$(BOARD)" + + +# Build .mcs +mcs := $(BUILD_DIR)/obj/$(MODEL).mcs +$(mcs): $(bit) + cd $(BUILD_DIR); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $< + +.PHONY: mcs +mcs: $(mcs) + +# Build Libero project +prjx := $(BUILD_DIR)/libero/$(MODEL).prjx +$(prjx): $(verilog) + cd $(BUILD_DIR); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(BUILD_DIR) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)" + +.PHONY: prjx +prjx: $(prjx) + +# Clean +.PHONY: clean +clean: +ifneq ($(BOOTROM_DIR),"") + $(MAKE) -C $(BOOTROM_DIR) clean +endif + $(MAKE) -C $(FPGA_DIR) clean + rm -rf $(BUILD_DIR) diff --git a/fpga/fpga-shells b/fpga/fpga-shells new file mode 160000 index 00000000..e8e7f8a3 --- /dev/null +++ b/fpga/fpga-shells @@ -0,0 +1 @@ +Subproject commit e8e7f8a321ebde213ebc79db06422278d9aa477f diff --git a/fpga/src/main/scala/arty/Config.scala b/fpga/src/main/scala/arty/Config.scala new file mode 100644 index 00000000..45f83036 --- /dev/null +++ b/fpga/src/main/scala/arty/Config.scala @@ -0,0 +1,65 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300artydevkit + +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._ + +// Default FreedomEConfig +class DefaultFreedomEConfig extends Config ( + new WithNBreakpoints(2) ++ + new WithNExtTopInterrupts(0) ++ + new WithJtagDTM ++ + new TinyConfig +) + +// Freedom E300 Arty Dev Kit Peripherals +class E300DevKitPeripherals 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 PeripheryMaskROMKey => List( + MaskROMParams(address = 0x10000, name = "BootROM")) +}) + +// Freedom E300 Arty Dev Kit Peripherals +class E300ArtyDevKitConfig extends Config( + new E300DevKitPeripherals ++ + new DefaultFreedomEConfig().alter((site,here,up) => { + case DTSTimebase => BigInt(32768) + case JtagDTMKey => new JtagDTMConfig ( + idcodeVersion = 2, + idcodePartNum = 0x000, + idcodeManufId = 0x489, + debugIdleCycles = 5) + }) +) diff --git a/fpga/src/main/scala/arty/FPGAChip.scala b/fpga/src/main/scala/arty/FPGAChip.scala new file mode 100644 index 00000000..e0b0634c --- /dev/null +++ b/fpga/src/main/scala/arty/FPGAChip.scala @@ -0,0 +1,193 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300artydevkit + +import Chisel._ +import chisel3.core.{attach} +import chisel3.experimental.{withClockAndReset} + +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy.{LazyModule} + +import sifive.blocks.devices.gpio._ +import sifive.blocks.devices.spi._ + +import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} +import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} + +//------------------------------------------------------------------------- +// E300ArtyDevKitFPGAChip +//------------------------------------------------------------------------- + +class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell { + + //----------------------------------------------------------------------- + // Clock divider + //----------------------------------------------------------------------- + val slow_clock = Wire(Bool()) + + // Divide clock by 256, used to generate 32.768 kHz clock for AON block + withClockAndReset(clock_8MHz, ~mmcm_locked) { + val clockToggleReg = RegInit(false.B) + val (_, slowTick) = Counter(true.B, 256) + when (slowTick) {clockToggleReg := ~clockToggleReg} + slow_clock := clockToggleReg + } + + //----------------------------------------------------------------------- + // DUT + //----------------------------------------------------------------------- + + withClockAndReset(clock_32MHz, ck_rst) { + val dut = Module(new E300ArtyDevKitPlatform) + + //--------------------------------------------------------------------- + // SPI flash IOBUFs + //--------------------------------------------------------------------- + + IOBUF(qspi_sck, dut.io.pins.qspi.sck) + IOBUF(qspi_cs, dut.io.pins.qspi.cs(0)) + + IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0)) + IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1)) + IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2)) + IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3)) + + //--------------------------------------------------------------------- + // JTAG IOBUFs + //--------------------------------------------------------------------- + + dut.io.pins.jtag.TCK.i.ival := IBUFG(IOBUF(jd_2).asClock).asUInt + + IOBUF(jd_5, dut.io.pins.jtag.TMS) + PULLUP(jd_5) + + IOBUF(jd_4, dut.io.pins.jtag.TDI) + PULLUP(jd_4) + + IOBUF(jd_0, dut.io.pins.jtag.TDO) + + // mimic putting a pullup on this line (part of reset vote) + SRST_n := IOBUF(jd_6) + PULLUP(jd_6) + + // jtag reset + val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_32MHz) + dut.io.jtag_reset := jtag_power_on_reset + + // debug reset + dut_ndreset := dut.io.ndreset + + //--------------------------------------------------------------------- + // Assignment to package pins + //--------------------------------------------------------------------- + // Pins IO0-IO13 + // + // FTDI UART TX/RX are not connected to 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 := dut.io.pins.gpio.pins(16).o.oval + iobuf_ck0.io.T := ~dut.io.pins.gpio.pins(16).o.oe + attach(iobuf_ck0.io.IO, ck_io(0)) // UART0 RX + + val iobuf_uart_txd = Module(new IOBUF()) + iobuf_uart_txd.io.I := dut.io.pins.gpio.pins(16).o.oval + iobuf_uart_txd.io.T := ~dut.io.pins.gpio.pins(16).o.oe + attach(iobuf_uart_txd.io.IO, 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(sw_3) + dut.io.pins.gpio.pins(16).i.ival := Mux(sw_3_in, + iobuf_ck0.io.O & dut.io.pins.gpio.pins(16).o.ie, + iobuf_uart_txd.io.O & dut.io.pins.gpio.pins(16).o.ie) + + IOBUF(uart_rxd_out, dut.io.pins.gpio.pins(17)) + + // Shield header row 0: PD2-PD7 + IOBUF(ck_io(2), dut.io.pins.gpio.pins(18)) + IOBUF(ck_io(3), dut.io.pins.gpio.pins(19)) // PWM1(1) + IOBUF(ck_io(4), dut.io.pins.gpio.pins(20)) // PWM1(0) + IOBUF(ck_io(5), dut.io.pins.gpio.pins(21)) // PWM1(2) + IOBUF(ck_io(6), dut.io.pins.gpio.pins(22)) // PWM1(3) + IOBUF(ck_io(7), dut.io.pins.gpio.pins(23)) + + // Header row 1: PB0-PB5 + IOBUF(ck_io(8), dut.io.pins.gpio.pins(0)) // PWM0(0) + IOBUF(ck_io(9), dut.io.pins.gpio.pins(1)) // PWM0(1) + IOBUF(ck_io(10), dut.io.pins.gpio.pins(2)) // SPI CS(0) / PWM0(2) + IOBUF(ck_io(11), dut.io.pins.gpio.pins(3)) // SPI MOSI / PWM0(3) + IOBUF(ck_io(12), dut.io.pins.gpio.pins(4)) // SPI MISO + IOBUF(ck_io(13), dut.io.pins.gpio.pins(5)) // SPI SCK + + dut.io.pins.gpio.pins(6).i.ival := 0.U + dut.io.pins.gpio.pins(7).i.ival := 0.U + dut.io.pins.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(ck_io(15), dut.io.pins.gpio.pins(9)) // A1 = CS(2) + IOBUF(ck_io(16), dut.io.pins.gpio.pins(10)) // A2 = CS(3) / PWM2(0) + IOBUF(ck_io(17), dut.io.pins.gpio.pins(11)) // A3 = PWM2(1) + IOBUF(ck_io(18), dut.io.pins.gpio.pins(12)) // A4 = PWM2(2) / SDA + IOBUF(ck_io(19), dut.io.pins.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(led0_r, dut.io.pins.gpio.pins(1)) + IOBUF(led0_g, dut.io.pins.gpio.pins(2)) + IOBUF(led0_b, dut.io.pins.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(led1_r, dut.io.pins.gpio.pins(19)) + IOBUF(led1_g, dut.io.pins.gpio.pins(21)) + IOBUF(led1_b, dut.io.pins.gpio.pins(22)) + + // and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active + IOBUF(led2_r, dut.io.pins.gpio.pins(11)) + IOBUF(led2_g, dut.io.pins.gpio.pins(12)) + IOBUF(led2_b, dut.io.pins.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(btn_0, dut.io.pins.gpio.pins(15)) + IOBUF(btn_1, dut.io.pins.gpio.pins(30)) + IOBUF(btn_2, dut.io.pins.gpio.pins(31)) + + val iobuf_btn_3 = Module(new IOBUF()) + iobuf_btn_3.io.I := ~dut.io.pins.aon.pmu.dwakeup_n.o.oval + iobuf_btn_3.io.T := ~dut.io.pins.aon.pmu.dwakeup_n.o.oe + attach(btn_3, iobuf_btn_3.io.IO) + dut.io.pins.aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & dut.io.pins.aon.pmu.dwakeup_n.o.ie + + // UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1 + IOBUF(ja_0, dut.io.pins.gpio.pins(25)) // UART1 TX + IOBUF(ja_1, dut.io.pins.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(ck_ss, dut.io.pins.gpio.pins(26)) + IOBUF(ck_mosi, dut.io.pins.gpio.pins(27)) + IOBUF(ck_miso, dut.io.pins.gpio.pins(28)) + IOBUF(ck_sck, dut.io.pins.gpio.pins(29)) + + // Use the LEDs for some more useful debugging things + IOBUF(led_0, ck_rst) + IOBUF(led_1, SRST_n) + IOBUF(led_2, dut.io.pins.aon.pmu.dwakeup_n.i.ival) + IOBUF(led_3, dut.io.pins.gpio.pins(14)) + + //--------------------------------------------------------------------- + // Unconnected inputs + //--------------------------------------------------------------------- + + dut.io.pins.aon.erst_n.i.ival := ~reset_periph + dut.io.pins.aon.lfextclk.i.ival := slow_clock + dut.io.pins.aon.pmu.vddpaden.i.ival := 1.U + } +} diff --git a/fpga/src/main/scala/arty/Platform.scala b/fpga/src/main/scala/arty/Platform.scala new file mode 100644 index 00000000..0f76cb15 --- /dev/null +++ b/fpga/src/main/scala/arty/Platform.scala @@ -0,0 +1,178 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300artydevkit + +import Chisel._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.ResetCatchAndSync +import freechips.rocketchip.system._ + +import sifive.blocks.devices.mockaon._ +import sifive.blocks.devices.gpio._ +import sifive.blocks.devices.jtag._ +import sifive.blocks.devices.pwm._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.uart._ +import sifive.blocks.devices.i2c._ +import sifive.blocks.devices.pinctrl._ + +//------------------------------------------------------------------------- +// PinGen +//------------------------------------------------------------------------- + +object PinGen { + def apply(): BasePin = { + val pin = new BasePin() + pin + } +} + +//------------------------------------------------------------------------- +// E300ArtyDevKitPlatformIO +//------------------------------------------------------------------------- + +class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { + val pins = new Bundle { + val jtag = new JTAGPins(() => PinGen(), false) + val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0)) + val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) + val aon = new MockAONWrapperPins() + } + val jtag_reset = Bool(INPUT) + val ndreset = Bool(OUTPUT) +} + +//------------------------------------------------------------------------- +// E300ArtyDevKitPlatform +//------------------------------------------------------------------------- + +class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { + val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) + val io = new E300ArtyDevKitPlatformIO + + // This needs to be de-asserted synchronously to the coreClk. + val async_corerst = sys.aon.rsts.corerst + // Add in debug-controlled reset. + sys.reset := ResetCatchAndSync(clock, async_corerst, 20) + Debug.connectDebugClockAndReset(sys.debug, 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 = sys.uart + val sys_pwm = sys.pwm + val sys_spi = sys.spi + val sys_i2c = sys.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 = clock, reset = reset, 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 = clock, reset = reset, syncStages = 0)} + (i2c_pins zip sys_i2c) map {case (p, r) => I2CPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)} + + //----------------------------------------------------------------------- + // Default Pin connections before attaching pinmux + + for (iof_0 <- sys.gpio(0).iof_0.get) { + iof_0.default() + } + + for (iof_1 <- sys.gpio(0).iof_1.get) { + iof_1.default() + } + + //----------------------------------------------------------------------- + + val iof_0 = sys.gpio(0).iof_0.get + val iof_1 = sys.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.pins.gpio, sys.gpio(0)) + + // Dedicated SPI Pads + SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3) + + // JTAG Debug Interface + val sjtag = sys.debug.get.systemjtag.get + JTAGPinsFromPort(io.pins.jtag, sjtag.jtag) + sjtag.reset := io.jtag_reset + sjtag.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) + + io.ndreset := sys.debug.get.ndreset + + // AON Pads -- direct connection is OK because + // EnhancedPin is hard-coded in MockAONPads + // and thus there is no .fromPort method. + io.pins.aon <> sys.aon.pins +} diff --git a/fpga/src/main/scala/arty/System.scala b/fpga/src/main/scala/arty/System.scala new file mode 100644 index 00000000..f614c06c --- /dev/null +++ b/fpga/src/main/scala/arty/System.scala @@ -0,0 +1,51 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300artydevkit + +import Chisel._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.system._ + +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._ + +//------------------------------------------------------------------------- +// E300ArtyDevKitSystem +//------------------------------------------------------------------------- + +class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem + with HasPeripheryDebug + with HasPeripheryMockAON + with chipyard.example.CanHavePeripheryGCD + with HasPeripheryUART + with HasPeripherySPIFlash + with HasPeripherySPI + with HasPeripheryGPIO + with HasPeripheryPWM + with HasPeripheryI2C { + override lazy val module = new E300ArtyDevKitSystemModule(this) +} + +class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) + extends RocketSubsystemModuleImp(_outer) + with HasPeripheryDebugModuleImp + with chipyard.example.CanHavePeripheryGCDModuleImp + with HasPeripheryUARTModuleImp + with HasPeripherySPIModuleImp + with HasPeripheryGPIOModuleImp + with HasPeripherySPIFlashModuleImp + with HasPeripheryMockAONModuleImp + with HasPeripheryPWMModuleImp + with HasPeripheryI2CModuleImp { + // Reset vector is set to the location of the mask rom + val maskROMParams = p(PeripheryMaskROMKey) + global_reset_vector := maskROMParams(0).address.U +} From 3b6d5846729bd4ed2c8f75869251558fd6340f0c Mon Sep 17 00:00:00 2001 From: James Dunn Date: Wed, 2 Sep 2020 13:27:31 -0700 Subject: [PATCH 02/28] Adding submodule update script for FPGA tools. --- scripts/init-fpga.sh | 11 +++++++++++ scripts/init-submodules-no-riscv-tools-nolog.sh | 2 ++ 2 files changed, 13 insertions(+) create mode 100755 scripts/init-fpga.sh diff --git a/scripts/init-fpga.sh b/scripts/init-fpga.sh new file mode 100755 index 00000000..08203259 --- /dev/null +++ b/scripts/init-fpga.sh @@ -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 diff --git a/scripts/init-submodules-no-riscv-tools-nolog.sh b/scripts/init-submodules-no-riscv-tools-nolog.sh index cede5e47..c243a86f 100755 --- a/scripts/init-submodules-no-riscv-tools-nolog.sh +++ b/scripts/init-submodules-no-riscv-tools-nolog.sh @@ -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-mentor-plugins.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 # Un-ignore toolchain submodules From 0656c5da4f0e99e0be5a4a18626a96c6462f5006 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 3 Sep 2020 20:29:19 -0700 Subject: [PATCH 03/28] First pass on using CY make system --- fpga/Makefile | 93 +++++++++++++++++++++++++ fpga/src/main/scala/arty/Config.scala | 4 +- fpga/src/main/scala/arty/Platform.scala | 1 + fpga/src/main/scala/arty/System.scala | 12 +++- 4 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 fpga/Makefile diff --git a/fpga/Makefile b/fpga/Makefile new file mode 100644 index 00000000..dcafb930 --- /dev/null +++ b/fpga/Makefile @@ -0,0 +1,93 @@ +######################################################################################### +# fpga prototype makefile +######################################################################################### + +######################################################################################### +# general path variables +######################################################################################### +base_dir=$(abspath ..) +sim_dir=$(abspath .) + +######################################################################################### +# include shared variables +######################################################################################### +include $(base_dir)/variables.mk + +export SUB_PROJECT=fpga +export SBT_PROJECT=freedomPlatforms +export MODEL=E300ArtyDevKitFPGAChip +export VLOG_MODEL=E300ArtyDevKitFPGAChip +export MODEL_PACKAGE=sifive.freedom.everywhere.e300artydevkit +export CONFIG=E300ArtyDevKitConfig +export CONFIG_PACKAGE=sifive.freedom.everywhere.e300artydevkit +export GENERATOR_PACKAGE=chipyard +export TB=none +export TOP=E300ArtyDevKitPlatform +export BOARD=arty + +export bootrom_dir := $(base_dir)/fpga/bootrom/xip +fpga_dir=$(base_dir)/fpga/fpga-shells/xilinx + +sim_name = verilator # unused + +######################################################################################### +# import other necessary rules and variables +######################################################################################### +include $(base_dir)/common.mk + +######################################################################################### +# copy from other directory +######################################################################################### +romgen := $(build_dir)/$(CONFIG_PROJECT).$(CONFIG).rom.v +$(romgen): $(verilog) +ifneq ($(bootrom_dir),"") + $(MAKE) -C $(bootrom_dir) romgen + mv $(build_dir)/rom.v $@ +endif + +.PHONY: romgen +romgen: $(romgen) + +f := $(build_dir)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F +$(f): + echo $(VSRCS) > $@ + +bit := $(build_dir)/obj/$(MODEL).bit +$(bit): $(romgen) $(f) + cd $(build_dir); vivado \ + -nojournal -mode batch \ + -source $(fpga_common_script_dir)/vivado.tcl \ + -tclargs \ + -top-module "$(MODEL)" \ + -F "$(f)" \ + -ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')" \ + -board "$(BOARD)" + + +# Build .mcs +mcs := $(build_dir)/obj/$(MODEL).mcs +$(mcs): $(bit) + cd $(build_dir); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $< + +.PHONY: mcs +mcs: $(mcs) + +# Build Libero project +prjx := $(build_dir)/libero/$(MODEL).prjx +$(prjx): $(verilog) + cd $(build_dir); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(build_dir) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)" + +.PHONY: prjx +prjx: $(prjx) + + +######################################################################################### +# general cleanup rules +######################################################################################### +.PHONY: clean +clean: + rm -rf $(gen_dir) +ifneq ($(bootrom_dir),"") + $(MAKE) -C $(bootrom_dir) clean +endif + $(MAKE) -C $(FPGA_DIR) clean diff --git a/fpga/src/main/scala/arty/Config.scala b/fpga/src/main/scala/arty/Config.scala index 45f83036..11642164 100644 --- a/fpga/src/main/scala/arty/Config.scala +++ b/fpga/src/main/scala/arty/Config.scala @@ -47,8 +47,8 @@ class E300DevKitPeripherals extends Config((site, here, up) => { I2CParams(address = 0x10016000)) case PeripheryMockAONKey => MockAONParams(address = 0x10000000) - case PeripheryMaskROMKey => List( - MaskROMParams(address = 0x10000, name = "BootROM")) + case MaskROMLocated(InSubsystem) => List(MaskROMParams(address = 0x10000, name = "BootROM")) + case BootROMLocated(InSubsystem) => None }) // Freedom E300 Arty Dev Kit Peripherals diff --git a/fpga/src/main/scala/arty/Platform.scala b/fpga/src/main/scala/arty/Platform.scala index 0f76cb15..14c31628 100644 --- a/fpga/src/main/scala/arty/Platform.scala +++ b/fpga/src/main/scala/arty/Platform.scala @@ -51,6 +51,7 @@ class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { //------------------------------------------------------------------------- class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { + //val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) This can be DigitalTop? val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) val io = new E300ArtyDevKitPlatformIO diff --git a/fpga/src/main/scala/arty/System.scala b/fpga/src/main/scala/arty/System.scala index f614c06c..46e5c34e 100644 --- a/fpga/src/main/scala/arty/System.scala +++ b/fpga/src/main/scala/arty/System.scala @@ -31,6 +31,12 @@ class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem with HasPeripheryGPIO with HasPeripheryPWM with HasPeripheryI2C { + val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) } + val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) } + + val maskROMResetVectorSourceNode = BundleBridgeSource[UInt]() + tileResetVectorNexusNode := maskROMResetVectorSourceNode + override lazy val module = new E300ArtyDevKitSystemModule(this) } @@ -45,7 +51,7 @@ class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) with HasPeripheryMockAONModuleImp with HasPeripheryPWMModuleImp with HasPeripheryI2CModuleImp { - // Reset vector is set to the location of the mask rom - val maskROMParams = p(PeripheryMaskROMKey) - global_reset_vector := maskROMParams(0).address.U + + // connect reset vector to 1st MaskROM + _outer.maskROMResetVectorSourceNode.bundle := p(MaskROMLocated(_outer.location))(0).address.U } From 5a885fdcfd621fffe6b1ad7c9a92d0dbbdf5db9c Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 3 Sep 2020 21:28:05 -0700 Subject: [PATCH 04/28] Delete old makefiles | Full switch to CY make system --- fpga/.gitignore | 3 + fpga/Makefile | 73 +++++++---- fpga/Makefile.e300artydevkit | 23 ---- fpga/bootrom/xip/Makefile | 13 +- fpga/common.mk | 119 ------------------ .../utilities/src/main/scala/Simulator.scala | 50 ++++---- 6 files changed, 93 insertions(+), 188 deletions(-) create mode 100644 fpga/.gitignore delete mode 100644 fpga/Makefile.e300artydevkit delete mode 100644 fpga/common.mk diff --git a/fpga/.gitignore b/fpga/.gitignore new file mode 100644 index 00000000..a0991ff4 --- /dev/null +++ b/fpga/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/fpga/Makefile b/fpga/Makefile index dcafb930..837902bc 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -8,27 +8,35 @@ base_dir=$(abspath ..) sim_dir=$(abspath .) +# do not generate simulation files +sim_name := none + ######################################################################################### # include shared variables ######################################################################################### include $(base_dir)/variables.mk -export SUB_PROJECT=fpga -export SBT_PROJECT=freedomPlatforms -export MODEL=E300ArtyDevKitFPGAChip -export VLOG_MODEL=E300ArtyDevKitFPGAChip -export MODEL_PACKAGE=sifive.freedom.everywhere.e300artydevkit -export CONFIG=E300ArtyDevKitConfig -export CONFIG_PACKAGE=sifive.freedom.everywhere.e300artydevkit -export GENERATOR_PACKAGE=chipyard -export TB=none -export TOP=E300ArtyDevKitPlatform -export BOARD=arty +# default variables to build the arty example +SUB_PROJECT := fpga +SBT_PROJECT := freedomPlatforms +MODEL := E300ArtyDevKitFPGAChip +VLOG_MODEL := E300ArtyDevKitFPGAChip +MODEL_PACKAGE := sifive.freedom.everywhere.e300artydevkit +CONFIG := E300ArtyDevKitConfig +CONFIG_PACKAGE := sifive.freedom.everywhere.e300artydevkit +GENERATOR_PACKAGE := chipyard +TB := none # unused +TOP := E300ArtyDevKitPlatform -export bootrom_dir := $(base_dir)/fpga/bootrom/xip -fpga_dir=$(base_dir)/fpga/fpga-shells/xilinx +# setup the board to use +BOARD ?= arty -sim_name = verilator # unused +######################################################################################### +# misc. directories +######################################################################################### +bootrom_dir := $(base_dir)/fpga/bootrom/xip +fpga_common_script_dir := $(FPGA_DIR)/common/tcl +fpga_dir := $(base_dir)/fpga/fpga-shells/xilinx ######################################################################################### # import other necessary rules and variables @@ -38,8 +46,23 @@ include $(base_dir)/common.mk ######################################################################################### # copy from other directory ######################################################################################### -romgen := $(build_dir)/$(CONFIG_PROJECT).$(CONFIG).rom.v -$(romgen): $(verilog) +all_vsrcs := \ + $(sim_vsrcs) \ + $(base_dir)/generators/sifive-blocks/vsrc/SRLatch.v \ + $(fpga_dir)/common/vsrc/PowerOnResetFPGAOnly.v \ + $(build_dir)/$(long_name).rom.v + +######################################################################################### +# build rom for the fpga +######################################################################################### +# needed for bootrom makefile +export BUILD_DIR=$(build_dir) +export ROCKETCHIP_DIR +export LONG_NAME=$(long_name) +export ROMCONF=$(build_dir)/$(long_name).rom.conf + +romgen := $(build_dir)/$(long_name).rom.v +$(romgen): $(sim_vsrcs) ifneq ($(bootrom_dir),"") $(MAKE) -C $(bootrom_dir) romgen mv $(build_dir)/rom.v $@ @@ -48,9 +71,14 @@ endif .PHONY: romgen romgen: $(romgen) -f := $(build_dir)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F -$(f): - echo $(VSRCS) > $@ +######################################################################################### +# vivado rules +######################################################################################### +# combine all sources into single .F +f := $(build_dir)/$(long_name).vsrcs.F +$(f): $(sim_common_files) $(all_vsrcs) + $(foreach file,$(all_vsrcs),echo "$(file)" >> $@;) + cat $(sim_common_files) >> $@ bit := $(build_dir)/obj/$(MODEL).bit $(bit): $(romgen) $(f) @@ -63,6 +91,8 @@ $(bit): $(romgen) $(f) -ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')" \ -board "$(BOARD)" +.PHONY: bit +bit: $(bit) # Build .mcs mcs := $(build_dir)/obj/$(MODEL).mcs @@ -72,6 +102,9 @@ $(mcs): $(bit) .PHONY: mcs mcs: $(mcs) +######################################################################################### +# mircosemi rules +######################################################################################### # Build Libero project prjx := $(build_dir)/libero/$(MODEL).prjx $(prjx): $(verilog) @@ -80,7 +113,6 @@ $(prjx): $(verilog) .PHONY: prjx prjx: $(prjx) - ######################################################################################### # general cleanup rules ######################################################################################### @@ -90,4 +122,3 @@ clean: ifneq ($(bootrom_dir),"") $(MAKE) -C $(bootrom_dir) clean endif - $(MAKE) -C $(FPGA_DIR) clean diff --git a/fpga/Makefile.e300artydevkit b/fpga/Makefile.e300artydevkit deleted file mode 100644 index 5f5c595b..00000000 --- a/fpga/Makefile.e300artydevkit +++ /dev/null @@ -1,23 +0,0 @@ -# See LICENSE for license details. -base_dir=$(abspath ..) -BUILD_DIR := $(base_dir)/fpga/builds/e300artydevkit -FPGA_DIR := $(base_dir)/fpga/fpga-shells/xilinx -MODEL := E300ArtyDevKitFPGAChip -PROJECT := sifive.freedom.everywhere.e300artydevkit -export CONFIG_PROJECT := sifive.freedom.everywhere.e300artydevkit -export CONFIG := E300ArtyDevKitConfig -export BOARD := arty -export BOOTROM_DIR := $(base_dir)/fpga/bootrom/xip - -rocketchip_dir := $(base_dir)/generators/rocket-chip -sifiveblocks_dir := $(base_dir)/generators/sifive-blocks -VSRCS := \ - $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ - $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ - $(rocketchip_dir)/src/main/resources/vsrc/EICG_wrapper.v \ - $(sifiveblocks_dir)/vsrc/SRLatch.v \ - $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ - $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ - $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v - -include common.mk diff --git a/fpga/bootrom/xip/Makefile b/fpga/bootrom/xip/Makefile index 57f94d49..e51fd9c5 100644 --- a/fpga/bootrom/xip/Makefile +++ b/fpga/bootrom/xip/Makefile @@ -1,12 +1,17 @@ # RISCV environment variable must be set +# needs the following variables +# LONG_NAME +# BUILD_DIR +# ROCKETCHIP_DIR +# ROMCONF CC=$(RISCV)/bin/riscv64-unknown-elf-gcc OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g LFLAGS=-static -nostdlib -dtb := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dtb -$(dtb): $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dts +dtb := $(BUILD_DIR)/$(LONG_NAME).dtb +$(dtb): $(BUILD_DIR)/$(LONG_NAME).dts dtc -I dts -O dtb -o $@ $< .PHONY: dtb @@ -35,11 +40,11 @@ hex: $(hex) romgen := $(BUILD_DIR)/rom.v $(romgen): $(hex) - $(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ + $(ROCKETCHIP_DIR)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ .PHONY: romgen romgen: $(romgen) .PHONY: clean clean:: - rm -rf $(hex) $(elf) + rm -rf $(hex) $(elf) diff --git a/fpga/common.mk b/fpga/common.mk deleted file mode 100644 index 5466ed7b..00000000 --- a/fpga/common.mk +++ /dev/null @@ -1,119 +0,0 @@ -# See LICENSE for license details. - -# Required variables: -# - MODEL -# - PROJECT -# - CONFIG_PROJECT -# - CONFIG -# - BUILD_DIR -# - FPGA_DIR - -# Optional variables: -# - EXTRA_FPGA_VSRCS - -# export to bootloader -export ROMCONF=$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.conf - -# export to fpga-shells -export FPGA_TOP_SYSTEM=$(MODEL) -export FPGA_BUILD_DIR=$(BUILD_DIR)/$(FPGA_TOP_SYSTEM) -export fpga_common_script_dir=$(FPGA_DIR)/common/tcl -export fpga_board_script_dir=$(FPGA_DIR)/$(BOARD)/tcl - -export BUILD_DIR - -EXTRA_FPGA_VSRCS ?= -PATCHVERILOG ?= "" -BOOTROM_DIR ?= "" - -base_dir=$(abspath ..) -export rocketchip_dir := $(base_dir)/generators/rocket-chip -SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar ++2.12.10 -SBT_PROJECT ?= chipyard -firrtl_dir := $(base_dir)/tools/firrtl - -# Build firrtl.jar and put it where chisel3 can find it. -FIRRTL_JAR := $(base_dir)/lib/firrtl.jar -FIRRTL ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp $(FIRRTL_JAR) firrtl.Driver - -$(FIRRTL_JAR): $(shell find $(firrtl_dir)/src/main/scala -iname "*.scala") - $(MAKE) -C $(firrtl_dir) SBT="$(SBT)" root_dir=$(firrtl_dir) build-scala - mkdir -p $(base_dir)/lib - cp $(firrtl_dir)/utils/bin/firrtl.jar $(FIRRTL_JAR) - -# Build .fir -long_name := $(CONFIG_PROJECT).$(CONFIG) -firrtl := $(BUILD_DIR)/$(long_name).fir -$(firrtl): $(shell find $(base_dir) -name '*.scala') $(FIRRTL_JAR) - mkdir -p $(dir $@) - cd $(base_dir) && $(SBT) "project freedomPlatforms" \ - "runMain chipyard.Generator \ - --target-dir $(BUILD_DIR) \ - --name $(long_name) \ - --top-module $(PROJECT).$(MODEL) \ - --legacy-configs $(CONFIG_PROJECT).$(CONFIG)" - -.PHONY: firrtl -firrtl: $(firrtl) - -# Build .v -verilog := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v -$(verilog): $(firrtl) $(FIRRTL_JAR) - $(FIRRTL) -i $(firrtl) -o $@ -X verilog -ifneq ($(PATCHVERILOG),"") - $(PATCHVERILOG) -endif - -.PHONY: verilog -verilog: $(verilog) - -romgen := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v -$(romgen): $(verilog) -ifneq ($(BOOTROM_DIR),"") - $(MAKE) -C $(BOOTROM_DIR) romgen - mv $(BUILD_DIR)/rom.v $@ -endif - -.PHONY: romgen -romgen: $(romgen) - -f := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F -$(f): - echo $(VSRCS) > $@ - -bit := $(BUILD_DIR)/obj/$(MODEL).bit -$(bit): $(romgen) $(f) - cd $(BUILD_DIR); vivado \ - -nojournal -mode batch \ - -source $(fpga_common_script_dir)/vivado.tcl \ - -tclargs \ - -top-module "$(MODEL)" \ - -F "$(f)" \ - -ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.vivado.tcl')" \ - -board "$(BOARD)" - - -# Build .mcs -mcs := $(BUILD_DIR)/obj/$(MODEL).mcs -$(mcs): $(bit) - cd $(BUILD_DIR); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $< - -.PHONY: mcs -mcs: $(mcs) - -# Build Libero project -prjx := $(BUILD_DIR)/libero/$(MODEL).prjx -$(prjx): $(verilog) - cd $(BUILD_DIR); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(BUILD_DIR) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)" - -.PHONY: prjx -prjx: $(prjx) - -# Clean -.PHONY: clean -clean: -ifneq ($(BOOTROM_DIR),"") - $(MAKE) -C $(BOOTROM_DIR) clean -endif - $(MAKE) -C $(FPGA_DIR) clean - rm -rf $(BUILD_DIR) diff --git a/generators/utilities/src/main/scala/Simulator.scala b/generators/utilities/src/main/scala/Simulator.scala index b2982db7..43edd33a 100644 --- a/generators/utilities/src/main/scala/Simulator.scala +++ b/generators/utilities/src/main/scala/Simulator.scala @@ -11,6 +11,7 @@ case class GenerateSimConfig( sealed trait Simulator object VerilatorSimulator extends Simulator object VCSSimulator extends Simulator +object NotSimulator extends Simulator trait HasGenerateSimConfig { val parser = new scopt.OptionParser[GenerateSimConfig]("GenerateSimFiles") { @@ -22,15 +23,16 @@ trait HasGenerateSimConfig { .action((x, c) => x match { case "verilator" => c.copy(simulator = VerilatorSimulator) case "vcs" => c.copy(simulator = VCSSimulator) + case "none" => c.copy(simulator = NotSimulator) 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") .abbr("td") .valueName("") .action((x, c) => c.copy(targetDir = x)) - .text("Target director to put files") + .text("Target directory to put files") opt[String]("dotFName") .abbr("df") @@ -50,6 +52,7 @@ object GenerateSimFiles extends App with HasGenerateSimConfig { case VerilatorSimulator => s"-FI ${fname}" // vcs pulls headers in with +incdir, doesn't have anything like verilator.h case VCSSimulator => "" + case _ => "" } } else { // do nothing otherwise fname @@ -82,26 +85,31 @@ object GenerateSimFiles extends App with HasGenerateSimConfig { out.close() } def resources(sim: Simulator): Seq[String] = Seq( - "/testchipip/csrc/SimSerial.cc", - "/testchipip/csrc/SimDRAM.cc", - "/testchipip/csrc/mm.h", - "/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", "/vsrc/EICG_wrapper.v", - ) ++ (sim match { // simulator specific files to include - case VerilatorSimulator => Seq( - "/csrc/emulator.cc", - "/csrc/verilator.h", - ) - case VCSSimulator => Seq( - "/vsrc/TestDriver.v", - ) - }) + ) ++ (sim match { + case NotSimulator => Seq() + case _ => Seq( + "/testchipip/csrc/SimSerial.cc", + "/testchipip/csrc/SimDRAM.cc", + "/testchipip/csrc/mm.h", + "/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 = { firrtl.FileUtils.makeDirectory("./bootrom/") From 990362933db4c3b5c40ff0f762ecc1bb6eaa2f79 Mon Sep 17 00:00:00 2001 From: James Dunn Date: Fri, 4 Sep 2020 14:16:42 -0700 Subject: [PATCH 05/28] Simple makefile variable fix to allow make mcs --- fpga/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/Makefile b/fpga/Makefile index 837902bc..ab538116 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -35,8 +35,8 @@ BOARD ?= arty # misc. directories ######################################################################################### bootrom_dir := $(base_dir)/fpga/bootrom/xip -fpga_common_script_dir := $(FPGA_DIR)/common/tcl fpga_dir := $(base_dir)/fpga/fpga-shells/xilinx +fpga_common_script_dir := $(fpga_dir)/common/tcl ######################################################################################### # import other necessary rules and variables From 8eb807a2fdc4b2cf3397ac2ff7a1cbf316e6421a Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 4 Sep 2020 18:55:56 -0700 Subject: [PATCH 06/28] Use DigitalTop in Platform | Use Chipyard BootRom --- fpga/Makefile | 30 +--------- fpga/bootrom/xip/Makefile | 50 ---------------- fpga/bootrom/xip/xip.S | 16 ------ fpga/src/main/scala/arty/Config.scala | 47 ++++++++------- fpga/src/main/scala/arty/FPGAChip.scala | 2 +- fpga/src/main/scala/arty/Platform.scala | 7 ++- fpga/src/main/scala/arty/System.scala | 57 ------------------- .../chipyard/src/main/scala/DigitalTop.scala | 8 +++ 8 files changed, 39 insertions(+), 178 deletions(-) delete mode 100644 fpga/bootrom/xip/Makefile delete mode 100644 fpga/bootrom/xip/xip.S delete mode 100644 fpga/src/main/scala/arty/System.scala diff --git a/fpga/Makefile b/fpga/Makefile index ab538116..835ffb59 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -21,9 +21,9 @@ SUB_PROJECT := fpga SBT_PROJECT := freedomPlatforms MODEL := E300ArtyDevKitFPGAChip VLOG_MODEL := E300ArtyDevKitFPGAChip -MODEL_PACKAGE := sifive.freedom.everywhere.e300artydevkit +MODEL_PACKAGE := chipyard.fpga CONFIG := E300ArtyDevKitConfig -CONFIG_PACKAGE := sifive.freedom.everywhere.e300artydevkit +CONFIG_PACKAGE := chipyard.fpga GENERATOR_PACKAGE := chipyard TB := none # unused TOP := E300ArtyDevKitPlatform @@ -34,7 +34,6 @@ BOARD ?= arty ######################################################################################### # misc. directories ######################################################################################### -bootrom_dir := $(base_dir)/fpga/bootrom/xip fpga_dir := $(base_dir)/fpga/fpga-shells/xilinx fpga_common_script_dir := $(fpga_dir)/common/tcl @@ -49,27 +48,7 @@ include $(base_dir)/common.mk all_vsrcs := \ $(sim_vsrcs) \ $(base_dir)/generators/sifive-blocks/vsrc/SRLatch.v \ - $(fpga_dir)/common/vsrc/PowerOnResetFPGAOnly.v \ - $(build_dir)/$(long_name).rom.v - -######################################################################################### -# build rom for the fpga -######################################################################################### -# needed for bootrom makefile -export BUILD_DIR=$(build_dir) -export ROCKETCHIP_DIR -export LONG_NAME=$(long_name) -export ROMCONF=$(build_dir)/$(long_name).rom.conf - -romgen := $(build_dir)/$(long_name).rom.v -$(romgen): $(sim_vsrcs) -ifneq ($(bootrom_dir),"") - $(MAKE) -C $(bootrom_dir) romgen - mv $(build_dir)/rom.v $@ -endif - -.PHONY: romgen -romgen: $(romgen) + $(fpga_dir)/common/vsrc/PowerOnResetFPGAOnly.v ######################################################################################### # vivado rules @@ -119,6 +98,3 @@ prjx: $(prjx) .PHONY: clean clean: rm -rf $(gen_dir) -ifneq ($(bootrom_dir),"") - $(MAKE) -C $(bootrom_dir) clean -endif diff --git a/fpga/bootrom/xip/Makefile b/fpga/bootrom/xip/Makefile deleted file mode 100644 index e51fd9c5..00000000 --- a/fpga/bootrom/xip/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# RISCV environment variable must be set -# needs the following variables -# LONG_NAME -# BUILD_DIR -# ROCKETCHIP_DIR -# ROMCONF - -CC=$(RISCV)/bin/riscv64-unknown-elf-gcc -OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy -CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g -LFLAGS=-static -nostdlib - -dtb := $(BUILD_DIR)/$(LONG_NAME).dtb -$(dtb): $(BUILD_DIR)/$(LONG_NAME).dts - dtc -I dts -O dtb -o $@ $< - -.PHONY: dtb -dtb: $(dtb) - -elf := $(BUILD_DIR)/xip.elf -$(elf): xip.S $(dtb) - $(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $< - -.PHONY: elf -elf: $(elf) - -bin := $(BUILD_DIR)/xip.bin -$(bin): $(elf) - $(OBJCOPY) -O binary $< $@ - -.PHONY: bin -bin: $(bin) - -hex := $(BUILD_DIR)/xip.hex -$(hex): $(bin) - od -t x4 -An -w4 -v $< > $@ - -.PHONY: hex -hex: $(hex) - -romgen := $(BUILD_DIR)/rom.v -$(romgen): $(hex) - $(ROCKETCHIP_DIR)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ - -.PHONY: romgen -romgen: $(romgen) - -.PHONY: clean -clean:: - rm -rf $(hex) $(elf) diff --git a/fpga/bootrom/xip/xip.S b/fpga/bootrom/xip/xip.S deleted file mode 100644 index 7445f4c9..00000000 --- a/fpga/bootrom/xip/xip.S +++ /dev/null @@ -1,16 +0,0 @@ -// See LICENSE for license details. -// Execute in place -// Jump directly to XIP_TARGET_ADDR - - .section .text.init - .option norvc - .globl _start -_start: - csrr a0, mhartid - la a1, dtb - li t0, XIP_TARGET_ADDR - jr t0 - - .section .rodata -dtb: - .incbin DEVICE_TREE diff --git a/fpga/src/main/scala/arty/Config.scala b/fpga/src/main/scala/arty/Config.scala index 11642164..73fb8b31 100644 --- a/fpga/src/main/scala/arty/Config.scala +++ b/fpga/src/main/scala/arty/Config.scala @@ -1,5 +1,5 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +package chipyard.fpga import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ @@ -16,16 +16,7 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ -// Default FreedomEConfig -class DefaultFreedomEConfig extends Config ( - new WithNBreakpoints(2) ++ - new WithNExtTopInterrupts(0) ++ - new WithJtagDTM ++ - new TinyConfig -) - -// Freedom E300 Arty Dev Kit Peripherals -class E300DevKitPeripherals extends Config((site, here, up) => { +class E300DevKitExtra extends Config((site, here, up) => { case PeripheryGPIOKey => List( GPIOParams(address = 0x10012000, width = 32, includeIOF = true)) case PeripheryPWMKey => List( @@ -47,19 +38,27 @@ class E300DevKitPeripherals extends Config((site, here, up) => { I2CParams(address = 0x10016000)) case PeripheryMockAONKey => MockAONParams(address = 0x10000000) - case MaskROMLocated(InSubsystem) => List(MaskROMParams(address = 0x10000, name = "BootROM")) - case BootROMLocated(InSubsystem) => None + case DTSTimebase => BigInt(32768) + case JtagDTMKey => new JtagDTMConfig ( + idcodeVersion = 2, + idcodePartNum = 0x000, + idcodeManufId = 0x489, + debugIdleCycles = 5) }) -// Freedom E300 Arty Dev Kit Peripherals class E300ArtyDevKitConfig extends Config( - new E300DevKitPeripherals ++ - new DefaultFreedomEConfig().alter((site,here,up) => { - case DTSTimebase => BigInt(32768) - case JtagDTMKey => new JtagDTMConfig ( - idcodeVersion = 2, - idcodePartNum = 0x000, - idcodeManufId = 0x489, - debugIdleCycles = 5) - }) -) + 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) diff --git a/fpga/src/main/scala/arty/FPGAChip.scala b/fpga/src/main/scala/arty/FPGAChip.scala index e0b0634c..26e75500 100644 --- a/fpga/src/main/scala/arty/FPGAChip.scala +++ b/fpga/src/main/scala/arty/FPGAChip.scala @@ -1,5 +1,5 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +package chipyard.fpga import Chisel._ import chisel3.core.{attach} diff --git a/fpga/src/main/scala/arty/Platform.scala b/fpga/src/main/scala/arty/Platform.scala index 14c31628..514ff74c 100644 --- a/fpga/src/main/scala/arty/Platform.scala +++ b/fpga/src/main/scala/arty/Platform.scala @@ -1,5 +1,5 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +package chipyard.fpga import Chisel._ @@ -20,6 +20,8 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.pinctrl._ +import chipyard.{DigitalTop} + //------------------------------------------------------------------------- // PinGen //------------------------------------------------------------------------- @@ -51,8 +53,7 @@ class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { //------------------------------------------------------------------------- class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { - //val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) This can be DigitalTop? - val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) + val sys = Module(LazyModule(new DigitalTop).module) val io = new E300ArtyDevKitPlatformIO // This needs to be de-asserted synchronously to the coreClk. diff --git a/fpga/src/main/scala/arty/System.scala b/fpga/src/main/scala/arty/System.scala deleted file mode 100644 index 46e5c34e..00000000 --- a/fpga/src/main/scala/arty/System.scala +++ /dev/null @@ -1,57 +0,0 @@ -// See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit - -import Chisel._ - -import freechips.rocketchip.config._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.system._ - -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._ - -//------------------------------------------------------------------------- -// E300ArtyDevKitSystem -//------------------------------------------------------------------------- - -class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem - with HasPeripheryDebug - with HasPeripheryMockAON - with chipyard.example.CanHavePeripheryGCD - with HasPeripheryUART - with HasPeripherySPIFlash - with HasPeripherySPI - with HasPeripheryGPIO - with HasPeripheryPWM - with HasPeripheryI2C { - val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) } - val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) } - - val maskROMResetVectorSourceNode = BundleBridgeSource[UInt]() - tileResetVectorNexusNode := maskROMResetVectorSourceNode - - override lazy val module = new E300ArtyDevKitSystemModule(this) -} - -class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) - extends RocketSubsystemModuleImp(_outer) - with HasPeripheryDebugModuleImp - with chipyard.example.CanHavePeripheryGCDModuleImp - with HasPeripheryUARTModuleImp - with HasPeripherySPIModuleImp - with HasPeripheryGPIOModuleImp - with HasPeripherySPIFlashModuleImp - with HasPeripheryMockAONModuleImp - with HasPeripheryPWMModuleImp - with HasPeripheryI2CModuleImp { - - // connect reset vector to 1st MaskROM - _outer.maskROMResetVectorSourceNode.bundle := p(MaskROMLocated(_outer.location))(0).address.U -} diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index 81d0003d..160e6acf 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -13,6 +13,10 @@ import freechips.rocketchip.devices.tilelink._ // DOC include start: DigitalTop class DigitalTop(implicit p: Parameters) extends ChipyardSystem + with sifive.blocks.devices.mockaon.HasPeripheryMockAON + with sifive.blocks.devices.spi.HasPeripherySPI + with sifive.blocks.devices.pwm.HasPeripheryPWM + with sifive.blocks.devices.i2c.HasPeripheryI2C with testchipip.CanHaveTraceIO // Enables optionally adding trace IO with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device @@ -31,6 +35,10 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem } class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) + with sifive.blocks.devices.mockaon.HasPeripheryMockAONModuleImp + with sifive.blocks.devices.spi.HasPeripherySPIModuleImp + with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp + with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp with testchipip.CanHaveTraceIOModuleImp with testchipip.CanHavePeripheryBlockDeviceModuleImp with testchipip.CanHavePeripherySerialModuleImp From 1fa1b6d57f1bc5dc0e2a1cbe248501af843f7e82 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 4 Sep 2020 19:03:26 -0700 Subject: [PATCH 07/28] Small makefile cleanup --- fpga/Makefile | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/fpga/Makefile b/fpga/Makefile index 835ffb59..e0882e63 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -31,6 +31,9 @@ TOP := E300ArtyDevKitPlatform # setup the board to use BOARD ?= arty +.PHONY: default +default: $(mcs) + ######################################################################################### # misc. directories ######################################################################################### @@ -53,44 +56,33 @@ all_vsrcs := \ ######################################################################################### # vivado rules ######################################################################################### -# combine all sources into single .F -f := $(build_dir)/$(long_name).vsrcs.F -$(f): $(sim_common_files) $(all_vsrcs) +# 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 := $(build_dir)/obj/$(MODEL).bit -$(bit): $(romgen) $(f) +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 "$(f)" \ + -F "$(synth_list_f)" \ -ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')" \ -board "$(BOARD)" .PHONY: bit -bit: $(bit) +bit: $(BIT_FILE) # Build .mcs -mcs := $(build_dir)/obj/$(MODEL).mcs -$(mcs): $(bit) +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) - -######################################################################################### -# mircosemi rules -######################################################################################### -# Build Libero project -prjx := $(build_dir)/libero/$(MODEL).prjx -$(prjx): $(verilog) - cd $(build_dir); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(build_dir) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)" - -.PHONY: prjx -prjx: $(prjx) +mcs: $(MCS_FILE) ######################################################################################### # general cleanup rules From a8083aa5709d9c17591de3d55bd146cba6ced532 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Mon, 7 Sep 2020 11:47:37 -0700 Subject: [PATCH 08/28] First pass at fpga-shells with IOBinders --- build.sbt | 6 +- common.mk | 2 +- fpga/Makefile | 12 +- fpga/src/main/scala/arty/Config.scala | 3 +- fpga/src/main/scala/arty/FPGAChip.scala | 193 ----------- fpga/src/main/scala/arty/IOBinders.scala | 357 +++++++++++++++++++++ fpga/src/main/scala/arty/Platform.scala | 180 ----------- fpga/src/main/scala/arty/TestHarness.scala | 34 ++ 8 files changed, 403 insertions(+), 384 deletions(-) delete mode 100644 fpga/src/main/scala/arty/FPGAChip.scala create mode 100644 fpga/src/main/scala/arty/IOBinders.scala delete mode 100644 fpga/src/main/scala/arty/Platform.scala create mode 100644 fpga/src/main/scala/arty/TestHarness.scala diff --git a/build.sbt b/build.sbt index 31bb3f88..ffe8bfe8 100644 --- a/build.sbt +++ b/build.sbt @@ -217,10 +217,10 @@ lazy val firechip = conditionalDependsOn(project in file("generators/firechip")) testGrouping in Test := isolateAllTests( (definedTests in Test).value ), testOptions in Test += Tests.Argument("-oF") ) -lazy val fpgaShells = (project in file("./fpga/fpga-shells")) +lazy val fpga_shells = (project in file("./fpga/fpga-shells")) .dependsOn(rocketchip, sifive_blocks) .settings(commonSettings) -lazy val freedomPlatforms = (project in file("./fpga")) - .dependsOn(chipyard, fpgaShells) +lazy val fpga_platforms = (project in file("./fpga")) + .dependsOn(chipyard, fpga_shells) .settings(commonSettings) diff --git a/common.mk b/common.mk index 89ebbea3..ee290ddc 100644 --- a/common.mk +++ b/common.mk @@ -58,7 +58,7 @@ include $(base_dir)/tools/dromajo/dromajo.mk # 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) -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) VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v) # This assumes no SBT meta-build sources diff --git a/fpga/Makefile b/fpga/Makefile index e0882e63..0110bb10 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -18,15 +18,15 @@ include $(base_dir)/variables.mk # default variables to build the arty example SUB_PROJECT := fpga -SBT_PROJECT := freedomPlatforms -MODEL := E300ArtyDevKitFPGAChip -VLOG_MODEL := E300ArtyDevKitFPGAChip -MODEL_PACKAGE := chipyard.fpga +SBT_PROJECT := fpga_platforms +MODEL := ArtyFPGATestHarness +VLOG_MODEL := ArtyFPGATestHarness +MODEL_PACKAGE := chipyard.fpga.arty CONFIG := E300ArtyDevKitConfig -CONFIG_PACKAGE := chipyard.fpga +CONFIG_PACKAGE := chipyard.fpga.arty GENERATOR_PACKAGE := chipyard TB := none # unused -TOP := E300ArtyDevKitPlatform +TOP := ChipTop # setup the board to use BOARD ?= arty diff --git a/fpga/src/main/scala/arty/Config.scala b/fpga/src/main/scala/arty/Config.scala index 73fb8b31..bcea7c78 100644 --- a/fpga/src/main/scala/arty/Config.scala +++ b/fpga/src/main/scala/arty/Config.scala @@ -1,5 +1,5 @@ // See LICENSE for license details. -package chipyard.fpga +package chipyard.fpga.arty import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ @@ -47,6 +47,7 @@ class E300DevKitExtra extends Config((site, here, up) => { }) class E300ArtyDevKitConfig extends Config( + new WithE300Connections ++ new E300DevKitExtra ++ new chipyard.config.WithBootROM ++ new chipyard.config.WithL2TLBs(1024) ++ diff --git a/fpga/src/main/scala/arty/FPGAChip.scala b/fpga/src/main/scala/arty/FPGAChip.scala deleted file mode 100644 index 26e75500..00000000 --- a/fpga/src/main/scala/arty/FPGAChip.scala +++ /dev/null @@ -1,193 +0,0 @@ -// See LICENSE for license details. -package chipyard.fpga - -import Chisel._ -import chisel3.core.{attach} -import chisel3.experimental.{withClockAndReset} - -import freechips.rocketchip.config._ -import freechips.rocketchip.diplomacy.{LazyModule} - -import sifive.blocks.devices.gpio._ -import sifive.blocks.devices.spi._ - -import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} -import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} - -//------------------------------------------------------------------------- -// E300ArtyDevKitFPGAChip -//------------------------------------------------------------------------- - -class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell { - - //----------------------------------------------------------------------- - // Clock divider - //----------------------------------------------------------------------- - val slow_clock = Wire(Bool()) - - // Divide clock by 256, used to generate 32.768 kHz clock for AON block - withClockAndReset(clock_8MHz, ~mmcm_locked) { - val clockToggleReg = RegInit(false.B) - val (_, slowTick) = Counter(true.B, 256) - when (slowTick) {clockToggleReg := ~clockToggleReg} - slow_clock := clockToggleReg - } - - //----------------------------------------------------------------------- - // DUT - //----------------------------------------------------------------------- - - withClockAndReset(clock_32MHz, ck_rst) { - val dut = Module(new E300ArtyDevKitPlatform) - - //--------------------------------------------------------------------- - // SPI flash IOBUFs - //--------------------------------------------------------------------- - - IOBUF(qspi_sck, dut.io.pins.qspi.sck) - IOBUF(qspi_cs, dut.io.pins.qspi.cs(0)) - - IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0)) - IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1)) - IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2)) - IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3)) - - //--------------------------------------------------------------------- - // JTAG IOBUFs - //--------------------------------------------------------------------- - - dut.io.pins.jtag.TCK.i.ival := IBUFG(IOBUF(jd_2).asClock).asUInt - - IOBUF(jd_5, dut.io.pins.jtag.TMS) - PULLUP(jd_5) - - IOBUF(jd_4, dut.io.pins.jtag.TDI) - PULLUP(jd_4) - - IOBUF(jd_0, dut.io.pins.jtag.TDO) - - // mimic putting a pullup on this line (part of reset vote) - SRST_n := IOBUF(jd_6) - PULLUP(jd_6) - - // jtag reset - val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_32MHz) - dut.io.jtag_reset := jtag_power_on_reset - - // debug reset - dut_ndreset := dut.io.ndreset - - //--------------------------------------------------------------------- - // Assignment to package pins - //--------------------------------------------------------------------- - // Pins IO0-IO13 - // - // FTDI UART TX/RX are not connected to 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 := dut.io.pins.gpio.pins(16).o.oval - iobuf_ck0.io.T := ~dut.io.pins.gpio.pins(16).o.oe - attach(iobuf_ck0.io.IO, ck_io(0)) // UART0 RX - - val iobuf_uart_txd = Module(new IOBUF()) - iobuf_uart_txd.io.I := dut.io.pins.gpio.pins(16).o.oval - iobuf_uart_txd.io.T := ~dut.io.pins.gpio.pins(16).o.oe - attach(iobuf_uart_txd.io.IO, 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(sw_3) - dut.io.pins.gpio.pins(16).i.ival := Mux(sw_3_in, - iobuf_ck0.io.O & dut.io.pins.gpio.pins(16).o.ie, - iobuf_uart_txd.io.O & dut.io.pins.gpio.pins(16).o.ie) - - IOBUF(uart_rxd_out, dut.io.pins.gpio.pins(17)) - - // Shield header row 0: PD2-PD7 - IOBUF(ck_io(2), dut.io.pins.gpio.pins(18)) - IOBUF(ck_io(3), dut.io.pins.gpio.pins(19)) // PWM1(1) - IOBUF(ck_io(4), dut.io.pins.gpio.pins(20)) // PWM1(0) - IOBUF(ck_io(5), dut.io.pins.gpio.pins(21)) // PWM1(2) - IOBUF(ck_io(6), dut.io.pins.gpio.pins(22)) // PWM1(3) - IOBUF(ck_io(7), dut.io.pins.gpio.pins(23)) - - // Header row 1: PB0-PB5 - IOBUF(ck_io(8), dut.io.pins.gpio.pins(0)) // PWM0(0) - IOBUF(ck_io(9), dut.io.pins.gpio.pins(1)) // PWM0(1) - IOBUF(ck_io(10), dut.io.pins.gpio.pins(2)) // SPI CS(0) / PWM0(2) - IOBUF(ck_io(11), dut.io.pins.gpio.pins(3)) // SPI MOSI / PWM0(3) - IOBUF(ck_io(12), dut.io.pins.gpio.pins(4)) // SPI MISO - IOBUF(ck_io(13), dut.io.pins.gpio.pins(5)) // SPI SCK - - dut.io.pins.gpio.pins(6).i.ival := 0.U - dut.io.pins.gpio.pins(7).i.ival := 0.U - dut.io.pins.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(ck_io(15), dut.io.pins.gpio.pins(9)) // A1 = CS(2) - IOBUF(ck_io(16), dut.io.pins.gpio.pins(10)) // A2 = CS(3) / PWM2(0) - IOBUF(ck_io(17), dut.io.pins.gpio.pins(11)) // A3 = PWM2(1) - IOBUF(ck_io(18), dut.io.pins.gpio.pins(12)) // A4 = PWM2(2) / SDA - IOBUF(ck_io(19), dut.io.pins.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(led0_r, dut.io.pins.gpio.pins(1)) - IOBUF(led0_g, dut.io.pins.gpio.pins(2)) - IOBUF(led0_b, dut.io.pins.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(led1_r, dut.io.pins.gpio.pins(19)) - IOBUF(led1_g, dut.io.pins.gpio.pins(21)) - IOBUF(led1_b, dut.io.pins.gpio.pins(22)) - - // and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active - IOBUF(led2_r, dut.io.pins.gpio.pins(11)) - IOBUF(led2_g, dut.io.pins.gpio.pins(12)) - IOBUF(led2_b, dut.io.pins.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(btn_0, dut.io.pins.gpio.pins(15)) - IOBUF(btn_1, dut.io.pins.gpio.pins(30)) - IOBUF(btn_2, dut.io.pins.gpio.pins(31)) - - val iobuf_btn_3 = Module(new IOBUF()) - iobuf_btn_3.io.I := ~dut.io.pins.aon.pmu.dwakeup_n.o.oval - iobuf_btn_3.io.T := ~dut.io.pins.aon.pmu.dwakeup_n.o.oe - attach(btn_3, iobuf_btn_3.io.IO) - dut.io.pins.aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & dut.io.pins.aon.pmu.dwakeup_n.o.ie - - // UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1 - IOBUF(ja_0, dut.io.pins.gpio.pins(25)) // UART1 TX - IOBUF(ja_1, dut.io.pins.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(ck_ss, dut.io.pins.gpio.pins(26)) - IOBUF(ck_mosi, dut.io.pins.gpio.pins(27)) - IOBUF(ck_miso, dut.io.pins.gpio.pins(28)) - IOBUF(ck_sck, dut.io.pins.gpio.pins(29)) - - // Use the LEDs for some more useful debugging things - IOBUF(led_0, ck_rst) - IOBUF(led_1, SRST_n) - IOBUF(led_2, dut.io.pins.aon.pmu.dwakeup_n.i.ival) - IOBUF(led_3, dut.io.pins.gpio.pins(14)) - - //--------------------------------------------------------------------- - // Unconnected inputs - //--------------------------------------------------------------------- - - dut.io.pins.aon.erst_n.i.ival := ~reset_periph - dut.io.pins.aon.lfextclk.i.ival := slow_clock - dut.io.pins.aon.pmu.vddpaden.i.ival := 1.U - } -} diff --git a/fpga/src/main/scala/arty/IOBinders.scala b/fpga/src/main/scala/arty/IOBinders.scala new file mode 100644 index 00000000..e8833827 --- /dev/null +++ b/fpga/src/main/scala/arty/IOBinders.scala @@ -0,0 +1,357 @@ +package chipyard.fpga.arty + +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) => { + // match the E300 connections using a "Chipyard"-like structure + + implicit val p: Parameters = GetSystemParameters(system) + + 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") + + // TODO: Fix + // add iocells (or none) + // 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 + + 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))) + } +}) + diff --git a/fpga/src/main/scala/arty/Platform.scala b/fpga/src/main/scala/arty/Platform.scala deleted file mode 100644 index 514ff74c..00000000 --- a/fpga/src/main/scala/arty/Platform.scala +++ /dev/null @@ -1,180 +0,0 @@ -// See LICENSE for license details. -package chipyard.fpga - -import Chisel._ - -import freechips.rocketchip.config._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util.ResetCatchAndSync -import freechips.rocketchip.system._ - -import sifive.blocks.devices.mockaon._ -import sifive.blocks.devices.gpio._ -import sifive.blocks.devices.jtag._ -import sifive.blocks.devices.pwm._ -import sifive.blocks.devices.spi._ -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.i2c._ -import sifive.blocks.devices.pinctrl._ - -import chipyard.{DigitalTop} - -//------------------------------------------------------------------------- -// PinGen -//------------------------------------------------------------------------- - -object PinGen { - def apply(): BasePin = { - val pin = new BasePin() - pin - } -} - -//------------------------------------------------------------------------- -// E300ArtyDevKitPlatformIO -//------------------------------------------------------------------------- - -class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { - val pins = new Bundle { - val jtag = new JTAGPins(() => PinGen(), false) - val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0)) - val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) - val aon = new MockAONWrapperPins() - } - val jtag_reset = Bool(INPUT) - val ndreset = Bool(OUTPUT) -} - -//------------------------------------------------------------------------- -// E300ArtyDevKitPlatform -//------------------------------------------------------------------------- - -class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { - val sys = Module(LazyModule(new DigitalTop).module) - val io = new E300ArtyDevKitPlatformIO - - // This needs to be de-asserted synchronously to the coreClk. - val async_corerst = sys.aon.rsts.corerst - // Add in debug-controlled reset. - sys.reset := ResetCatchAndSync(clock, async_corerst, 20) - Debug.connectDebugClockAndReset(sys.debug, 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 = sys.uart - val sys_pwm = sys.pwm - val sys_spi = sys.spi - val sys_i2c = sys.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 = clock, reset = reset, 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 = clock, reset = reset, syncStages = 0)} - (i2c_pins zip sys_i2c) map {case (p, r) => I2CPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)} - - //----------------------------------------------------------------------- - // Default Pin connections before attaching pinmux - - for (iof_0 <- sys.gpio(0).iof_0.get) { - iof_0.default() - } - - for (iof_1 <- sys.gpio(0).iof_1.get) { - iof_1.default() - } - - //----------------------------------------------------------------------- - - val iof_0 = sys.gpio(0).iof_0.get - val iof_1 = sys.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.pins.gpio, sys.gpio(0)) - - // Dedicated SPI Pads - SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3) - - // JTAG Debug Interface - val sjtag = sys.debug.get.systemjtag.get - JTAGPinsFromPort(io.pins.jtag, sjtag.jtag) - sjtag.reset := io.jtag_reset - sjtag.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) - - io.ndreset := sys.debug.get.ndreset - - // AON Pads -- direct connection is OK because - // EnhancedPin is hard-coded in MockAONPads - // and thus there is no .fromPort method. - io.pins.aon <> sys.aon.pins -} diff --git a/fpga/src/main/scala/arty/TestHarness.scala b/fpga/src/main/scala/arty/TestHarness.scala new file mode 100644 index 00000000..919e5c99 --- /dev/null +++ b/fpga/src/main/scala/arty/TestHarness.scala @@ -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)) +} + From c49eef32241ff2a112628d5999ffec89c2f8179d Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Mon, 7 Sep 2020 15:26:30 -0700 Subject: [PATCH 09/28] Small cleanup to CY DigitalTop | Move E300 configs to unique folder --- fpga/Makefile | 2 +- .../arty/{Config.scala => e300/Configs.scala} | 9 +++++++- .../src/main/scala/arty/e300/DigitalTop.scala | 23 +++++++++++++++++++ .../scala/arty/{ => e300}/IOBinders.scala | 2 +- .../chipyard/src/main/scala/DigitalTop.scala | 14 +++++------ 5 files changed, 39 insertions(+), 11 deletions(-) rename fpga/src/main/scala/arty/{Config.scala => e300/Configs.scala} (92%) create mode 100644 fpga/src/main/scala/arty/e300/DigitalTop.scala rename fpga/src/main/scala/arty/{ => e300}/IOBinders.scala (99%) diff --git a/fpga/Makefile b/fpga/Makefile index 0110bb10..c1e4fb2d 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -23,7 +23,7 @@ MODEL := ArtyFPGATestHarness VLOG_MODEL := ArtyFPGATestHarness MODEL_PACKAGE := chipyard.fpga.arty CONFIG := E300ArtyDevKitConfig -CONFIG_PACKAGE := chipyard.fpga.arty +CONFIG_PACKAGE := chipyard.fpga.arty.e300 GENERATOR_PACKAGE := chipyard TB := none # unused TOP := ChipTop diff --git a/fpga/src/main/scala/arty/Config.scala b/fpga/src/main/scala/arty/e300/Configs.scala similarity index 92% rename from fpga/src/main/scala/arty/Config.scala rename to fpga/src/main/scala/arty/e300/Configs.scala index bcea7c78..dd9213fc 100644 --- a/fpga/src/main/scala/arty/Config.scala +++ b/fpga/src/main/scala/arty/e300/Configs.scala @@ -1,5 +1,5 @@ // See LICENSE for license details. -package chipyard.fpga.arty +package chipyard.fpga.arty.e300 import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ @@ -16,6 +16,8 @@ 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)) @@ -46,7 +48,12 @@ class E300DevKitExtra extends Config((site, here, up) => { 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 ++ diff --git a/fpga/src/main/scala/arty/e300/DigitalTop.scala b/fpga/src/main/scala/arty/e300/DigitalTop.scala new file mode 100644 index 00000000..1bda2680 --- /dev/null +++ b/fpga/src/main/scala/arty/e300/DigitalTop.scala @@ -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 diff --git a/fpga/src/main/scala/arty/IOBinders.scala b/fpga/src/main/scala/arty/e300/IOBinders.scala similarity index 99% rename from fpga/src/main/scala/arty/IOBinders.scala rename to fpga/src/main/scala/arty/e300/IOBinders.scala index e8833827..d9a2e1cc 100644 --- a/fpga/src/main/scala/arty/IOBinders.scala +++ b/fpga/src/main/scala/arty/e300/IOBinders.scala @@ -1,4 +1,4 @@ -package chipyard.fpga.arty +package chipyard.fpga.arty.e300 import chisel3._ import chisel3.experimental.{attach, IO} diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index 160e6acf..9e40cfab 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -13,10 +13,6 @@ import freechips.rocketchip.devices.tilelink._ // DOC include start: DigitalTop class DigitalTop(implicit p: Parameters) extends ChipyardSystem - with sifive.blocks.devices.mockaon.HasPeripheryMockAON - with sifive.blocks.devices.spi.HasPeripherySPI - with sifive.blocks.devices.pwm.HasPeripheryPWM - with sifive.blocks.devices.i2c.HasPeripheryI2C with testchipip.CanHaveTraceIO // Enables optionally adding trace IO with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device @@ -24,6 +20,9 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem 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.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 chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget @@ -35,16 +34,15 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem } class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) - with sifive.blocks.devices.mockaon.HasPeripheryMockAONModuleImp - with sifive.blocks.devices.spi.HasPeripherySPIModuleImp - with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp - with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp with testchipip.CanHaveTraceIOModuleImp with testchipip.CanHavePeripheryBlockDeviceModuleImp with testchipip.CanHavePeripherySerialModuleImp with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp 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 icenet.CanHavePeripheryIceNICModuleImp with chipyard.example.CanHavePeripheryGCDModuleImp with freechips.rocketchip.util.DontTouch From 2580073d75cd98838f4ccf9ae3757e158a2d25f2 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Mon, 7 Sep 2020 15:30:21 -0700 Subject: [PATCH 10/28] Comment cleanup --- fpga/src/main/scala/arty/e300/IOBinders.scala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fpga/src/main/scala/arty/e300/IOBinders.scala b/fpga/src/main/scala/arty/e300/IOBinders.scala index d9a2e1cc..8d866619 100644 --- a/fpga/src/main/scala/arty/e300/IOBinders.scala +++ b/fpga/src/main/scala/arty/e300/IOBinders.scala @@ -33,10 +33,15 @@ class WithE300Connections extends OverrideIOBinder({ with HasPeripherySPIFlashModuleImp with HasPeripheryMockAONModuleImp with HasPeripheryI2CModuleImp) => { - // match the E300 connections using a "Chipyard"-like structure implicit val p: Parameters = GetSystemParameters(system) + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // E300DigitalTop <-> ChipTop connections + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + object PinGen { def apply(): BasePin = { val pin = new BasePin() @@ -51,8 +56,6 @@ class WithE300Connections extends OverrideIOBinder({ val io_jtag_reset = IO(Input(Bool())).suggestName("jtag_reset") val io_ndreset = IO(Output(Bool())).suggestName("ndreset") - // TODO: Fix - // add iocells (or none) // This needs to be de-asserted synchronously to the coreClk. val async_corerst = system.aon.rsts.corerst // Add in debug-controlled reset. @@ -175,6 +178,11 @@ class WithE300Connections extends OverrideIOBinder({ // 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 => From 56eead4053df7f7a2c284e9aa7602ca544e18011 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Tue, 8 Sep 2020 17:04:56 -0700 Subject: [PATCH 11/28] NOT WORKING: VCU118 Commit --- build.sbt | 2 +- fpga/Makefile | 10 +-- fpga/src/main/scala/vcu118/Configs.scala | 51 ++++++++++++++ fpga/src/main/scala/vcu118/IOBinders.scala | 69 +++++++++++++++++++ fpga/src/main/scala/vcu118/Shell.scala | 0 fpga/src/main/scala/vcu118/TestHarness.scala | 36 ++++++++++ .../chipyard/src/main/scala/ChipTop.scala | 1 + 7 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 fpga/src/main/scala/vcu118/Configs.scala create mode 100644 fpga/src/main/scala/vcu118/IOBinders.scala create mode 100644 fpga/src/main/scala/vcu118/Shell.scala create mode 100644 fpga/src/main/scala/vcu118/TestHarness.scala diff --git a/build.sbt b/build.sbt index ffe8bfe8..3420955b 100644 --- a/build.sbt +++ b/build.sbt @@ -218,7 +218,7 @@ lazy val firechip = conditionalDependsOn(project in file("generators/firechip")) testOptions in Test += Tests.Argument("-oF") ) lazy val fpga_shells = (project in file("./fpga/fpga-shells")) - .dependsOn(rocketchip, sifive_blocks) + .dependsOn(rocketchip, sifive_blocks, chipyard) .settings(commonSettings) lazy val fpga_platforms = (project in file("./fpga")) diff --git a/fpga/Makefile b/fpga/Makefile index c1e4fb2d..643e0c67 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -19,11 +19,11 @@ include $(base_dir)/variables.mk # default variables to build the arty example SUB_PROJECT := fpga SBT_PROJECT := fpga_platforms -MODEL := ArtyFPGATestHarness -VLOG_MODEL := ArtyFPGATestHarness -MODEL_PACKAGE := chipyard.fpga.arty -CONFIG := E300ArtyDevKitConfig -CONFIG_PACKAGE := chipyard.fpga.arty.e300 +MODEL := VCU118FPGATestHarness +VLOG_MODEL := VCU118FPGATestHarness +MODEL_PACKAGE := chipyard.fpga.vcu118 +CONFIG := FakeBringupConfig +CONFIG_PACKAGE := chipyard.fpga.vcu118 GENERATOR_PACKAGE := chipyard TB := none # unused TOP := ChipTop diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala new file mode 100644 index 00000000..a98aa3cf --- /dev/null +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -0,0 +1,51 @@ +// See LICENSE for license details. +package chipyard.fpga.vcu118 + +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 sifive.fpgashells.shell.{DesignKey} + +import chipyard.{BuildTop} + +class WithChipyardBuildTop extends Config((site, here, up) => { + //case DesignKey => { (p:Parameters) => p(BuildTop)(p) } + case DesignKey => {(p: Parameters) => new chipyard.ChipTop()(p) } +}) + +class WithBringupUARTs extends Config((site, here, up) => { + case PeripheryUARTKey => List( + UARTParams(address = BigInt(0x64000000L)), + UARTParams(address = BigInt(0x64003000L))) +}) + +class FakeBringupConfig extends Config( + new WithUARTConnection1 ++ + new WithBringupUARTs ++ + new WithChipyardBuildTop ++ + 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) diff --git a/fpga/src/main/scala/vcu118/IOBinders.scala b/fpga/src/main/scala/vcu118/IOBinders.scala new file mode 100644 index 00000000..dfec55cc --- /dev/null +++ b/fpga/src/main/scala/vcu118/IOBinders.scala @@ -0,0 +1,69 @@ +package chipyard.fpga.vcu118 + +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._ +import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} + +import chipsalliance.rocketchip.config._ +import sifive.fpgashells.shell._ + +import chipyard.iobinders.{OverrideIOBinder, GetSystemParameters} +import chipyard.{HasHarnessSignalReferences} +import freechips.rocketchip.diplomacy._ + +class WithUARTConnection1 extends OverrideIOBinder({ + (system: HasPeripheryUARTModuleImp) => { + + implicit val p: Parameters = GetSystemParameters(system) + + val io_uart_pins = p(PeripheryUARTKey).zipWithIndex map { case (c, i) => IO(new UARTPortIO(c)).suggestName(s"uart_$i") } + (io_uart_pins zip system.uart) map { case (p, r) => p <> r } + + val harnessFn = (th: HasHarnessSignalReferences) => { + println(th) + println("Got here - -- - - - ") + Nil + } + //val harnessFn = (baseTh: HasHarnessSignalReferences) => { + // println("DEBUG: ---------------------- 0") + // baseTh match { case th: VCU118Shell => + // println("DEBUG: ---------------------- 1") + + // val io_uart_pins_bb = p(PeripheryUARTKey) map { c => BundleBridgeSource(() => (new UARTPortIO(c))) } + + // InModuleBody { + // (io_uart_pins_bb zip io_uart_pins) map { case (p, r) => p.bundle <> r } + // } + + // require(p(PeripheryUARTKey).size >= 1) + + // println("DEBUG: ---------------------- 2") + + // th.designParameters(UARTOverlayKey).foreach { uok => + // println("DEBUG: ---------------------- 3") + // uok.place(UARTDesignInput(io_uart_pins_bb(0))).overlayOutput + // } + + // Nil + // } + //} + + Seq((Nil, Nil, Some(harnessFn))) + } +}) + diff --git a/fpga/src/main/scala/vcu118/Shell.scala b/fpga/src/main/scala/vcu118/Shell.scala new file mode 100644 index 00000000..e69de29b diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala new file mode 100644 index 00000000..6da984bf --- /dev/null +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -0,0 +1,36 @@ +package chipyard.fpga.vcu118 + +import chisel3._ +import chisel3.experimental.{Analog, IO} + +import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp} +import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.diplomacy.{InModuleBody} + +import sifive.fpgashells.shell.xilinx._ +import sifive.fpgashells.ip.xilinx._ +import sifive.fpgashells.shell._ +import sifive.fpgashells.clocks._ + +import chipyard.{BuildTop, HasHarnessSignalReferences, HasTestHarnessFunctions} + +class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell with HasHarnessSignalReferences { + val pllResetAsReset = InModuleBody{ Wire(Reset()) } + + InModuleBody { + pllResetAsReset := pllReset + } + + lazy val harnessClock = this.module.sysclk + lazy val harnessReset = pllResetAsReset.getWrappedValue + val success = false.B + lazy val dutReset = pllResetAsReset.getWrappedValue + + // must be after HasHarnessSignalReferences assignments + println(s"DEBUG: ----- sz:${topDesign.harnessFunctions.size}") + topDesign match { case d: HasTestHarnessFunctions => + println(s"DEBUG: ----- sz:${d.harnessFunctions.size}") + d.harnessFunctions.foreach(_(this)) + } +} + diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index cf71987b..2df79ec2 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -55,6 +55,7 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc // We ignore _ports for now... iocells ++= _iocells.flatten harnessFunctions ++= _harnessFunctions.flatten + println(s"ChipTop: sz:${harnessFunctions.size}") } // Connect the implicit clock/reset, if present From e98a0f172f92cbf37d6aed258267a502b90fc1fa Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 11 Sep 2020 16:55:25 -0700 Subject: [PATCH 12/28] Connected UART nicely --- fpga/Makefile | 2 +- fpga/src/main/scala/vcu118/Configs.scala | 6 +- fpga/src/main/scala/vcu118/IOBinders.scala | 69 -------------------- fpga/src/main/scala/vcu118/Shell.scala | 0 fpga/src/main/scala/vcu118/TestHarness.scala | 25 +++---- 5 files changed, 11 insertions(+), 91 deletions(-) delete mode 100644 fpga/src/main/scala/vcu118/IOBinders.scala delete mode 100644 fpga/src/main/scala/vcu118/Shell.scala diff --git a/fpga/Makefile b/fpga/Makefile index 643e0c67..f3f6308b 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -26,7 +26,7 @@ CONFIG := FakeBringupConfig CONFIG_PACKAGE := chipyard.fpga.vcu118 GENERATOR_PACKAGE := chipyard TB := none # unused -TOP := ChipTop +TOP := VCU118Platform # setup the board to use BOARD ?= arty diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index a98aa3cf..ba88377f 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -21,8 +21,7 @@ import sifive.fpgashells.shell.{DesignKey} import chipyard.{BuildTop} class WithChipyardBuildTop extends Config((site, here, up) => { - //case DesignKey => { (p:Parameters) => p(BuildTop)(p) } - case DesignKey => {(p: Parameters) => new chipyard.ChipTop()(p) } + case DesignKey => {(p: Parameters) => new VCU118Platform()(p) } }) class WithBringupUARTs extends Config((site, here, up) => { @@ -32,7 +31,6 @@ class WithBringupUARTs extends Config((site, here, up) => { }) class FakeBringupConfig extends Config( - new WithUARTConnection1 ++ new WithBringupUARTs ++ new WithChipyardBuildTop ++ new chipyard.config.WithBootROM ++ @@ -47,5 +45,5 @@ class FakeBringupConfig extends Config( new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithIncoherentBusTopology ++ + new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.system.BaseConfig) diff --git a/fpga/src/main/scala/vcu118/IOBinders.scala b/fpga/src/main/scala/vcu118/IOBinders.scala deleted file mode 100644 index dfec55cc..00000000 --- a/fpga/src/main/scala/vcu118/IOBinders.scala +++ /dev/null @@ -1,69 +0,0 @@ -package chipyard.fpga.vcu118 - -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._ -import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} - -import chipsalliance.rocketchip.config._ -import sifive.fpgashells.shell._ - -import chipyard.iobinders.{OverrideIOBinder, GetSystemParameters} -import chipyard.{HasHarnessSignalReferences} -import freechips.rocketchip.diplomacy._ - -class WithUARTConnection1 extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp) => { - - implicit val p: Parameters = GetSystemParameters(system) - - val io_uart_pins = p(PeripheryUARTKey).zipWithIndex map { case (c, i) => IO(new UARTPortIO(c)).suggestName(s"uart_$i") } - (io_uart_pins zip system.uart) map { case (p, r) => p <> r } - - val harnessFn = (th: HasHarnessSignalReferences) => { - println(th) - println("Got here - -- - - - ") - Nil - } - //val harnessFn = (baseTh: HasHarnessSignalReferences) => { - // println("DEBUG: ---------------------- 0") - // baseTh match { case th: VCU118Shell => - // println("DEBUG: ---------------------- 1") - - // val io_uart_pins_bb = p(PeripheryUARTKey) map { c => BundleBridgeSource(() => (new UARTPortIO(c))) } - - // InModuleBody { - // (io_uart_pins_bb zip io_uart_pins) map { case (p, r) => p.bundle <> r } - // } - - // require(p(PeripheryUARTKey).size >= 1) - - // println("DEBUG: ---------------------- 2") - - // th.designParameters(UARTOverlayKey).foreach { uok => - // println("DEBUG: ---------------------- 3") - // uok.place(UARTDesignInput(io_uart_pins_bb(0))).overlayOutput - // } - - // Nil - // } - //} - - Seq((Nil, Nil, Some(harnessFn))) - } -}) - diff --git a/fpga/src/main/scala/vcu118/Shell.scala b/fpga/src/main/scala/vcu118/Shell.scala deleted file mode 100644 index e69de29b..00000000 diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 6da984bf..0bce7c97 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -5,32 +5,23 @@ import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp} import freechips.rocketchip.config.{Parameters} -import freechips.rocketchip.diplomacy.{InModuleBody} +import freechips.rocketchip.diplomacy.{InModuleBody, BundleBridgeSource} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx._ import sifive.fpgashells.shell._ import sifive.fpgashells.clocks._ -import chipyard.{BuildTop, HasHarnessSignalReferences, HasTestHarnessFunctions} +import sifive.blocks.devices.uart._ -class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell with HasHarnessSignalReferences { - val pllResetAsReset = InModuleBody{ Wire(Reset()) } +class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell { - InModuleBody { - pllResetAsReset := pllReset - } + require(p(PeripheryUARTKey).size >= 1) - lazy val harnessClock = this.module.sysclk - lazy val harnessReset = pllResetAsReset.getWrappedValue - val success = false.B - lazy val dutReset = pllResetAsReset.getWrappedValue - - // must be after HasHarnessSignalReferences assignments - println(s"DEBUG: ----- sz:${topDesign.harnessFunctions.size}") - topDesign match { case d: HasTestHarnessFunctions => - println(s"DEBUG: ----- sz:${d.harnessFunctions.size}") - d.harnessFunctions.foreach(_(this)) + designParameters(UARTOverlayKey).foreach { uok => + topDesign match { case td: HasPlatformIO => + io_uart_bb)) + } } } From 382e5f1ae8061b0934e5d53d7aa89d473c852a50 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 11 Sep 2020 17:02:22 -0700 Subject: [PATCH 13/28] Add forgotten file --- fpga/src/main/scala/vcu118/Platform.scala | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 fpga/src/main/scala/vcu118/Platform.scala diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala new file mode 100644 index 00000000..3a4cac8a --- /dev/null +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -0,0 +1,40 @@ +package chipyard.fpga.vcu118 + +import chisel3._ +import chisel3.experimental.{Analog, IO} + +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import freechips.rocketchip.diplomacy.{InModuleBody, BundleBridgeSource} +import freechips.rocketchip.config.{Parameters} + +import chipyard.{BuildSystem} + +import sifive.blocks.devices.uart._ + +trait HasPlatformIO { + val io_uart_bb: BundleBridgeSource[UARTPortIO] +} + +class VCU118Platform(override implicit val p: Parameters) extends LazyModule + with HasPlatformIO { + + val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") + + // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design + // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey)(0)))) + + override lazy val module = new VCU118PlatformModule(this) +} + +class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleImp(_outer) { + + _outer.lazySystem.module match { case sys: HasPeripheryUARTModuleImp => + // create UART pins in Platform + //val io_uart_pins_temp = p(PeripheryUARTKey).zipWithIndex map { case (c, i) => IO(new UARTPortIO(c)).suggestName(s"uart_$i") } + + //(io_uart_pins_temp zip sys.uart) map { case (p, r) => p <> r } + _outer.io_uart_bb.bundle <> sys.uart(0) + } + +} From 69bf39bf13053f566a32a5c6d2e05403b95bfd60 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Sat, 12 Sep 2020 18:18:13 -0700 Subject: [PATCH 14/28] Added more overlays | Closer to bringup platform --- fpga/src/main/scala/vcu118/Configs.scala | 11 +- .../main/scala/vcu118/CustomOverlays.scala | 65 ++++ fpga/src/main/scala/vcu118/FMCUtil.scala | 334 ++++++++++++++++++ fpga/src/main/scala/vcu118/Platform.scala | 45 ++- fpga/src/main/scala/vcu118/TestHarness.scala | 54 ++- 5 files changed, 488 insertions(+), 21 deletions(-) create mode 100644 fpga/src/main/scala/vcu118/CustomOverlays.scala create mode 100644 fpga/src/main/scala/vcu118/FMCUtil.scala diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index ba88377f..42663f0b 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -17,6 +17,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ import sifive.fpgashells.shell.{DesignKey} +import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD} import chipyard.{BuildTop} @@ -24,14 +25,20 @@ class WithChipyardBuildTop extends Config((site, here, up) => { case DesignKey => {(p: Parameters) => new VCU118Platform()(p) } }) -class WithBringupUARTs extends Config((site, here, up) => { +class WithBringupPeripherals extends Config((site, here, up) => { case PeripheryUARTKey => List( UARTParams(address = BigInt(0x64000000L)), UARTParams(address = BigInt(0x64003000L))) + case PeripherySPIKey => List( + SPIParams(rAddress = BigInt(0x64001000L)), + SPIParams(rAddress = BigInt(0x64004000L))) + case PeripheryI2CKey => List( + I2CParams(address = BigInt(0x64005000L))) + case VCU118ShellPMOD => "SDIO" }) class FakeBringupConfig extends Config( - new WithBringupUARTs ++ + new WithBringupPeripherals ++ new WithChipyardBuildTop ++ new chipyard.config.WithBootROM ++ new chipyard.config.WithL2TLBs(1024) ++ diff --git a/fpga/src/main/scala/vcu118/CustomOverlays.scala b/fpga/src/main/scala/vcu118/CustomOverlays.scala new file mode 100644 index 00000000..3d51c3e7 --- /dev/null +++ b/fpga/src/main/scala/vcu118/CustomOverlays.scala @@ -0,0 +1,65 @@ +package chipyard.fpga.vcu118.bringup + +import chisel3._ + +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: VCU118Shell, 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: VCU118Shell, val shellInput: I2CShellInput)(implicit val valName: ValName) + extends I2CShellPlacer[VCU118Shell] +{ + def place(designInput: I2CDesignInput) = new BringupI2CVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +/* Connect the UART to certain FMC pins */ +class BringupUARTVCU118PlacedOverlay(val shell: VCU118Shell, 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: VCU118Shell, val shellInput: UARTShellInput)(implicit val valName: ValName) + extends UARTShellPlacer[VCU118Shell] { + def place(designInput: UARTDesignInput) = new BringupUARTVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +/* Connect SPI to ADI device */ diff --git a/fpga/src/main/scala/vcu118/FMCUtil.scala b/fpga/src/main/scala/vcu118/FMCUtil.scala new file mode 100644 index 00000000..00982585 --- /dev/null +++ b/fpga/src/main/scala/vcu118/FMCUtil.scala @@ -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) +} diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala index 3a4cac8a..47e64de0 100644 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -10,31 +10,46 @@ import freechips.rocketchip.config.{Parameters} import chipyard.{BuildSystem} import sifive.blocks.devices.uart._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.i2c._ -trait HasPlatformIO { - val io_uart_bb: BundleBridgeSource[UARTPortIO] +trait HasVCU118PlatformIO { + val io_uart: Seq[UARTPortIO] + val io_spi: Seq[SPIPortIO] + val io_i2c: Seq[I2CPort] } -class VCU118Platform(override implicit val p: Parameters) extends LazyModule - with HasPlatformIO { +class VCU118Platform(override implicit val p: Parameters) extends LazyModule { val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") - // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design - // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. - val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey)(0)))) - override lazy val module = new VCU118PlatformModule(this) } -class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleImp(_outer) { +class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleImp(_outer) + with HasVCU118PlatformIO { - _outer.lazySystem.module match { case sys: HasPeripheryUARTModuleImp => - // create UART pins in Platform - //val io_uart_pins_temp = p(PeripheryUARTKey).zipWithIndex map { case (c, i) => IO(new UARTPortIO(c)).suggestName(s"uart_$i") } - - //(io_uart_pins_temp zip sys.uart) map { case (p, r) => p <> r } - _outer.io_uart_bb.bundle <> sys.uart(0) + val io_uart = _outer.lazySystem.module match { case sys: HasPeripheryUARTModuleImp => + val io_uart_pins_temp = p(PeripheryUARTKey).zipWithIndex.map { case (p, i) => IO(new UARTPortIO(p)).suggestName(s"uart_$i") } + (io_uart_pins_temp zip sys.uart).map { case (io, sysio) => + io <> sysio + } + io_uart_pins_temp } + val io_spi = _outer.lazySystem.module match { case sys: HasPeripherySPIModuleImp => + val io_spi_pins_temp = p(PeripherySPIKey).zipWithIndex.map { case (p, i) => IO(new SPIPortIO(p)).suggestName(s"spi_$i") } + (io_spi_pins_temp zip sys.spi).map { case (io, sysio) => + io <> sysio + } + io_spi_pins_temp + } + + val io_i2c = _outer.lazySystem.module match { case sys: HasPeripheryI2CModuleImp => + val io_i2c_pins_temp = p(PeripheryI2CKey).zipWithIndex.map { case (p, i) => IO(new I2CPort).suggestName(s"i2c_$i") } + (io_i2c_pins_temp zip sys.i2c).map { case (io, sysio) => + io <> sysio + } + io_i2c_pins_temp + } } diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 0bce7c97..31f3c0ff 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -13,14 +13,60 @@ import sifive.fpgashells.shell._ import sifive.fpgashells.clocks._ import sifive.blocks.devices.uart._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.i2c._ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell { - require(p(PeripheryUARTKey).size >= 1) - designParameters(UARTOverlayKey).foreach { uok => - topDesign match { case td: HasPlatformIO => - io_uart_bb)) + /*** UART ***/ + require(p(PeripheryUARTKey).size == 2) + + // 1st UART goes to the VCU118 dedicated UART + + // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design + // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey).head))) + designParameters(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + io_uart_bb.bundle <> dutMod.io_uart.head + } + } + + // 2nd UART goes to the FMC UART + + val uart_fmc = Overlay(UARTOverlayKey, new chipyard.fpga.vcu118.bringup.BringupUARTVCU118ShellPlacer(this, UARTShellInput())) + + val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey).last))) + designParameters(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + io_uart_bb_2.bundle <> dutMod.io_uart.last + } + } + + /*** SPI ***/ + require(p(PeripherySPIKey).size >= 1) + + val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).head))) + designParameters(SPIOverlayKey).head.place(SPIDesignInput(p(PeripherySPIKey).head, io_spi_bb)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + io_spi_bb.bundle <> dutMod.io_spi.head + } + } + + /*** I2C ***/ + require(p(PeripheryI2CKey).size >= 1) + + val i2c = Overlay(I2COverlayKey, new chipyard.fpga.vcu118.bringup.BringupI2CVCU118ShellPlacer(this, I2CShellInput())) + + val io_i2c_bb = BundleBridgeSource(() => (new I2CPort)) + designParameters(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + io_i2c_bb.bundle <> dutMod.io_i2c.head } } } From 72c0f4b3d3f2236c2477b0ab405f5fd26c58b520 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Sun, 13 Sep 2020 16:37:20 -0700 Subject: [PATCH 15/28] Add GPIO Overlay --- fpga/src/main/scala/vcu118/BringupGPIOs.scala | 28 ++++++ fpga/src/main/scala/vcu118/Configs.scala | 19 +++- .../main/scala/vcu118/CustomOverlays.scala | 86 +++++++++++++++++++ fpga/src/main/scala/vcu118/Platform.scala | 10 +++ fpga/src/main/scala/vcu118/TestHarness.scala | 57 ++++++++++-- 5 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 fpga/src/main/scala/vcu118/BringupGPIOs.scala diff --git a/fpga/src/main/scala/vcu118/BringupGPIOs.scala b/fpga/src/main/scala/vcu118/BringupGPIOs.scala new file mode 100644 index 00000000..1e11dfa2 --- /dev/null +++ b/fpga/src/main/scala/vcu118/BringupGPIOs.scala @@ -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 +} diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index 42663f0b..7cc106d5 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. package chipyard.fpga.vcu118 +import math.min + import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.debug._ @@ -9,7 +11,6 @@ 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._ @@ -20,6 +21,7 @@ import sifive.fpgashells.shell.{DesignKey} import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD} import chipyard.{BuildTop} +import chipyard.fpga.vcu118.bringup.{BringupGPIOs} class WithChipyardBuildTop extends Config((site, here, up) => { case DesignKey => {(p: Parameters) => new VCU118Platform()(p) } @@ -32,9 +34,22 @@ class WithBringupPeripherals extends Config((site, here, up) => { case PeripherySPIKey => List( SPIParams(rAddress = BigInt(0x64001000L)), SPIParams(rAddress = BigInt(0x64004000L))) + case VCU118ShellPMOD => "SDIO" case PeripheryI2CKey => List( I2CParams(address = BigInt(0x64005000L))) - case VCU118ShellPMOD => "SDIO" + 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 FakeBringupConfig extends Config( diff --git a/fpga/src/main/scala/vcu118/CustomOverlays.scala b/fpga/src/main/scala/vcu118/CustomOverlays.scala index 3d51c3e7..ccb61f0e 100644 --- a/fpga/src/main/scala/vcu118/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/CustomOverlays.scala @@ -1,13 +1,17 @@ package chipyard.fpga.vcu118.bringup import chisel3._ +import chisel3.experimental.{attach} import freechips.rocketchip.diplomacy._ +import chipsalliance.rocketchip.config.{Parameters, Field} import sifive.fpgashells.shell._ import sifive.fpgashells.ip.xilinx._ import sifive.fpgashells.shell.xilinx._ +import sifive.blocks.devices.gpio._ + import chipyard.fpga.vcu118.{FMCPMap} /* Connect the I2C to certain FMC pins */ @@ -63,3 +67,85 @@ class BringupUARTVCU118ShellPlacer(shell: VCU118Shell, val shellInput: UARTShell } /* Connect SPI to ADI device */ +class BringupSPIVCU118PlacedOverlay(val shell: VCU118Shell, 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: VCU118Shell, val shellInput: SPIShellInput)(implicit val valName: ValName) + extends SPIShellPlacer[VCU118Shell] { + 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: VCU118Shell, 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) + // TODO: no drive strength found + //if (iostd == "LVCMOS12") { shell.xdc.addDriveStrength(io, "8") } + } } + } } +} + +class BringupGPIOVCU118ShellPlacer(shell: VCU118Shell, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName) + extends GPIOShellPlacer[VCU118Shell] { + def place(designInput: GPIODesignInput) = new BringupGPIOVCU118PlacedOverlay(shell, valName.name, designInput, shellInput, gpioNames) +} + + diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala index 47e64de0..8f9a1ae8 100644 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -12,11 +12,13 @@ import chipyard.{BuildSystem} import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ +import sifive.blocks.devices.gpio._ trait HasVCU118PlatformIO { val io_uart: Seq[UARTPortIO] val io_spi: Seq[SPIPortIO] val io_i2c: Seq[I2CPort] + val io_gpio: Seq[GPIOPortIO] } class VCU118Platform(override implicit val p: Parameters) extends LazyModule { @@ -52,4 +54,12 @@ class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleIm } io_i2c_pins_temp } + + val io_gpio = _outer.lazySystem.module match { case sys: HasPeripheryGPIOModuleImp => + val io_gpio_pins_temp = p(PeripheryGPIOKey).zipWithIndex.map { case (p, i) => IO(new GPIOPortIO(p)).suggestName(s"gpio_$i") } + (io_gpio_pins_temp zip sys.gpio).map { case (io, sysio) => + io <> sysio + } + io_gpio_pins_temp + } } diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 31f3c0ff..9a58960f 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -3,9 +3,8 @@ package chipyard.fpga.vcu118 import chisel3._ import chisel3.experimental.{Analog, IO} -import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp} +import freechips.rocketchip.diplomacy._ import freechips.rocketchip.config.{Parameters} -import freechips.rocketchip.diplomacy.{InModuleBody, BundleBridgeSource} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx._ @@ -15,6 +14,9 @@ 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.bringup._ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell { @@ -47,18 +49,44 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } /*** SPI ***/ - require(p(PeripherySPIKey).size >= 1) + require(p(PeripherySPIKey).size == 2) + + // 1st SPI goes to the VCU118 SDIO port val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).head))) - designParameters(SPIOverlayKey).head.place(SPIDesignInput(p(PeripherySPIKey).head, io_spi_bb)) + val sdio_placed = designParameters(SPIOverlayKey).head.place(SPIDesignInput(p(PeripherySPIKey).head, io_spi_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_spi_bb.bundle <> dutMod.io_spi.head } } + // TODO: No access to the TLSPI node... + //val mmcDev = new MMCDevice(sdio_placed.device, 1) + //ResourceBinding { + // Resource(mmcDev, "reg").bind(ResourceAddress(0)) + //} + + // 2nd SPI goes to the ADI port + + val adi = Overlay(SPIOverlayKey, new chipyard.fpga.vcu118.bringup.BringupSPIVCU118ShellPlacer(this, SPIShellInput())) + + val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).last))) + val adi_placed = designParameters(SPIOverlayKey).last.place(SPIDesignInput(p(PeripherySPIKey).last, io_spi_bb_2)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + io_spi_bb_2.bundle <> dutMod.io_spi.last + } + } + + // TODO: No access to the TLSPI node... + //val adiDev = new chipyard.fpga.vcu118.bringup.ADISPIDevice(adi_placed.device, 1) + //ResourceBinding { + // Resource(adiDev, "reg").bind(ResourceAddress(0)) + //} + /*** I2C ***/ - require(p(PeripheryI2CKey).size >= 1) + require(p(PeripheryI2CKey).size == 1) val i2c = Overlay(I2COverlayKey, new chipyard.fpga.vcu118.bringup.BringupI2CVCU118ShellPlacer(this, I2CShellInput())) @@ -69,5 +97,24 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S io_i2c_bb.bundle <> dutMod.io_i2c.head } } + + /*** GPIO ***/ + val gpio = Seq.tabulate(p(PeripheryGPIOKey).size)(i => { + val maxGPIOSupport = 32 + val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1)) + Overlay(GPIOOverlayKey, new chipyard.fpga.vcu118.bringup.BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) + }) + + val io_gpio_bb = p(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) } + (designParameters(GPIOOverlayKey) zip p(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) => + placer.place(GPIODesignInput(params, io_gpio_bb(i))) + } + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + (io_gpio_bb zip dutMod.io_gpio).map { case (bb_io, dut_io) => + bb_io.bundle <> dut_io + } + } + } } From f1b40d51afdba1e1d7c9bd95742aec2e85adef3d Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Tue, 15 Sep 2020 12:58:58 -0700 Subject: [PATCH 16/28] Connected clocks | Exposed Master TL port --- fpga/src/main/scala/vcu118/Configs.scala | 29 ++++-- .../main/scala/vcu118/CustomOverlays.scala | 25 ++--- fpga/src/main/scala/vcu118/Platform.scala | 16 +++- fpga/src/main/scala/vcu118/TestHarness.scala | 94 ++++++++++++++----- .../chipyard/src/main/scala/DigitalTop.scala | 40 ++++++++ .../chipyard/src/main/scala/System.scala | 1 - 6 files changed, 159 insertions(+), 46 deletions(-) diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index 7cc106d5..ab087afa 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -7,7 +7,7 @@ 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.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet} import freechips.rocketchip.system._ import freechips.rocketchip.tile._ @@ -52,20 +52,35 @@ class WithBringupPeripherals extends Config((site, here, up) => { } }) +class SmallModifications extends Config((site, here, up) => { + 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(DUTFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt), + errorDevice = None) + case DTSTimebase => BigInt(1000000) + case JtagDTMKey => new JtagDTMConfig( + idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). + idcodePartNum = 0x000, // Decided to simplify. + idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. + debugIdleCycles = 5) // Reasonable guess for synchronization +}) + + class FakeBringupConfig extends Config( new WithBringupPeripherals ++ new WithChipyardBuildTop ++ 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.WithNMemoryChannels(1) ++ 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.WithCoherentBusTopology ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) diff --git a/fpga/src/main/scala/vcu118/CustomOverlays.scala b/fpga/src/main/scala/vcu118/CustomOverlays.scala index ccb61f0e..2c438a34 100644 --- a/fpga/src/main/scala/vcu118/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/CustomOverlays.scala @@ -12,10 +12,11 @@ import sifive.fpgashells.shell.xilinx._ import sifive.blocks.devices.gpio._ + import chipyard.fpga.vcu118.{FMCPMap} /* Connect the I2C to certain FMC pins */ -class BringupI2CVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput) +class BringupI2CVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput) extends I2CXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -32,14 +33,14 @@ class BringupI2CVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val de } } } -class BringupI2CVCU118ShellPlacer(val shell: VCU118Shell, val shellInput: I2CShellInput)(implicit val valName: ValName) - extends I2CShellPlacer[VCU118Shell] +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: VCU118Shell, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput) +class BringupUARTVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput) extends UARTXilinxPlacedOverlay(name, designInput, shellInput, true) { shell { InModuleBody { @@ -61,13 +62,13 @@ class BringupUARTVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val d } } } -class BringupUARTVCU118ShellPlacer(shell: VCU118Shell, val shellInput: UARTShellInput)(implicit val valName: ValName) - extends UARTShellPlacer[VCU118Shell] { +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: VCU118Shell, name: String, val designInput: SPIDesignInput, val shellInput: SPIShellInput) +class BringupSPIVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: SPIDesignInput, val shellInput: SPIShellInput) extends SDIOXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -89,8 +90,8 @@ class BringupSPIVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val de } } } -class BringupSPIVCU118ShellPlacer(shell: VCU118Shell, val shellInput: SPIShellInput)(implicit val valName: ValName) - extends SPIShellPlacer[VCU118Shell] { +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) } @@ -123,7 +124,7 @@ abstract class GPIOXilinxPlacedOverlay(name: String, di: GPIODesignInput, si: GP } } } -class BringupGPIOVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String]) +class BringupGPIOVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String]) extends GPIOXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -143,8 +144,8 @@ class BringupGPIOVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val d } } } -class BringupGPIOVCU118ShellPlacer(shell: VCU118Shell, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName) - extends GPIOShellPlacer[VCU118Shell] { +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) } diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala index 8f9a1ae8..bdacdf42 100644 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -1,11 +1,12 @@ package chipyard.fpga.vcu118 import chisel3._ -import chisel3.experimental.{Analog, IO} +import chisel3.experimental.{Analog, IO, DataMirror} -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} -import freechips.rocketchip.diplomacy.{InModuleBody, BundleBridgeSource} +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyScope, InModuleBody, BundleBridgeSource, ValName} import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.util.{HeterogeneousBag} +import freechips.rocketchip.tilelink.{TLBundle} import chipyard.{BuildSystem} @@ -19,9 +20,10 @@ trait HasVCU118PlatformIO { val io_spi: Seq[SPIPortIO] val io_i2c: Seq[I2CPort] val io_gpio: Seq[GPIOPortIO] + val io_tl_mem: HeterogeneousBag[TLBundle] } -class VCU118Platform(override implicit val p: Parameters) extends LazyModule { +class VCU118Platform(override implicit val p: Parameters) extends LazyModule with LazyScope { val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") @@ -62,4 +64,10 @@ class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleIm } io_gpio_pins_temp } + + val io_tl_mem = _outer.lazySystem match { case sys: chipyard.CanHaveMasterTLMemPort => + val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](sys.mem_tl)).suggestName("tl_slave") + io_tl_mem_pins_temp <> sys.mem_tl + io_tl_mem_pins_temp + } } diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 9a58960f..d4e299a5 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -4,7 +4,8 @@ import chisel3._ import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx._ @@ -16,20 +17,55 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.fpga.vcu118.bringup._ +import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} -class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell { +case object DUTFrequencyKey extends Field[Double](100.0) +class VCU118FPGATestHarness(override implicit val p: Parameters) extends ChipyardVCU118Shell { + + def dp = designParameters + + /*** 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(DUTFrequencyKey)) + val dutWrangler = LazyModule(new ResetWrangler) + val dutGroup = ClockGroup() + dutClock := dutWrangler.node := dutGroup := harnessSysPLL + + InModuleBody { + topDesign.module match { case td: LazyModuleImp => { + td.clock := dutClock.in.head._1.clock + td.reset := dutClock.in.head._1.reset + } + } + } + + // connect ref clock to dummy sink node + ref_clock.get() match { + case Some(x : RefClockVCU118PlacedOverlay) => { + val sink = ClockSinkNode(Seq(ClockSinkParameters())) + sink := x.node + } + } /*** UART ***/ - require(p(PeripheryUARTKey).size == 2) + require(dp(PeripheryUARTKey).size == 2) // 1st UART goes to the VCU118 dedicated UART // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. - val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey).head))) - designParameters(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) + dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_uart_bb.bundle <> dutMod.io_uart.head @@ -38,10 +74,10 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S // 2nd UART goes to the FMC UART - val uart_fmc = Overlay(UARTOverlayKey, new chipyard.fpga.vcu118.bringup.BringupUARTVCU118ShellPlacer(this, UARTShellInput())) + val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) - val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey).last))) - designParameters(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) + dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_uart_bb_2.bundle <> dutMod.io_uart.last @@ -49,12 +85,12 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } /*** SPI ***/ - require(p(PeripherySPIKey).size == 2) + require(dp(PeripherySPIKey).size == 2) // 1st SPI goes to the VCU118 SDIO port - val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).head))) - val sdio_placed = designParameters(SPIOverlayKey).head.place(SPIDesignInput(p(PeripherySPIKey).head, io_spi_bb)) + val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) + val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_spi_bb.bundle <> dutMod.io_spi.head @@ -69,10 +105,10 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S // 2nd SPI goes to the ADI port - val adi = Overlay(SPIOverlayKey, new chipyard.fpga.vcu118.bringup.BringupSPIVCU118ShellPlacer(this, SPIShellInput())) + val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) - val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).last))) - val adi_placed = designParameters(SPIOverlayKey).last.place(SPIDesignInput(p(PeripherySPIKey).last, io_spi_bb_2)) + val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) + val adi_placed = dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_spi_bb_2)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_spi_bb_2.bundle <> dutMod.io_spi.last @@ -86,12 +122,12 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S //} /*** I2C ***/ - require(p(PeripheryI2CKey).size == 1) + require(dp(PeripheryI2CKey).size == 1) - val i2c = Overlay(I2COverlayKey, new chipyard.fpga.vcu118.bringup.BringupI2CVCU118ShellPlacer(this, I2CShellInput())) + val i2c = Overlay(I2COverlayKey, new BringupI2CVCU118ShellPlacer(this, I2CShellInput())) val io_i2c_bb = BundleBridgeSource(() => (new I2CPort)) - designParameters(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) + dp(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_i2c_bb.bundle <> dutMod.io_i2c.head @@ -99,14 +135,14 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } /*** GPIO ***/ - val gpio = Seq.tabulate(p(PeripheryGPIOKey).size)(i => { + val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { val maxGPIOSupport = 32 val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1)) - Overlay(GPIOOverlayKey, new chipyard.fpga.vcu118.bringup.BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) + Overlay(GPIOOverlayKey, new BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) }) - val io_gpio_bb = p(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) } - (designParameters(GPIOOverlayKey) zip p(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) => + 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))) } InModuleBody { @@ -116,5 +152,19 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } } } + + /*** Experimental DDR ***/ + + //val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL)) + + //topDesign match { case lazyDut: VCU118Platform => + // lazyDut.lazySystem match { case lazyDutWBus: BaseSubsystem => + // lazyDutWBus { + // InModuleBody { + // ddrPlaced.overlayOutput.ddr := lazyDutWBus.mbus.toDRAMController(Some("xilinxvcu118mig"))() + // } + // } + // } + //} } diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index 9e40cfab..dedcfbf8 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -29,6 +29,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem 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 nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA + with CanHaveMasterTLMemPort { override lazy val module = new DigitalTopModule(this) } @@ -47,3 +48,42 @@ class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) with chipyard.example.CanHavePeripheryGCDModuleImp with freechips.rocketchip.util.DontTouch // 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() } +} diff --git a/generators/chipyard/src/main/scala/System.scala b/generators/chipyard/src/main/scala/System.scala index bd20ddc7..f8906e04 100644 --- a/generators/chipyard/src/main/scala/System.scala +++ b/generators/chipyard/src/main/scala/System.scala @@ -23,7 +23,6 @@ import freechips.rocketchip.util.{DontTouch} */ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem with HasAsyncExtInterrupts - with CanHaveMasterAXI4MemPort with CanHaveMasterAXI4MMIOPort with CanHaveSlaveAXI4Port { From 8257775e96650c83b232aa921a8e53038be153fb Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Mon, 12 Oct 2020 21:50:50 -0700 Subject: [PATCH 17/28] Connect DDR from harness --- fpga/src/main/scala/vcu118/TestHarness.scala | 29 +++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index d4e299a5..4275f68d 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -6,6 +6,7 @@ import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy._ import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} +import freechips.rocketchip.tilelink._ import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx._ @@ -155,16 +156,24 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends Chipyar /*** Experimental DDR ***/ - //val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL)) + val ddrWrangler = LazyModule(new ResetWrangler) + val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, ddrWrangler.node, harnessSysPLL)) - //topDesign match { case lazyDut: VCU118Platform => - // lazyDut.lazySystem match { case lazyDutWBus: BaseSubsystem => - // lazyDutWBus { - // InModuleBody { - // ddrPlaced.overlayOutput.ddr := lazyDutWBus.mbus.toDRAMController(Some("xilinxvcu118mig"))() - // } - // } - // } - //} + // connect 1 mem. channel to the FPGA DDR + val inParams = topDesign match { case td: VCU118Platform => + td.lazySystem match { case lsys: chipyard.CanHaveMasterTLMemPort => + lsys.memTLNode.edges.in(0) + } + } + val ddrClient = TLClientNode(Seq(inParams.master)) + InModuleBody { + topDesign.module match { case dutMod: HasVCU118PlatformIO => + val bundles = ddrClient.out.map(_._1) + val ddrClientBundle = Wire(new freechips.rocketchip.util.HeterogeneousBag(bundles.map(_.cloneType))) + bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } + ddrClientBundle <> dutMod.io_tl_mem + } + } + ddrPlaced.overlayOutput.ddr := ddrClient } From 9c298eedfe539e05aa409d4b60595f5a0ab2ada1 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 13 Oct 2020 15:10:41 -0700 Subject: [PATCH 18/28] Support evaluation of HarnessBinders in LazyModule context --- .../src/main/scala/HarnessBinders.scala | 75 ++++++++++--------- .../chipyard/src/main/scala/IOBinders.scala | 46 +++++------- .../chipyard/src/main/scala/TestHarness.scala | 2 +- .../src/main/scala/BridgeBinders.scala | 16 ++-- 4 files changed, 66 insertions(+), 73 deletions(-) diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index e5cfacfb..6f7d2dd8 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -1,7 +1,7 @@ package chipyard.harness import chisel3._ -import chisel3.experimental.{Analog} +import chisel3.experimental.{Analog, BaseModule} import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} @@ -33,40 +33,41 @@ case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalRefer object ApplyHarnessBinders { - def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = { + def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = { val pm = portMap.withDefaultValue(Nil) - map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } + p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } } } -class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { +class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) extends Config((site, here, up) => { case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { - val pts = ports.collect({case p: S => p}) + val pts = ports.collect({case p: U => p}) require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - t match { - case system: T => fn(system, th, pts) + val upfn = up(HarnessBinders, site)(tag.runtimeClass.toString) + th match { + case th: S => + t match { + case system: T => composer(upfn)(system, th, pts) + case _ => Nil + } case _ => Nil } }) ) }) -class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { - case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> - ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { - val pts = ports.collect({case p: S => p}) - require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - t match { - case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts) - case _ => Nil - } - }) - ) -}) +class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) + (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn) + +class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) + (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p)) + class WithGPIOTiedOff extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { + (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => { ports.foreach { _ <> AnalogConst(0) } Nil } @@ -74,7 +75,7 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({ // DOC include start: WithUARTAdapter class WithUARTAdapter extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { UARTAdapter.connect(ports)(system.p) Nil } @@ -82,14 +83,14 @@ class WithUARTAdapter extends OverrideHarnessBinder({ // DOC include end: WithUARTAdapter class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ - (system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { + (system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p) Nil } }) class WithSimBlockDevice extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) } Nil @@ -97,7 +98,7 @@ class WithSimBlockDevice extends OverrideHarnessBinder({ }) class WithBlockDeviceModel extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } } Nil @@ -105,7 +106,7 @@ class WithBlockDeviceModel extends OverrideHarnessBinder({ }) class WithLoopbackNIC extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => withClockAndReset(n.clock, th.harnessReset) { @@ -117,7 +118,7 @@ class WithLoopbackNIC extends OverrideHarnessBinder({ }) class WithSimNetwork extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) } Nil @@ -125,7 +126,7 @@ class WithSimNetwork extends OverrideHarnessBinder({ }) class WithSimAXIMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p)) @@ -139,7 +140,7 @@ class WithSimAXIMem extends OverrideHarnessBinder({ }) class WithBlackBoxSimMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val memSize = p(ExtMem).get.master.size @@ -154,7 +155,7 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({ }) class WithSimAXIMMIO extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MMIOPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) => val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p)) @@ -168,21 +169,21 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({ }) class WithTieOffInterrupts extends OverrideHarnessBinder({ - (system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { + (system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => { ports.foreach { _ := 0.U } Nil } }) class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ - (system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { ports.foreach({ p => p := DontCare; p.bits.tieoff() }) Nil } }) class WithSimDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case d: ClockedDMIIO => val dtm_success = WireInit(false.B) @@ -198,7 +199,7 @@ class WithSimDebug extends OverrideHarnessBinder({ }) class WithTiedOffDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case j: JTAGIO => j.TCK := true.B.asClock @@ -224,7 +225,7 @@ class WithTiedOffDebug extends OverrideHarnessBinder({ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -234,7 +235,7 @@ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ }) class WithSimSerial extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -245,14 +246,14 @@ class WithSimSerial extends OverrideHarnessBinder({ }) class WithTraceGenSuccess extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { + (system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => { ports.map { p => when (p) { th.success := true.B } } Nil } }) class WithSimDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } Nil } diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 4a31e2c0..5259cbb1 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -72,41 +72,33 @@ object GetSystemParameters { } } -class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f) +class IOBinder[T, S <: Data](composer: (Any => (Seq[Data], Seq[IOCell])) => T => (Seq[Data], Seq[IOCell]))(implicit tag: ClassTag[T]) extends Config((site, here, up) => { + case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> + ((t: Any) => { + val upfn = up(IOBinders, site)(tag.runtimeClass.toString) + t match { + case system: T => composer(upfn)(system) + case _ => (Nil, Nil) + } + }) + ) +}) + // This macro overrides previous matches on some Top mixin. This is useful for // binders which drive IO, since those typically cannot be composed -class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { - case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { - t match { - case system: T => - val (ports, cells) = fn(system) - (ports, cells) - case _ => (Nil, Nil) - } - }) - ) -}) +class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => fn) + // This macro composes with previous matches on some Top mixin. This is useful for // annotation-like binders, since those can typically be composed -class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { - case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { - t match { - case system: T => - val r = up(IOBinders, site)(tag.runtimeClass.toString)(system) - val h = fn(system) - val ports = r._1 ++ h._1 - val cells = r._2 ++ h._2 - (ports, cells) - case _ => (Nil, Nil) - } - }) - ) +class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => t => { + val r = upfn(t) + val h = fn(t) + (r._1 ++ h._1, r._2 ++ h._2) }) + object BoreHelper { def apply(name: String, source: Clock): Clock = { val clock_io = IO(Output(Clock())).suggestName(name) diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index 2faff565..64b889e3 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -44,7 +44,7 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign lazyDut match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) - ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) + ApplyHarnessBinders(this, d.lazySystem, d.portMap.toMap) } } diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 444c7b33..2fa49fc3 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => { }) class WithSerialBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => { ports.map { port => implicit val p = GetSystemParameters(system) val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -77,7 +77,7 @@ class WithSerialBridge extends OverrideHarnessBinder({ }) class WithNICBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => { val p: Parameters = GetSystemParameters(system) ports.map { n => NICBridge(n.clock, n.bits)(p) } Nil @@ -85,12 +85,12 @@ class WithNICBridge extends OverrideHarnessBinder({ }) class WithUARTBridge extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => + (system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) => ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil }) class WithBlockDeviceBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) } Nil @@ -98,7 +98,7 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({ }) class WithFASEDBridge extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedIO[AXI4Bundle]]) => { implicit val p: Parameters = GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) => val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth, @@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({ }) class WithTracerVBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) } Nil } }) class WithDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => + (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil }) class WithTraceGenBridge extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => + (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) => ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil }) From 5bbd8654470a004c1f06cb7abd5f9060b64e24b3 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Tue, 13 Oct 2020 16:18:00 -0700 Subject: [PATCH 19/28] Add MMC Device section to the DTS --- .gitmodules | 2 +- fpga/src/main/scala/vcu118/Platform.scala | 12 ++++++++++-- generators/sifive-blocks | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index ea3cb2c7..f406a5c2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,7 +21,7 @@ url = https://github.com/riscv-boom/riscv-boom.git [submodule "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"] path = generators/hwacha url = https://github.com/ucb-bar/hwacha.git diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala index bdacdf42..342f7328 100644 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -3,7 +3,7 @@ package chipyard.fpga.vcu118 import chisel3._ import chisel3.experimental.{Analog, IO, DataMirror} -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyScope, InModuleBody, BundleBridgeSource, ValName} +import freechips.rocketchip.diplomacy._ import freechips.rocketchip.config.{Parameters} import freechips.rocketchip.util.{HeterogeneousBag} import freechips.rocketchip.tilelink.{TLBundle} @@ -23,10 +23,18 @@ trait HasVCU118PlatformIO { val io_tl_mem: HeterogeneousBag[TLBundle] } -class VCU118Platform(override implicit val p: Parameters) extends LazyModule with LazyScope { +class VCU118Platform(override implicit val p: Parameters) extends LazyModule with LazyScope with BindingScope { val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") + // add MMC to the DTS + lazySystem match { case lsys: HasPeripherySPI => + val mmcDev = new MMCDevice(lsys.tlspi.head.device, 1) + ResourceBinding { + Resource(mmcDev, "reg").bind(ResourceAddress(0)) + } + } + override lazy val module = new VCU118PlatformModule(this) } diff --git a/generators/sifive-blocks b/generators/sifive-blocks index c240e629..413e0a88 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit c240e629e2fc111cbb12e4fe707be898b5204984 +Subproject commit 413e0a88a4e48b1966b9444d613a7f3a776e65aa From dda7622c29c1bd00abdb74bcd7251915886ed323 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 14 Oct 2020 14:49:22 -0700 Subject: [PATCH 20/28] temp commit --- fpga/src/main/scala/arty/TestHarness.scala | 68 +- fpga/src/main/scala/arty/e300/Configs.scala | 144 ++-- .../src/main/scala/arty/e300/DigitalTop.scala | 46 +- fpga/src/main/scala/arty/e300/IOBinders.scala | 730 +++++++++--------- fpga/src/main/scala/vcu118/Configs.scala | 28 +- fpga/src/main/scala/vcu118/Platform.scala | 81 -- fpga/src/main/scala/vcu118/TestHarness.scala | 130 +--- .../chipyard/src/main/scala/ChipTop.scala | 4 +- 8 files changed, 529 insertions(+), 702 deletions(-) delete mode 100644 fpga/src/main/scala/vcu118/Platform.scala diff --git a/fpga/src/main/scala/arty/TestHarness.scala b/fpga/src/main/scala/arty/TestHarness.scala index 919e5c99..6571f3d6 100644 --- a/fpga/src/main/scala/arty/TestHarness.scala +++ b/fpga/src/main/scala/arty/TestHarness.scala @@ -1,34 +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)) -} - +//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)) +//} +// diff --git a/fpga/src/main/scala/arty/e300/Configs.scala b/fpga/src/main/scala/arty/e300/Configs.scala index dd9213fc..9e04d8df 100644 --- a/fpga/src/main/scala/arty/e300/Configs.scala +++ b/fpga/src/main/scala/arty/e300/Configs.scala @@ -1,72 +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) +//// 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) diff --git a/fpga/src/main/scala/arty/e300/DigitalTop.scala b/fpga/src/main/scala/arty/e300/DigitalTop.scala index 1bda2680..45018c00 100644 --- a/fpga/src/main/scala/arty/e300/DigitalTop.scala +++ b/fpga/src/main/scala/arty/e300/DigitalTop.scala @@ -1,23 +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 +//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 diff --git a/fpga/src/main/scala/arty/e300/IOBinders.scala b/fpga/src/main/scala/arty/e300/IOBinders.scala index 8d866619..82da669c 100644 --- a/fpga/src/main/scala/arty/e300/IOBinders.scala +++ b/fpga/src/main/scala/arty/e300/IOBinders.scala @@ -1,365 +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))) - } -}) - +//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))) +// } +//}) +// diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index ab087afa..feaa0484 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -23,20 +23,18 @@ import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD} import chipyard.{BuildTop} import chipyard.fpga.vcu118.bringup.{BringupGPIOs} -class WithChipyardBuildTop extends Config((site, here, up) => { - case DesignKey => {(p: Parameters) => new VCU118Platform()(p) } -}) +import chipyard.harness._ class WithBringupPeripherals extends Config((site, here, up) => { case PeripheryUARTKey => List( UARTParams(address = BigInt(0x64000000L)), UARTParams(address = BigInt(0x64003000L))) - case PeripherySPIKey => List( - SPIParams(rAddress = BigInt(0x64001000L)), - SPIParams(rAddress = BigInt(0x64004000L))) - case VCU118ShellPMOD => "SDIO" - case PeripheryI2CKey => List( - I2CParams(address = BigInt(0x64005000L))) +// case PeripherySPIKey => List( +// SPIParams(rAddress = BigInt(0x64001000L)), +// SPIParams(rAddress = BigInt(0x64004000L))) +// case VCU118ShellPMOD => "SDIO" +// 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) @@ -72,8 +70,18 @@ class SmallModifications extends Config((site, here, up) => { class FakeBringupConfig extends Config( + new WithBringupUART ++ + //new WithBringupSPI ++ + //new WithBringupI2C ++ + new WithBringupGPIO ++ + new chipyard.iobinders.WithUARTIOCells ++ + //new WithSPICells ++ + //new WithI2CCells ++ + new chipyard.iobinders.WithGPIOCells ++ + //new WithBringupDDR ++ new WithBringupPeripherals ++ - new WithChipyardBuildTop ++ + new chipyard.config.WithNoSubsystemDrivenClocks ++ + new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ new chipyard.config.WithBootROM ++ new chipyard.config.WithL2TLBs(1024) ++ new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala deleted file mode 100644 index 342f7328..00000000 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ /dev/null @@ -1,81 +0,0 @@ -package chipyard.fpga.vcu118 - -import chisel3._ -import chisel3.experimental.{Analog, IO, DataMirror} - -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters} -import freechips.rocketchip.util.{HeterogeneousBag} -import freechips.rocketchip.tilelink.{TLBundle} - -import chipyard.{BuildSystem} - -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.spi._ -import sifive.blocks.devices.i2c._ -import sifive.blocks.devices.gpio._ - -trait HasVCU118PlatformIO { - val io_uart: Seq[UARTPortIO] - val io_spi: Seq[SPIPortIO] - val io_i2c: Seq[I2CPort] - val io_gpio: Seq[GPIOPortIO] - val io_tl_mem: HeterogeneousBag[TLBundle] -} - -class VCU118Platform(override implicit val p: Parameters) extends LazyModule with LazyScope with BindingScope { - - val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") - - // add MMC to the DTS - lazySystem match { case lsys: HasPeripherySPI => - val mmcDev = new MMCDevice(lsys.tlspi.head.device, 1) - ResourceBinding { - Resource(mmcDev, "reg").bind(ResourceAddress(0)) - } - } - - override lazy val module = new VCU118PlatformModule(this) -} - -class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleImp(_outer) - with HasVCU118PlatformIO { - - val io_uart = _outer.lazySystem.module match { case sys: HasPeripheryUARTModuleImp => - val io_uart_pins_temp = p(PeripheryUARTKey).zipWithIndex.map { case (p, i) => IO(new UARTPortIO(p)).suggestName(s"uart_$i") } - (io_uart_pins_temp zip sys.uart).map { case (io, sysio) => - io <> sysio - } - io_uart_pins_temp - } - - val io_spi = _outer.lazySystem.module match { case sys: HasPeripherySPIModuleImp => - val io_spi_pins_temp = p(PeripherySPIKey).zipWithIndex.map { case (p, i) => IO(new SPIPortIO(p)).suggestName(s"spi_$i") } - (io_spi_pins_temp zip sys.spi).map { case (io, sysio) => - io <> sysio - } - io_spi_pins_temp - } - - val io_i2c = _outer.lazySystem.module match { case sys: HasPeripheryI2CModuleImp => - val io_i2c_pins_temp = p(PeripheryI2CKey).zipWithIndex.map { case (p, i) => IO(new I2CPort).suggestName(s"i2c_$i") } - (io_i2c_pins_temp zip sys.i2c).map { case (io, sysio) => - io <> sysio - } - io_i2c_pins_temp - } - - val io_gpio = _outer.lazySystem.module match { case sys: HasPeripheryGPIOModuleImp => - val io_gpio_pins_temp = p(PeripheryGPIOKey).zipWithIndex.map { case (p, i) => IO(new GPIOPortIO(p)).suggestName(s"gpio_$i") } - (io_gpio_pins_temp zip sys.gpio).map { case (io, sysio) => - io <> sysio - } - io_gpio_pins_temp - } - - val io_tl_mem = _outer.lazySystem match { case sys: chipyard.CanHaveMasterTLMemPort => - val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](sys.mem_tl)).suggestName("tl_slave") - io_tl_mem_pins_temp <> sys.mem_tl - io_tl_mem_pins_temp - } -} diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 4275f68d..d371aced 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -19,10 +19,12 @@ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} +import chipyard.harness._ +import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions} case object DUTFrequencyKey extends Field[Double](100.0) -class VCU118FPGATestHarness(override implicit val p: Parameters) extends ChipyardVCU118Shell { +class VCU118FPGATestHarness(override implicit val p: Parameters) extends ChipyardVCU118Shell with HasHarnessSignalReferences { def dp = designParameters @@ -58,122 +60,20 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends Chipyar } } - /*** UART ***/ - require(dp(PeripheryUARTKey).size == 2) + lazy val harnessClock = InModuleBody { + dutClock.in.head._1.clock + }.getWrappedValue + lazy val harnessReset = InModuleBody { + WireInit(dutClock.in.head._1.reset) + }.getWrappedValue + lazy val dutReset = harnessReset + lazy val success = InModuleBody { false.B }.getWrappedValue - // 1st UART goes to the VCU118 dedicated UART - - // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design - // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. - val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) - dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - io_uart_bb.bundle <> dutMod.io_uart.head + topDesign match { case d: HasTestHarnessFunctions => + InModuleBody { + d.harnessFunctions.foreach(_(this)) } + ApplyHarnessBinders(this, d.lazySystem, d.portMap.toMap) } - - // 2nd UART goes to the FMC UART - - val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) - - val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) - dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - io_uart_bb_2.bundle <> dutMod.io_uart.last - } - } - - /*** SPI ***/ - require(dp(PeripherySPIKey).size == 2) - - // 1st SPI goes to the VCU118 SDIO port - - val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) - val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - io_spi_bb.bundle <> dutMod.io_spi.head - } - } - - // TODO: No access to the TLSPI node... - //val mmcDev = new MMCDevice(sdio_placed.device, 1) - //ResourceBinding { - // Resource(mmcDev, "reg").bind(ResourceAddress(0)) - //} - - // 2nd SPI goes to the ADI port - - val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) - - val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) - val adi_placed = dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_spi_bb_2)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - io_spi_bb_2.bundle <> dutMod.io_spi.last - } - } - - // TODO: No access to the TLSPI node... - //val adiDev = new chipyard.fpga.vcu118.bringup.ADISPIDevice(adi_placed.device, 1) - //ResourceBinding { - // Resource(adiDev, "reg").bind(ResourceAddress(0)) - //} - - /*** I2C ***/ - require(dp(PeripheryI2CKey).size == 1) - - val i2c = Overlay(I2COverlayKey, new BringupI2CVCU118ShellPlacer(this, I2CShellInput())) - - val io_i2c_bb = BundleBridgeSource(() => (new I2CPort)) - dp(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - io_i2c_bb.bundle <> dutMod.io_i2c.head - } - } - - /*** GPIO ***/ - val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { - val maxGPIOSupport = 32 - 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))) - } - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - (io_gpio_bb zip dutMod.io_gpio).map { case (bb_io, dut_io) => - bb_io.bundle <> dut_io - } - } - } - - /*** Experimental DDR ***/ - - val ddrWrangler = LazyModule(new ResetWrangler) - val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, ddrWrangler.node, harnessSysPLL)) - - // connect 1 mem. channel to the FPGA DDR - val inParams = topDesign match { case td: VCU118Platform => - td.lazySystem match { case lsys: chipyard.CanHaveMasterTLMemPort => - lsys.memTLNode.edges.in(0) - } - } - val ddrClient = TLClientNode(Seq(inParams.master)) - InModuleBody { - topDesign.module match { case dutMod: HasVCU118PlatformIO => - val bundles = ddrClient.out.map(_._1) - val ddrClientBundle = Wire(new freechips.rocketchip.util.HeterogeneousBag(bundles.map(_.cloneType))) - bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> dutMod.io_tl_mem - } - } - ddrPlaced.overlayOutput.ddr := ddrClient } diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index 1cef2180..b86b6b07 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -7,7 +7,7 @@ import scala.collection.mutable.{ArrayBuffer} import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup} import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} 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 chipyard.iobinders._ @@ -23,7 +23,7 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) * drive clock and reset generation */ -class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions { +class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions with BindingScope { // A publicly accessible list of IO cells (useful for a floorplanning tool, for example) val iocells = ArrayBuffer.empty[IOCell] From 949d60597fb4d930e985cdc4c935683649fe11d4 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 14 Oct 2020 14:50:38 -0700 Subject: [PATCH 21/28] Revert "Support evaluation of HarnessBinders in LazyModule context" This reverts commit 9c298eedfe539e05aa409d4b60595f5a0ab2ada1. --- .../src/main/scala/HarnessBinders.scala | 75 +++++++++---------- .../chipyard/src/main/scala/IOBinders.scala | 36 +++++---- .../chipyard/src/main/scala/TestHarness.scala | 2 +- .../src/main/scala/BridgeBinders.scala | 16 ++-- 4 files changed, 68 insertions(+), 61 deletions(-) diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index 6f7d2dd8..e5cfacfb 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -1,7 +1,7 @@ package chipyard.harness import chisel3._ -import chisel3.experimental.{Analog, BaseModule} +import chisel3.experimental.{Analog} import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} @@ -33,41 +33,40 @@ case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalRefer object ApplyHarnessBinders { - def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = { + def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = { val pm = portMap.withDefaultValue(Nil) - p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } + map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } } } -class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) extends Config((site, here, up) => { +class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { - val pts = ports.collect({case p: U => p}) + val pts = ports.collect({case p: S => p}) require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - val upfn = up(HarnessBinders, site)(tag.runtimeClass.toString) - th match { - case th: S => - t match { - case system: T => composer(upfn)(system, th, pts) - case _ => Nil - } + t match { + case system: T => fn(system, th, pts) case _ => Nil } }) ) }) -class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) - (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) - extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn) - -class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) - (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) - extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p)) - +class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { + case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> + ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { + val pts = ports.collect({case p: S => p}) + require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") + t match { + case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts) + case _ => Nil + } + }) + ) +}) class WithGPIOTiedOff extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => { + (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { ports.foreach { _ <> AnalogConst(0) } Nil } @@ -75,7 +74,7 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({ // DOC include start: WithUARTAdapter class WithUARTAdapter extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { UARTAdapter.connect(ports)(system.p) Nil } @@ -83,14 +82,14 @@ class WithUARTAdapter extends OverrideHarnessBinder({ // DOC include end: WithUARTAdapter class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ - (system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { + (system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p) Nil } }) class WithSimBlockDevice extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) } Nil @@ -98,7 +97,7 @@ class WithSimBlockDevice extends OverrideHarnessBinder({ }) class WithBlockDeviceModel extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } } Nil @@ -106,7 +105,7 @@ class WithBlockDeviceModel extends OverrideHarnessBinder({ }) class WithLoopbackNIC extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => withClockAndReset(n.clock, th.harnessReset) { @@ -118,7 +117,7 @@ class WithLoopbackNIC extends OverrideHarnessBinder({ }) class WithSimNetwork extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) } Nil @@ -126,7 +125,7 @@ class WithSimNetwork extends OverrideHarnessBinder({ }) class WithSimAXIMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p)) @@ -140,7 +139,7 @@ class WithSimAXIMem extends OverrideHarnessBinder({ }) class WithBlackBoxSimMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val memSize = p(ExtMem).get.master.size @@ -155,7 +154,7 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({ }) class WithSimAXIMMIO extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MMIOPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) => val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p)) @@ -169,21 +168,21 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({ }) class WithTieOffInterrupts extends OverrideHarnessBinder({ - (system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => { + (system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { ports.foreach { _ := 0.U } Nil } }) class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ - (system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { ports.foreach({ p => p := DontCare; p.bits.tieoff() }) Nil } }) class WithSimDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case d: ClockedDMIIO => val dtm_success = WireInit(false.B) @@ -199,7 +198,7 @@ class WithSimDebug extends OverrideHarnessBinder({ }) class WithTiedOffDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case j: JTAGIO => j.TCK := true.B.asClock @@ -225,7 +224,7 @@ class WithTiedOffDebug extends OverrideHarnessBinder({ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -235,7 +234,7 @@ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ }) class WithSimSerial extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -246,14 +245,14 @@ class WithSimSerial extends OverrideHarnessBinder({ }) class WithTraceGenSuccess extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => { + (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { ports.map { p => when (p) { th.success := true.B } } Nil } }) class WithSimDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } Nil } diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 5259cbb1..4a31e2c0 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -72,33 +72,41 @@ object GetSystemParameters { } } -class IOBinder[T, S <: Data](composer: (Any => (Seq[Data], Seq[IOCell])) => T => (Seq[Data], Seq[IOCell]))(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f) + +// This macro overrides previous matches on some Top mixin. This is useful for +// binders which drive IO, since those typically cannot be composed +class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> ((t: Any) => { - val upfn = up(IOBinders, site)(tag.runtimeClass.toString) t match { - case system: T => composer(upfn)(system) + case system: T => + val (ports, cells) = fn(system) + (ports, cells) case _ => (Nil, Nil) } }) ) }) - -// This macro overrides previous matches on some Top mixin. This is useful for -// binders which drive IO, since those typically cannot be composed -class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => fn) - - // This macro composes with previous matches on some Top mixin. This is useful for // annotation-like binders, since those can typically be composed -class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => t => { - val r = upfn(t) - val h = fn(t) - (r._1 ++ h._1, r._2 ++ h._2) +class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { + case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> + ((t: Any) => { + t match { + case system: T => + val r = up(IOBinders, site)(tag.runtimeClass.toString)(system) + val h = fn(system) + val ports = r._1 ++ h._1 + val cells = r._2 ++ h._2 + (ports, cells) + case _ => (Nil, Nil) + } + }) + ) }) - object BoreHelper { def apply(name: String, source: Clock): Clock = { val clock_io = IO(Output(Clock())).suggestName(name) diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index 64b889e3..2faff565 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -44,7 +44,7 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign lazyDut match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) - ApplyHarnessBinders(this, d.lazySystem, d.portMap.toMap) + ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) } } diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 2fa49fc3..444c7b33 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => { }) class WithSerialBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { ports.map { port => implicit val p = GetSystemParameters(system) val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -77,7 +77,7 @@ class WithSerialBridge extends OverrideHarnessBinder({ }) class WithNICBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { val p: Parameters = GetSystemParameters(system) ports.map { n => NICBridge(n.clock, n.bits)(p) } Nil @@ -85,12 +85,12 @@ class WithNICBridge extends OverrideHarnessBinder({ }) class WithUARTBridge extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) => + (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil }) class WithBlockDeviceBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) } Nil @@ -98,7 +98,7 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({ }) class WithFASEDBridge extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { implicit val p: Parameters = GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) => val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth, @@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({ }) class WithTracerVBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) } Nil } }) class WithDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => + (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil }) class WithTraceGenBridge extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) => + (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil }) From dcac9b79dfb222218023372a0a335647466ec310 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 14 Oct 2020 16:15:10 -0700 Subject: [PATCH 22/28] Basic working with UART --- fpga/Makefile | 2 +- fpga/src/main/scala/vcu118/Configs.scala | 6 +- fpga/src/main/scala/vcu118/TestHarness.scala | 116 +++++++++++++++---- 3 files changed, 98 insertions(+), 26 deletions(-) diff --git a/fpga/Makefile b/fpga/Makefile index f3f6308b..643e0c67 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -26,7 +26,7 @@ CONFIG := FakeBringupConfig CONFIG_PACKAGE := chipyard.fpga.vcu118 GENERATOR_PACKAGE := chipyard TB := none # unused -TOP := VCU118Platform +TOP := ChipTop # setup the board to use BOARD ?= arty diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index feaa0484..efb2c551 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -73,11 +73,11 @@ class FakeBringupConfig extends Config( new WithBringupUART ++ //new WithBringupSPI ++ //new WithBringupI2C ++ - new WithBringupGPIO ++ - new chipyard.iobinders.WithUARTIOCells ++ + //new WithBringupGPIO ++ + new WithUARTIOPassthrough ++ //new WithSPICells ++ //new WithI2CCells ++ - new chipyard.iobinders.WithGPIOCells ++ + //new chipyard.iobinders.WithGPIOCells ++ //new WithBringupDDR ++ new WithBringupPeripherals ++ new chipyard.config.WithNoSubsystemDrivenClocks ++ diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index d371aced..ea8d4b0c 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -20,14 +20,31 @@ import sifive.blocks.devices.gpio._ import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} import chipyard.harness._ -import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions} +import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop} case object DUTFrequencyKey extends Field[Double](100.0) -class VCU118FPGATestHarness(override implicit val p: Parameters) extends ChipyardVCU118Shell with HasHarnessSignalReferences { +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 @@ -44,13 +61,13 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends Chipyar val dutGroup = ClockGroup() dutClock := dutWrangler.node := dutGroup := harnessSysPLL - InModuleBody { - topDesign.module match { case td: LazyModuleImp => { - td.clock := dutClock.in.head._1.clock - td.reset := dutClock.in.head._1.reset - } - } - } + //InModuleBody { + // topDesign.module match { case td: LazyModuleImp => { + // td.clock := dutClock.in.head._1.clock + // td.reset := dutClock.in.head._1.reset + // } + // } + //} // connect ref clock to dummy sink node ref_clock.get() match { @@ -60,20 +77,75 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends Chipyar } } - lazy val harnessClock = InModuleBody { - dutClock.in.head._1.clock - }.getWrappedValue - lazy val harnessReset = InModuleBody { - WireInit(dutClock.in.head._1.reset) - }.getWrappedValue - lazy val dutReset = harnessReset - lazy val success = InModuleBody { false.B }.getWrappedValue + // extra overlays - topDesign match { case d: HasTestHarnessFunctions => - InModuleBody { - d.harnessFunctions.foreach(_(this)) - } - ApplyHarnessBinders(this, d.lazySystem, d.portMap.toMap) + /*** UART ***/ + + // 1st UART goes to the VCU118 dedicated UART + + // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design + // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) + dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) + + // 2nd UART goes to the FMC UART + + val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) + + val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) + dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + + /*** GPIO ***/ + + val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { + val maxGPIOSupport = 32 + 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 VCU118FPGATestHarnessImp(this) } +class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { + + val outer = _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 + + // harness binders are non-lazy + _outer.topDesign match { case d: HasTestHarnessFunctions => + d.harnessFunctions.foreach(_(this)) + ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) + } +} From 7f387a254b25951f9038a93bfab10833bdb6c5ee Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 14 Oct 2020 23:09:49 -0700 Subject: [PATCH 23/28] Working up until the MMC attachment --- fpga/Makefile | 8 +- .../vcu118/{ => bringup}/BringupGPIOs.scala | 0 .../scala/vcu118/{ => bringup}/Configs.scala | 31 +++--- .../vcu118/{ => bringup}/CustomOverlays.scala | 0 .../scala/vcu118/bringup/HarnessBinders.scala | 94 +++++++++++++++++++ .../main/scala/vcu118/bringup/IOBinders.scala | 90 ++++++++++++++++++ .../vcu118/{ => bringup}/TestHarness.scala | 50 ++++++++-- 7 files changed, 248 insertions(+), 25 deletions(-) rename fpga/src/main/scala/vcu118/{ => bringup}/BringupGPIOs.scala (100%) rename fpga/src/main/scala/vcu118/{ => bringup}/Configs.scala (85%) rename fpga/src/main/scala/vcu118/{ => bringup}/CustomOverlays.scala (100%) create mode 100644 fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala create mode 100644 fpga/src/main/scala/vcu118/bringup/IOBinders.scala rename fpga/src/main/scala/vcu118/{ => bringup}/TestHarness.scala (74%) diff --git a/fpga/Makefile b/fpga/Makefile index 643e0c67..e6bc426a 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -19,11 +19,11 @@ include $(base_dir)/variables.mk # default variables to build the arty example SUB_PROJECT := fpga SBT_PROJECT := fpga_platforms -MODEL := VCU118FPGATestHarness -VLOG_MODEL := VCU118FPGATestHarness -MODEL_PACKAGE := chipyard.fpga.vcu118 +MODEL := BringupVCU118FPGATestHarness +VLOG_MODEL := BringupVCU118FPGATestHarness +MODEL_PACKAGE := chipyard.fpga.vcu118.bringup CONFIG := FakeBringupConfig -CONFIG_PACKAGE := chipyard.fpga.vcu118 +CONFIG_PACKAGE := chipyard.fpga.vcu118.bringup GENERATOR_PACKAGE := chipyard TB := none # unused TOP := ChipTop diff --git a/fpga/src/main/scala/vcu118/BringupGPIOs.scala b/fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala similarity index 100% rename from fpga/src/main/scala/vcu118/BringupGPIOs.scala rename to fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala similarity index 85% rename from fpga/src/main/scala/vcu118/Configs.scala rename to fpga/src/main/scala/vcu118/bringup/Configs.scala index efb2c551..9a34b198 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -1,5 +1,4 @@ -// See LICENSE for license details. -package chipyard.fpga.vcu118 +package chipyard.fpga.vcu118.bringup import math.min @@ -29,12 +28,12 @@ class WithBringupPeripherals extends Config((site, here, up) => { case PeripheryUARTKey => List( UARTParams(address = BigInt(0x64000000L)), UARTParams(address = BigInt(0x64003000L))) -// case PeripherySPIKey => List( -// SPIParams(rAddress = BigInt(0x64001000L)), -// SPIParams(rAddress = BigInt(0x64004000L))) -// case VCU118ShellPMOD => "SDIO" -// case PeripheryI2CKey => List( -// I2CParams(address = BigInt(0x64005000L))) + case PeripherySPIKey => List( + SPIParams(rAddress = BigInt(0x64001000L)), + SPIParams(rAddress = BigInt(0x64004000L))) + case VCU118ShellPMOD => "SDIO" + 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) @@ -71,14 +70,16 @@ class SmallModifications extends Config((site, here, up) => { class FakeBringupConfig extends Config( new WithBringupUART ++ - //new WithBringupSPI ++ - //new WithBringupI2C ++ - //new WithBringupGPIO ++ + new WithBringupSPI ++ + new WithBringupI2C ++ + new WithBringupGPIO ++ + new WithBringupDDR ++ new WithUARTIOPassthrough ++ - //new WithSPICells ++ - //new WithI2CCells ++ - //new chipyard.iobinders.WithGPIOCells ++ - //new WithBringupDDR ++ + new WithSPIIOPassthrough ++ + //new WithMMCSPIDTS ++ + new WithI2CIOPassthrough ++ + new WithGPIOIOPassthrough ++ + new WithTLIOPassthrough ++ new WithBringupPeripherals ++ new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ diff --git a/fpga/src/main/scala/vcu118/CustomOverlays.scala b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala similarity index 100% rename from fpga/src/main/scala/vcu118/CustomOverlays.scala rename to fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala diff --git a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala new file mode 100644 index 00000000..efe805cd --- /dev/null +++ b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala @@ -0,0 +1,94 @@ +package chipyard.fpga.vcu118.bringup + +import chisel3._ +import chisel3.experimental.{Analog, IO} + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ + +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.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} +import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences} +import chipyard.harness._ + +/*** UART ***/ +class WithBringupUART extends OverrideHarnessBinder({ + (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { + require(ports.size == 2) + + vcu118th.outer.io_uart_bb.bundle <> ports.head + vcu118th.outer.io_uart_bb_2.bundle <> ports.last + } } + + Nil + } +}) + +/*** SPI ***/ +class WithBringupSPI extends OverrideHarnessBinder({ + (system: HasPeripherySPIModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { + th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { + require(ports.size == 2) + + vcu118th.outer.io_spi_bb.bundle <> ports.head + vcu118th.outer.io_spi_bb_2.bundle <> ports.last + } } + + Nil + } +}) + +/*** I2C ***/ +class WithBringupI2C extends OverrideHarnessBinder({ + (system: HasPeripheryI2CModuleImp, th: HasHarnessSignalReferences, ports: Seq[I2CPort]) => { + th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { + require(ports.size == 1) + + vcu118th.outer.io_i2c_bb.bundle <> ports.head + } } + + Nil + } +}) + +/*** GPIO ***/ +class WithBringupGPIO extends OverrideHarnessBinder({ + (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { + th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { + (vcu118th.outer.io_gpio_bb zip ports).map { case (bb_io, dut_io) => + bb_io.bundle <> dut_io + } + } } + + Nil + } +}) + +/*** Experimental DDR ***/ +class WithBringupDDR extends OverrideHarnessBinder({ + (system: CanHaveMasterTLMemPort, th: HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { + th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { + require(ports.size == 1) + + val bundles = vcu118th.outer.ddrClient.out.map(_._1) + val ddrClientBundle = Wire(new freechips.rocketchip.util.HeterogeneousBag(bundles.map(_.cloneType))) + bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } + ddrClientBundle <> ports.head + } } + + Nil + } +}) diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala new file mode 100644 index 00000000..d10f5500 --- /dev/null +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -0,0 +1,90 @@ +package chipyard.fpga.vcu118.bringup + +import chisel3._ +import chisel3.util.experimental.{BoringUtils} +import chisel3.experimental.{Analog, IO, DataMirror} + +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike, ResourceBinding, Resource, ResourceAddress} +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.jtag.{JTAGIO} +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.system.{SimAXIMem} +import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} +import freechips.rocketchip.util._ +import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} +import freechips.rocketchip.tilelink.{TLBundle} + +import sifive.blocks.devices.gpio._ +import sifive.blocks.devices.uart._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.i2c._ +import tracegen.{TraceGenSystemModuleImp} + +import barstools.iocell.chisel._ + +import testchipip._ +import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} + +import chipyard.{GlobalResetSchemeKey, CanHaveMasterTLMemPort} +import chipyard.iobinders.{OverrideIOBinder} + +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 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 WithSPIIOPassthrough extends OverrideIOBinder({ + (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 WithMMCSPIDTS extends OverrideIOBinder({ +// (system: HasPeripherySPI) => { +// +// val mmcDev = new MMCDevice(system.tlspi.head.device, 1) +// ResourceBinding { +// Resource(mmcDev, "reg").bind(ResourceAddress(0)) +// } +// +// (Nil, 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) + } +}) + +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) + } +}) diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala similarity index 74% rename from fpga/src/main/scala/vcu118/TestHarness.scala rename to fpga/src/main/scala/vcu118/bringup/TestHarness.scala index ea8d4b0c..28e42e3c 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -1,4 +1,4 @@ -package chipyard.fpga.vcu118 +package chipyard.fpga.vcu118.bringup import chisel3._ import chisel3.experimental.{Analog, IO} @@ -18,13 +18,12 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} import chipyard.harness._ -import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop} +import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop} case object DUTFrequencyKey extends Field[Double](100.0) -class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays { +class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays { def dp = designParameters @@ -81,6 +80,8 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S /*** UART ***/ + require(dp(PeripheryUARTKey).size == 2) + // 1st UART goes to the VCU118 dedicated UART // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design @@ -95,6 +96,29 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + /*** SPI ***/ + + require(dp(PeripherySPIKey).size == 2) + + // 1st SPI goes to the VCU118 SDIO port + + val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) + val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) + + // 2nd SPI goes to the ADI port + + val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) + + val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) + val adi_placed = dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_spi_bb_2)) + + /*** 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 => { @@ -108,11 +132,25 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S placer.place(GPIODesignInput(params, io_gpio_bb(i))) } + /*** DDR ***/ + + val ddrWrangler = LazyModule(new ResetWrangler) + val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, ddrWrangler.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) + override lazy val module = new BringupVCU118FPGATestHarnessImp(this) } -class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { +class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { val outer = _outer From 9ba4918cb863294844a3b16cddede8b4a7d752dd Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 15 Oct 2020 11:46:42 -0700 Subject: [PATCH 24/28] Inject MMCDevice into TLSPI Node --- fpga/src/main/scala/vcu118/bringup/Configs.scala | 10 +++++++--- fpga/src/main/scala/vcu118/bringup/IOBinders.scala | 12 ------------ generators/sifive-blocks | 2 +- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index 9a34b198..f0dd91cc 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -6,7 +6,7 @@ import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet} +import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress} import freechips.rocketchip.system._ import freechips.rocketchip.tile._ @@ -20,7 +20,6 @@ import sifive.fpgashells.shell.{DesignKey} import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD} import chipyard.{BuildTop} -import chipyard.fpga.vcu118.bringup.{BringupGPIOs} import chipyard.harness._ @@ -29,7 +28,12 @@ class WithBringupPeripherals extends Config((site, here, up) => { UARTParams(address = BigInt(0x64000000L)), UARTParams(address = BigInt(0x64003000L))) case PeripherySPIKey => List( - SPIParams(rAddress = BigInt(0x64001000L)), + SPIParams(rAddress = BigInt(0x64001000L), + injectFunc = Some((spi: TLSPI) => { + ResourceBinding { + Resource(new MMCDevice(spi.device, 1), "reg").bind(ResourceAddress(0)) + } + })), SPIParams(rAddress = BigInt(0x64004000L))) case VCU118ShellPMOD => "SDIO" case PeripheryI2CKey => List( diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index d10f5500..ece212bb 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -59,18 +59,6 @@ class WithSPIIOPassthrough extends OverrideIOBinder({ } }) -//class WithMMCSPIDTS extends OverrideIOBinder({ -// (system: HasPeripherySPI) => { -// -// val mmcDev = new MMCDevice(system.tlspi.head.device, 1) -// ResourceBinding { -// Resource(mmcDev, "reg").bind(ResourceAddress(0)) -// } -// -// (Nil, 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") } diff --git a/generators/sifive-blocks b/generators/sifive-blocks index 413e0a88..ed9f63f9 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit 413e0a88a4e48b1966b9444d613a7f3a776e65aa +Subproject commit ed9f63f9f5b9209c9e5ef2adfd063d6669691d79 From dd358f45ab7e3e85aab41cbef04710a056a89b3e Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Mon, 19 Oct 2020 11:29:25 -0700 Subject: [PATCH 25/28] UART Working... Bumped to newer fpga-shells --- fpga/Makefile | 2 +- fpga/fpga-shells | 2 +- .../main/scala/vcu118/bringup/Configs.scala | 24 ++++++++++++------- .../scala/vcu118/bringup/CustomOverlays.scala | 3 +-- .../scala/vcu118/bringup/TestHarness.scala | 3 +++ generators/sifive-blocks | 2 +- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/fpga/Makefile b/fpga/Makefile index e6bc426a..b984431c 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -29,7 +29,7 @@ TB := none # unused TOP := ChipTop # setup the board to use -BOARD ?= arty +BOARD ?= vcu118 .PHONY: default default: $(mcs) diff --git a/fpga/fpga-shells b/fpga/fpga-shells index e8e7f8a3..89a5efec 160000 --- a/fpga/fpga-shells +++ b/fpga/fpga-shells @@ -1 +1 @@ -Subproject commit e8e7f8a321ebde213ebc79db06422278d9aa477f +Subproject commit 89a5efec011ebc21b9455923501df70783161cb8 diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index f0dd91cc..8db731ed 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -1,6 +1,7 @@ package chipyard.fpga.vcu118.bringup import math.min +import sys.process._ import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ @@ -54,6 +55,7 @@ class WithBringupPeripherals extends Config((site, here, up) => { }) class SmallModifications extends Config((site, here, up) => { + case DebugModuleKey => None // disable debug module case SystemBusKey => up(SystemBusKey).copy( errorDevice = Some(DevNullParams( Seq(AddressSet(0x3000, 0xfff)), @@ -61,18 +63,24 @@ class SmallModifications extends Config((site, here, up) => { maxTransfer=128, region = RegionType.TRACKED))) case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = - Some(BigDecimal(site(DUTFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt), + Some(BigDecimal(site(DUTFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt)) + case ControlBusKey => up(ControlBusKey, site).copy( errorDevice = None) case DTSTimebase => BigInt(1000000) - case JtagDTMKey => new JtagDTMConfig( - idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). - idcodePartNum = 0x000, // Decided to simplify. - idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. - debugIdleCycles = 5) // Reasonable guess for synchronization }) +class WithBootROM extends Config((site, here, up) => { + case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => + // invoke makefile for sdboot + val freqMHz = site(DUTFrequencyKey).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") + } +}) class FakeBringupConfig extends Config( + new SmallModifications ++ new WithBringupUART ++ new WithBringupSPI ++ new WithBringupI2C ++ @@ -80,14 +88,14 @@ class FakeBringupConfig extends Config( new WithBringupDDR ++ new WithUARTIOPassthrough ++ new WithSPIIOPassthrough ++ - //new WithMMCSPIDTS ++ new WithI2CIOPassthrough ++ new WithGPIOIOPassthrough ++ new WithTLIOPassthrough ++ new WithBringupPeripherals ++ + new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ - new chipyard.config.WithBootROM ++ + new WithBootROM ++ // use local bootrom new chipyard.config.WithL2TLBs(1024) ++ new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++ diff --git a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala index 2c438a34..fdbbb919 100644 --- a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala @@ -138,8 +138,7 @@ class BringupGPIOVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: packagePinsWithIOStdWithPackageIOs foreach { case (pin, iostd, io) => { shell.xdc.addPackagePin(io, pin) shell.xdc.addIOStandard(io, iostd) - // TODO: no drive strength found - //if (iostd == "LVCMOS12") { shell.xdc.addDriveStrength(io, "8") } + if (iostd == "LVCMOS12") { shell.xdc.addDriveStrength(io, "8") } } } } } } diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index 28e42e3c..28c3ae14 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -181,6 +181,9 @@ class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) exte 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)) diff --git a/generators/sifive-blocks b/generators/sifive-blocks index ed9f63f9..c160544e 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit ed9f63f9f5b9209c9e5ef2adfd063d6669691d79 +Subproject commit c160544e74db4f33d51f23c8a41c07a1ec16b7b7 From db73cab164b063da299bfcabba6c6d99f91277fb Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Tue, 20 Oct 2020 21:20:11 -0700 Subject: [PATCH 26/28] Add BootROM | Fix ResetWrangler for DDR | Add scripts --- fpga/.gitignore | 4 +- fpga/Makefile | 10 + fpga/scripts/run_impl_bitstream.tcl | 45 ++++ fpga/scripts/write_mmi.tcl | 75 ++++++ .../main/resources/vcu118/sdboot/.gitignore | 1 + .../src/main/resources/vcu118/sdboot/Makefile | 39 +++ .../src/main/resources/vcu118/sdboot/common.h | 9 + fpga/src/main/resources/vcu118/sdboot/head.S | 20 ++ .../resources/vcu118/sdboot/include/bits.h | 36 +++ .../resources/vcu118/sdboot/include/const.h | 18 ++ .../vcu118/sdboot/include/devices/clint.h | 14 ++ .../vcu118/sdboot/include/devices/gpio.h | 24 ++ .../vcu118/sdboot/include/devices/plic.h | 31 +++ .../vcu118/sdboot/include/devices/spi.h | 79 ++++++ .../vcu118/sdboot/include/devices/uart.h | 28 +++ .../vcu118/sdboot/include/platform.h | 108 ++++++++ .../sdboot/include/riscv_test_defaults.h | 81 ++++++ .../vcu118/sdboot/include/sections.h | 17 ++ .../resources/vcu118/sdboot/include/smp.h | 142 +++++++++++ .../main/resources/vcu118/sdboot/kprintf.c | 75 ++++++ .../main/resources/vcu118/sdboot/kprintf.h | 49 ++++ .../resources/vcu118/sdboot/linker/memory.lds | 5 + .../vcu118/sdboot/linker/sdboot.elf.lds | 79 ++++++ fpga/src/main/resources/vcu118/sdboot/sd.c | 236 ++++++++++++++++++ .../scala/vcu118/bringup/TestHarness.scala | 3 +- 25 files changed, 1223 insertions(+), 5 deletions(-) create mode 100644 fpga/scripts/run_impl_bitstream.tcl create mode 100644 fpga/scripts/write_mmi.tcl create mode 100644 fpga/src/main/resources/vcu118/sdboot/.gitignore create mode 100644 fpga/src/main/resources/vcu118/sdboot/Makefile create mode 100644 fpga/src/main/resources/vcu118/sdboot/common.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/head.S create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/bits.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/const.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/devices/clint.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/platform.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/riscv_test_defaults.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/sections.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/include/smp.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/kprintf.c create mode 100644 fpga/src/main/resources/vcu118/sdboot/kprintf.h create mode 100644 fpga/src/main/resources/vcu118/sdboot/linker/memory.lds create mode 100644 fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds create mode 100644 fpga/src/main/resources/vcu118/sdboot/sd.c diff --git a/fpga/.gitignore b/fpga/.gitignore index a0991ff4..814384f3 100644 --- a/fpga/.gitignore +++ b/fpga/.gitignore @@ -1,3 +1 @@ -* -!.gitignore -!Makefile +generated-src diff --git a/fpga/Makefile b/fpga/Makefile index b984431c..748a5029 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -76,6 +76,16 @@ $(BIT_FILE): $(synth_list_f) .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) diff --git a/fpga/scripts/run_impl_bitstream.tcl b/fpga/scripts/run_impl_bitstream.tcl new file mode 100644 index 00000000..ec3828e8 --- /dev/null +++ b/fpga/scripts/run_impl_bitstream.tcl @@ -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 diff --git a/fpga/scripts/write_mmi.tcl b/fpga/scripts/write_mmi.tcl new file mode 100644 index 00000000..e577dd2b --- /dev/null +++ b/fpga/scripts/write_mmi.tcl @@ -0,0 +1,75 @@ +proc write_mmi {filepath inst} { + current_instance + current_instance $inst + set chn [open $filepath w] + puts $chn "" + puts $chn "" + puts $chn "\t" + 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> 3]\">" + puts $chn "\t\t\t" + 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" + puts $chn "\t\t\t\t\t" + puts $chn "\t\t\t\t\t" + puts $chn "\t\t\t\t\t" + puts $chn "\t\t\t\t" + } + puts $chn "\t\t\t" + puts $chn "\t\t" + } + } + puts $chn "\t" + puts $chn "\t" + puts $chn "\t\t" + puts $chn "" + 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 diff --git a/fpga/src/main/resources/vcu118/sdboot/.gitignore b/fpga/src/main/resources/vcu118/sdboot/.gitignore new file mode 100644 index 00000000..378eac25 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/.gitignore @@ -0,0 +1 @@ +build diff --git a/fpga/src/main/resources/vcu118/sdboot/Makefile b/fpga/src/main/resources/vcu118/sdboot/Makefile new file mode 100644 index 00000000..b9c21470 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/Makefile @@ -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) diff --git a/fpga/src/main/resources/vcu118/sdboot/common.h b/fpga/src/main/resources/vcu118/sdboot/common.h new file mode 100644 index 00000000..4f71e103 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/common.h @@ -0,0 +1,9 @@ +#ifndef _SDBOOT_COMMON_H +#define _SDBOOT_COMMON_H + +#ifndef PAYLOAD_DEST + #define PAYLOAD_DEST MEMORY_MEM_ADDR +#endif + + +#endif diff --git a/fpga/src/main/resources/vcu118/sdboot/head.S b/fpga/src/main/resources/vcu118/sdboot/head.S new file mode 100644 index 00000000..662a6fd2 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/head.S @@ -0,0 +1,20 @@ +// See LICENSE for license details. +#include +#include +#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 .rodata +dtb: diff --git a/fpga/src/main/resources/vcu118/sdboot/include/bits.h b/fpga/src/main/resources/vcu118/sdboot/include/bits.h new file mode 100644 index 00000000..bfe656fe --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/bits.h @@ -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 diff --git a/fpga/src/main/resources/vcu118/sdboot/include/const.h b/fpga/src/main/resources/vcu118/sdboot/include/const.h new file mode 100644 index 00000000..8dcffbb0 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/const.h @@ -0,0 +1,18 @@ +// See LICENSE for license details. +/* Derived from */ + +#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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/devices/clint.h b/fpga/src/main/resources/vcu118/sdboot/include/devices/clint.h new file mode 100644 index 00000000..c2b05bae --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/devices/clint.h @@ -0,0 +1,14 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_CLINT_H +#define _SIFIVE_CLINT_H + + +#define CLINT_MSIP 0x0000 +#define CLINT_MSIP_size 0x4 +#define CLINT_MTIMECMP 0x4000 +#define CLINT_MTIMECMP_size 0x8 +#define CLINT_MTIME 0xBFF8 +#define CLINT_MTIME_size 0x8 + +#endif /* _SIFIVE_CLINT_H */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h b/fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h new file mode 100644 index 00000000..f7f0acb4 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h @@ -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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h b/fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h new file mode 100644 index 00000000..4d5b2d8d --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h @@ -0,0 +1,31 @@ +// See LICENSE for license details. + +#ifndef PLIC_H +#define PLIC_H + +#include + +// 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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h b/fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h new file mode 100644 index 00000000..7118572a --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h @@ -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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h b/fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h new file mode 100644 index 00000000..aecfd912 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h @@ -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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/platform.h b/fpga/src/main/resources/vcu118/sdboot/include/platform.h new file mode 100644 index 00000000..c240e0e5 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/platform.h @@ -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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/riscv_test_defaults.h b/fpga/src/main/resources/vcu118/sdboot/include/riscv_test_defaults.h new file mode 100644 index 00000000..a2dea3d4 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/riscv_test_defaults.h @@ -0,0 +1,81 @@ +// See LICENSE for license details. +#ifndef _RISCV_TEST_DEFAULTS_H +#define _RISCV_TEST_DEFAULTS_H + +#define TESTNUM x28 +#define TESTBASE 0x4000 + +#define RVTEST_RV32U \ + .macro init; \ + .endm + +#define RVTEST_RV64U \ + .macro init; \ + .endm + +#define RVTEST_RV32UF \ + .macro init; \ + /* If FPU exists, initialize FCSR. */ \ + csrr t0, misa; \ + andi t0, t0, 1 << ('F' - 'A'); \ + beqz t0, 1f; \ + /* Enable FPU if it exists. */ \ + li t0, MSTATUS_FS; \ + csrs mstatus, t0; \ + fssr x0; \ +1: ; \ + .endm + +#define RVTEST_RV64UF \ + .macro init; \ + /* If FPU exists, initialize FCSR. */ \ + csrr t0, misa; \ + andi t0, t0, 1 << ('F' - 'A'); \ + beqz t0, 1f; \ + /* Enable FPU if it exists. */ \ + li t0, MSTATUS_FS; \ + csrs mstatus, t0; \ + fssr x0; \ +1: ; \ + .endm + +#define RVTEST_CODE_BEGIN \ + .section .text.init; \ + .globl _prog_start; \ +_prog_start: \ + init; + +#define RVTEST_CODE_END \ + unimp + +#define RVTEST_PASS \ + fence; \ + li t0, TESTBASE; \ + li t1, 0x5555; \ + sw t1, 0(t0); \ +1: \ + j 1b; + +#define RVTEST_FAIL \ + li t0, TESTBASE; \ + li t1, 0x3333; \ + slli a0, a0, 16; \ + add a0, a0, t1; \ + sw a0, 0(t0); \ +1: \ + j 1b; + +#define EXTRA_DATA + +#define RVTEST_DATA_BEGIN \ + EXTRA_DATA \ + .align 4; .global begin_signature; begin_signature: + +#define RVTEST_DATA_END \ + _msg_init: .asciz "RUN\r\n"; \ + _msg_pass: .asciz "PASS"; \ + _msg_fail: .asciz "FAIL "; \ + _msg_end: .asciz "\r\n"; \ + .align 4; .global end_signature; end_signature: + +#endif /* _RISCV_TEST_DEFAULTS_H */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/sections.h b/fpga/src/main/resources/vcu118/sdboot/include/sections.h new file mode 100644 index 00000000..6e1f0518 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/sections.h @@ -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 */ diff --git a/fpga/src/main/resources/vcu118/sdboot/include/smp.h b/fpga/src/main/resources/vcu118/sdboot/include/smp.h new file mode 100644 index 00000000..145ceb37 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/include/smp.h @@ -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 diff --git a/fpga/src/main/resources/vcu118/sdboot/kprintf.c b/fpga/src/main/resources/vcu118/sdboot/kprintf.c new file mode 100644 index 00000000..57627011 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/kprintf.c @@ -0,0 +1,75 @@ +// See LICENSE for license details. +#include +#include +#include + +#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); +} diff --git a/fpga/src/main/resources/vcu118/sdboot/kprintf.h b/fpga/src/main/resources/vcu118/sdboot/kprintf.h new file mode 100644 index 00000000..26cc8055 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/kprintf.h @@ -0,0 +1,49 @@ +// See LICENSE for license details. +#ifndef _SDBOOT_KPRINTF_H +#define _SDBOOT_KPRINTF_H + +#include +#include + +#define REG32(p, i) ((p)[(i) >> 2]) + +#ifndef UART_CTRL_ADDR + #ifndef UART_NUM + #define UART_NUM 0 + #endif + + #define _CONCAT3(A, B, C) A ## B ## C + #define _UART_CTRL_ADDR(UART_NUM) _CONCAT3(UART, UART_NUM, _CTRL_ADDR) + #define UART_CTRL_ADDR _UART_CTRL_ADDR(UART_NUM) +#endif +static volatile uint32_t * const uart = (void *)(UART_CTRL_ADDR); + +static inline void kputc(char c) +{ + volatile uint32_t *tx = ®32(uart, UART_REG_TXFIFO); +#ifdef __riscv_atomic + int32_t r; + do { + __asm__ __volatile__ ( + "amoor.w %0, %2, %1\n" + : "=r" (r), "+A" (*tx) + : "r" (c)); + } while (r < 0); +#else + while ((int32_t)(*tx) < 0); + *tx = c; +#endif +} + +extern void kputs(const char *); +extern void kprintf(const char *, ...); + +#ifdef DEBUG +#define dprintf(s, ...) kprintf((s), ##__VA_ARGS__) +#define dputs(s) kputs((s)) +#else +#define dprintf(s, ...) do { } while (0) +#define dputs(s) do { } while (0) +#endif + +#endif /* _SDBOOT_KPRINTF_H */ diff --git a/fpga/src/main/resources/vcu118/sdboot/linker/memory.lds b/fpga/src/main/resources/vcu118/sdboot/linker/memory.lds new file mode 100644 index 00000000..997de4d3 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/linker/memory.lds @@ -0,0 +1,5 @@ +MEMORY +{ + bootrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000 + memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000 +} diff --git a/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds b/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds new file mode 100644 index 00000000..34610c94 --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds @@ -0,0 +1,79 @@ +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.*) + } >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"); + } +} diff --git a/fpga/src/main/resources/vcu118/sdboot/sd.c b/fpga/src/main/resources/vcu118/sdboot/sd.c new file mode 100644 index 00000000..bdd9d62a --- /dev/null +++ b/fpga/src/main/resources/vcu118/sdboot/sd.c @@ -0,0 +1,236 @@ +// See LICENSE for license details. +#include + +#include + +#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; +} diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index 28c3ae14..4eaea05b 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -134,8 +134,7 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends /*** DDR ***/ - val ddrWrangler = LazyModule(new ResetWrangler) - val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, ddrWrangler.node, harnessSysPLL)) + 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 => From 3c42e2cae7a903d4d3e914d90405274e247cbbb1 Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Mon, 26 Oct 2020 18:15:58 -0700 Subject: [PATCH 27/28] Fixed BootROM | Updated HarnessBinders --- fpga/src/main/resources/vcu118/sdboot/head.S | 3 ++- .../vcu118/sdboot/linker/sdboot.elf.lds | 1 + .../main/scala/vcu118/bringup/Configs.scala | 19 +++++++------- .../scala/vcu118/bringup/HarnessBinders.scala | 13 +++++----- .../main/scala/vcu118/bringup/IOBinders.scala | 25 +++++++++++++------ .../scala/vcu118/bringup/TestHarness.scala | 5 +++- .../chipyard/src/main/scala/ChipTop.scala | 4 +-- generators/sifive-blocks | 2 +- 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/fpga/src/main/resources/vcu118/sdboot/head.S b/fpga/src/main/resources/vcu118/sdboot/head.S index 662a6fd2..d871b824 100644 --- a/fpga/src/main/resources/vcu118/sdboot/head.S +++ b/fpga/src/main/resources/vcu118/sdboot/head.S @@ -16,5 +16,6 @@ _prog_start: li s1, PAYLOAD_DEST jr s1 - .section .rodata + .section .dtb + .align 3 dtb: diff --git a/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds b/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds index 34610c94..7a0a42fe 100644 --- a/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds +++ b/fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds @@ -47,6 +47,7 @@ SECTIONS .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)); diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index 8db731ed..79dbf6db 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -18,7 +18,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ import sifive.fpgashells.shell.{DesignKey} -import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD} +import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize} import chipyard.{BuildTop} @@ -29,12 +29,7 @@ class WithBringupPeripherals extends Config((site, here, up) => { UARTParams(address = BigInt(0x64000000L)), UARTParams(address = BigInt(0x64003000L))) case PeripherySPIKey => List( - SPIParams(rAddress = BigInt(0x64001000L), - injectFunc = Some((spi: TLSPI) => { - ResourceBinding { - Resource(new MMCDevice(spi.device, 1), "reg").bind(ResourceAddress(0)) - } - })), + SPIParams(rAddress = BigInt(0x64001000L)), SPIParams(rAddress = BigInt(0x64004000L))) case VCU118ShellPMOD => "SDIO" case PeripheryI2CKey => List( @@ -56,6 +51,7 @@ class WithBringupPeripherals extends Config((site, here, up) => { class SmallModifications 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)), @@ -79,6 +75,10 @@ class WithBootROM extends Config((site, here, up) => { } }) +class WithExtMemSetToDDR extends Config((site, here, up) => { + case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize)))) +}) + class FakeBringupConfig extends Config( new SmallModifications ++ new WithBringupUART ++ @@ -92,6 +92,7 @@ class FakeBringupConfig extends Config( new WithGPIOIOPassthrough ++ new WithTLIOPassthrough ++ new WithBringupPeripherals ++ + new WithExtMemSetToDDR ++ // set the external mem port size properly new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ @@ -100,8 +101,8 @@ class FakeBringupConfig extends Config( 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.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ + new chipyard.WithMulticlockCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) diff --git a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala index efe805cd..79f602dc 100644 --- a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala @@ -1,7 +1,7 @@ package chipyard.fpga.vcu118.bringup import chisel3._ -import chisel3.experimental.{Analog, IO} +import chisel3.experimental.{Analog, IO, BaseModule} import freechips.rocketchip.diplomacy._ import freechips.rocketchip.config.{Parameters, Field} @@ -19,13 +19,12 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences} import chipyard.harness._ /*** UART ***/ class WithBringupUART extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) @@ -39,7 +38,7 @@ class WithBringupUART extends OverrideHarnessBinder({ /*** SPI ***/ class WithBringupSPI extends OverrideHarnessBinder({ - (system: HasPeripherySPIModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { + (system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) @@ -53,7 +52,7 @@ class WithBringupSPI extends OverrideHarnessBinder({ /*** I2C ***/ class WithBringupI2C extends OverrideHarnessBinder({ - (system: HasPeripheryI2CModuleImp, th: HasHarnessSignalReferences, ports: Seq[I2CPort]) => { + (system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[I2CPort]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 1) @@ -66,7 +65,7 @@ class WithBringupI2C extends OverrideHarnessBinder({ /*** GPIO ***/ class WithBringupGPIO extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { + (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { (vcu118th.outer.io_gpio_bb zip ports).map { case (bb_io, dut_io) => bb_io.bundle <> dut_io @@ -79,7 +78,7 @@ class WithBringupGPIO extends OverrideHarnessBinder({ /*** Experimental DDR ***/ class WithBringupDDR extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { + (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 1) diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index ece212bb..558b074f 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -5,7 +5,7 @@ import chisel3.util.experimental.{BoringUtils} import chisel3.experimental.{Analog, IO, DataMirror} import freechips.rocketchip.config._ -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike, ResourceBinding, Resource, ResourceAddress} +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike, ResourceBinding, Resource, ResourceAddress, InModuleBody} import freechips.rocketchip.devices.debug._ import freechips.rocketchip.jtag.{JTAGIO} import freechips.rocketchip.subsystem._ @@ -27,7 +27,7 @@ import testchipip._ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} import chipyard.{GlobalResetSchemeKey, CanHaveMasterTLMemPort} -import chipyard.iobinders.{OverrideIOBinder} +import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder} class WithUARTIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryUARTModuleImp) => { @@ -49,13 +49,22 @@ class WithGPIOIOPassthrough extends OverrideIOBinder({ } }) -class WithSPIIOPassthrough extends OverrideIOBinder({ - (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 +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) + } } } - (io_spi_pins_temp, Nil) } }) diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index 4eaea05b..9f51d2aa 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -20,6 +20,7 @@ import sifive.blocks.devices.gpio._ import chipyard.harness._ import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop} +import chipyard.iobinders.{HasIOBinders} case object DUTFrequencyKey extends Field[Double](100.0) @@ -186,6 +187,8 @@ class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) exte // harness binders are non-lazy _outer.topDesign match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) - ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) + } + _outer.topDesign match { case d: HasIOBinders => + ApplyHarnessBinders(this, d.lazySystem, d.portMap) } } diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index bf07bcee..61a043b6 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -23,8 +23,8 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) * drive clock and reset generation */ -class ChipTop(implicit p: Parameters) extends LazyModule - with HasTestHarnessFunctions with HasIOBinders with BindingScope { +class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope + with HasTestHarnessFunctions with HasIOBinders { // The system module specified by BuildSystem lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") diff --git a/generators/sifive-blocks b/generators/sifive-blocks index c160544e..25eae85e 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit c160544e74db4f33d51f23c8a41c07a1ec16b7b7 +Subproject commit 25eae85e711d650a305eb1cd923421a2872fcc56 From 0eca51ba4dce419b803945ad888b27ba7981a455 Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Tue, 27 Oct 2020 12:57:34 -0700 Subject: [PATCH 28/28] Reorganize into bringup/simple | Bump sifive-blocks --- fpga/Makefile | 54 +++++-- fpga/src/main/scala/vcu118/Configs.scala | 85 +++++++++++ .../main/scala/vcu118/HarnessBinders.scala | 51 +++++++ fpga/src/main/scala/vcu118/IOBinders.scala | 52 +++++++ fpga/src/main/scala/vcu118/TestHarness.scala | 144 ++++++++++++++++++ .../main/scala/vcu118/bringup/Configs.scala | 92 +++-------- .../scala/vcu118/bringup/CustomOverlays.scala | 4 - .../scala/vcu118/bringup/HarnessBinders.scala | 53 ++----- .../main/scala/vcu118/bringup/IOBinders.scala | 66 +------- .../scala/vcu118/bringup/TestHarness.scala | 144 ++---------------- generators/sifive-blocks | 2 +- 11 files changed, 420 insertions(+), 327 deletions(-) create mode 100644 fpga/src/main/scala/vcu118/Configs.scala create mode 100644 fpga/src/main/scala/vcu118/HarnessBinders.scala create mode 100644 fpga/src/main/scala/vcu118/IOBinders.scala create mode 100644 fpga/src/main/scala/vcu118/TestHarness.scala diff --git a/fpga/Makefile b/fpga/Makefile index 748a5029..74af21e9 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -14,22 +14,52 @@ 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 -SUB_PROJECT := fpga -SBT_PROJECT := fpga_platforms -MODEL := BringupVCU118FPGATestHarness -VLOG_MODEL := BringupVCU118FPGATestHarness -MODEL_PACKAGE := chipyard.fpga.vcu118.bringup -CONFIG := FakeBringupConfig -CONFIG_PACKAGE := chipyard.fpga.vcu118.bringup -GENERATOR_PACKAGE := chipyard -TB := none # unused -TOP := ChipTop - # setup the board to use -BOARD ?= vcu118 .PHONY: default default: $(mcs) diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala new file mode 100644 index 00000000..f7b0df10 --- /dev/null +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -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) diff --git a/fpga/src/main/scala/vcu118/HarnessBinders.scala b/fpga/src/main/scala/vcu118/HarnessBinders.scala new file mode 100644 index 00000000..ae2462a2 --- /dev/null +++ b/fpga/src/main/scala/vcu118/HarnessBinders.scala @@ -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 + } +}) diff --git a/fpga/src/main/scala/vcu118/IOBinders.scala b/fpga/src/main/scala/vcu118/IOBinders.scala new file mode 100644 index 00000000..a1f67bcd --- /dev/null +++ b/fpga/src/main/scala/vcu118/IOBinders.scala @@ -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) + } +}) diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala new file mode 100644 index 00000000..4748c528 --- /dev/null +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -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) + } +} diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index 79dbf6db..0e5602e5 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -1,39 +1,24 @@ package chipyard.fpga.vcu118.bringup import math.min -import sys.process._ -import freechips.rocketchip.config._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.config.{Config} import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress} -import freechips.rocketchip.system._ -import freechips.rocketchip.tile._ -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 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.{BuildTop} - -import chipyard.harness._ +import chipyard.fpga.vcu118.{RocketVCU118Config, BoomVCU118Config} class WithBringupPeripherals extends Config((site, here, up) => { - case PeripheryUARTKey => List( - UARTParams(address = BigInt(0x64000000L)), - UARTParams(address = BigInt(0x64003000L))) - case PeripherySPIKey => List( - SPIParams(rAddress = BigInt(0x64001000L)), - SPIParams(rAddress = BigInt(0x64004000L))) - case VCU118ShellPMOD => "SDIO" - case PeripheryI2CKey => List( - I2CParams(address = BigInt(0x64005000L))) + 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) @@ -49,60 +34,19 @@ class WithBringupPeripherals extends Config((site, here, up) => { } }) -class SmallModifications 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(DUTFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt)) - case ControlBusKey => up(ControlBusKey, site).copy( - errorDevice = None) - case DTSTimebase => BigInt(1000000) -}) - -class WithBootROM extends Config((site, here, up) => { - case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => - // invoke makefile for sdboot - val freqMHz = site(DUTFrequencyKey).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") - } -}) - -class WithExtMemSetToDDR extends Config((site, here, up) => { - case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize)))) -}) - -class FakeBringupConfig extends Config( - new SmallModifications ++ +class WithBringupAdditions extends Config( new WithBringupUART ++ new WithBringupSPI ++ new WithBringupI2C ++ new WithBringupGPIO ++ - new WithBringupDDR ++ - new WithUARTIOPassthrough ++ - new WithSPIIOPassthrough ++ new WithI2CIOPassthrough ++ new WithGPIOIOPassthrough ++ - new WithTLIOPassthrough ++ + new WithBringupPeripherals) + +class RocketBringupConfig extends Config( new WithBringupPeripherals ++ - new WithExtMemSetToDDR ++ // set the external mem port size properly - new freechips.rocketchip.subsystem.WithoutTLMonitors ++ - new chipyard.config.WithNoSubsystemDrivenClocks ++ - new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ - new WithBootROM ++ // use local bootrom - 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.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.system.BaseConfig) + new RocketVCU118Config) + +class BoomBringupConfig extends Config( + new WithBringupPeripherals ++ + new BoomVCU118Config) diff --git a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala index fdbbb919..c0a96d3c 100644 --- a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala @@ -4,15 +4,11 @@ import chisel3._ import chisel3.experimental.{attach} import freechips.rocketchip.diplomacy._ -import chipsalliance.rocketchip.config.{Parameters, Field} import sifive.fpgashells.shell._ import sifive.fpgashells.ip.xilinx._ import sifive.fpgashells.shell.xilinx._ -import sifive.blocks.devices.gpio._ - - import chipyard.fpga.vcu118.{FMCPMap} /* Connect the I2C to certain FMC pins */ diff --git a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala index 79f602dc..b6693036 100644 --- a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala @@ -3,33 +3,21 @@ package chipyard.fpga.vcu118.bringup import chisel3._ import chisel3.experimental.{Analog, IO, BaseModule} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +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 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.{CanHaveMasterTLMemPort, HasHarnessSignalReferences} -import chipyard.harness._ +import chipyard.{HasHarnessSignalReferences} +import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder} /*** UART ***/ -class WithBringupUART extends OverrideHarnessBinder({ +class WithBringupUART extends ComposeHarnessBinder({ (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) - vcu118th.outer.io_uart_bb.bundle <> ports.head - vcu118th.outer.io_uart_bb_2.bundle <> ports.last + vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last } } Nil @@ -37,13 +25,12 @@ class WithBringupUART extends OverrideHarnessBinder({ }) /*** SPI ***/ -class WithBringupSPI extends OverrideHarnessBinder({ +class WithBringupSPI extends ComposeHarnessBinder({ (system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) - vcu118th.outer.io_spi_bb.bundle <> ports.head - vcu118th.outer.io_spi_bb_2.bundle <> ports.last + vcu118th.bringupOuter.io_adi_spi_bb.bundle <> ports.last } } Nil @@ -56,7 +43,7 @@ class WithBringupI2C extends OverrideHarnessBinder({ th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 1) - vcu118th.outer.io_i2c_bb.bundle <> ports.head + vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head } } Nil @@ -67,7 +54,7 @@ class WithBringupI2C extends OverrideHarnessBinder({ class WithBringupGPIO extends OverrideHarnessBinder({ (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - (vcu118th.outer.io_gpio_bb zip ports).map { case (bb_io, dut_io) => + (vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) => bb_io.bundle <> dut_io } } } @@ -75,19 +62,3 @@ class WithBringupGPIO extends OverrideHarnessBinder({ Nil } }) - -/*** Experimental DDR ***/ -class WithBringupDDR extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - require(ports.size == 1) - - val bundles = vcu118th.outer.ddrClient.out.map(_._1) - val ddrClientBundle = Wire(new freechips.rocketchip.util.HeterogeneousBag(bundles.map(_.cloneType))) - bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head - } } - - Nil - } -}) diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index 558b074f..168933f7 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -1,43 +1,12 @@ package chipyard.fpga.vcu118.bringup import chisel3._ -import chisel3.util.experimental.{BoringUtils} -import chisel3.experimental.{Analog, IO, DataMirror} +import chisel3.experimental.{IO, DataMirror} -import freechips.rocketchip.config._ -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike, ResourceBinding, Resource, ResourceAddress, InModuleBody} -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.jtag.{JTAGIO} -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.system.{SimAXIMem} -import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} -import freechips.rocketchip.util._ -import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} -import freechips.rocketchip.tilelink.{TLBundle} +import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp} +import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp} -import sifive.blocks.devices.gpio._ -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.spi._ -import sifive.blocks.devices.i2c._ -import tracegen.{TraceGenSystemModuleImp} - -import barstools.iocell.chisel._ - -import testchipip._ -import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} - -import chipyard.{GlobalResetSchemeKey, 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) - } -}) +import chipyard.iobinders.{OverrideIOBinder} class WithGPIOIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryGPIOModuleImp) => { @@ -49,25 +18,6 @@ class WithGPIOIOPassthrough extends OverrideIOBinder({ } }) -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 WithI2CIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryI2CModuleImp) => { val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") } @@ -77,11 +27,3 @@ class WithI2CIOPassthrough extends OverrideIOBinder({ (io_i2c_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) - } -}) diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index 9f51d2aa..080f6189 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -1,11 +1,10 @@ package chipyard.fpga.vcu118.bringup import chisel3._ -import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ import freechips.rocketchip.tilelink._ import sifive.fpgashells.shell.xilinx._ @@ -18,100 +17,31 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.harness._ -import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop} -import chipyard.iobinders.{HasIOBinders} +import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp} -case object DUTFrequencyKey extends Field[Double](100.0) - -class BringupVCU118FPGATestHarness(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(DUTFrequencyKey)) - val dutWrangler = LazyModule(new ResetWrangler) - val dutGroup = ClockGroup() - dutClock := dutWrangler.node := dutGroup := harnessSysPLL - - //InModuleBody { - // topDesign.module match { case td: LazyModuleImp => { - // td.clock := dutClock.in.head._1.clock - // td.reset := dutClock.in.head._1.reset - // } - // } - //} - - // connect ref clock to dummy sink node - ref_clock.get() match { - case Some(x : RefClockVCU118PlacedOverlay) => { - val sink = ClockSinkNode(Seq(ClockSinkParameters())) - sink := x.node - } - } - - // extra overlays +class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness { /*** UART ***/ require(dp(PeripheryUARTKey).size == 2) - // 1st UART goes to the VCU118 dedicated UART - - // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design - // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. - val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) - dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) - // 2nd UART goes to the FMC UART val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) - val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) - dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + 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) - // 1st SPI goes to the VCU118 SDIO port - - val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) - val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) - // 2nd SPI goes to the ADI port val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) - val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) - val adi_placed = dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_spi_bb_2)) + val io_adi_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) + dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_adi_spi_bb)) /*** I2C ***/ @@ -123,7 +53,7 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends /*** GPIO ***/ val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { - val maxGPIOSupport = 32 + 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)) }) @@ -133,62 +63,10 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends placer.place(GPIODesignInput(params, io_gpio_bb(i))) } - /*** 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 BringupVCU118FPGATestHarnessImp(this) } -class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { - - val outer = _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) - } +class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends VCU118FPGATestHarnessImp(_outer) { + val bringupOuter = _outer } diff --git a/generators/sifive-blocks b/generators/sifive-blocks index 25eae85e..7e2121ee 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit 25eae85e711d650a305eb1cd923421a2872fcc56 +Subproject commit 7e2121ee26e614f2144a9e4c67c440773aa7544d