From 4556425d5870a76dbcd3eca381c1b327cbb76ad7 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Thu, 8 Jun 2017 09:54:23 -0700 Subject: [PATCH 1/5] upgrade to latest RocketChip * Scala updates to 2.11.12 * Bootrom code moved to testchipip * Makefrag for testchipip blackboxes moved to testchipip * Added support for block device --- .gitignore | 6 + common/Makefrag | 40 +++- common/bootrom/.gitignore | 2 - common/bootrom/Makefile | 16 -- common/bootrom/bootrom.S | 35 --- common/bootrom/bootrom.img | Bin 104 -> 0 bytes common/bootrom/linker.ld | 5 - common/csrc/fesvr_zynq.cc | 66 +++++- common/csrc/zynq_driver.cc | 194 ++++++++++++++++ common/csrc/zynq_driver.h | 37 +++ common/csrc/zynq_tsi_driver.cc | 59 ----- common/csrc/zynq_tsi_driver.h | 22 -- common/generate-pkg-mk.sh | 2 +- common/project/build.properties | 1 + common/project/build.scala | 2 +- common/rocketchip_wrapper.v | 26 +-- common/src/main/scala/Configs.scala | 108 ++++----- common/src/main/scala/Drivers.scala | 273 +++++++++++++++++++++++ common/src/main/scala/Generator.scala | 4 +- common/src/main/scala/Serdes.scala | 162 ++++++++++++++ common/src/main/scala/SerialDriver.scala | 160 ------------- common/src/main/scala/TestHarness.scala | 92 +++++--- common/src/main/scala/Top.scala | 264 ++++------------------ common/src/main/scala/ZynqAdapter.scala | 124 ++++++++++ common/zynq_rocketchip.tcl | 2 + rocket-chip | 2 +- simulation/.gitignore | 11 +- simulation/Makefile | 11 +- testchipip | 2 +- zc706/Makefile | 1 + zc706/fpga-images-zc706 | 2 +- zedboard/Makefile | 1 + zedboard/fpga-images-zedboard | 2 +- zybo/Makefile | 2 +- zybo/fpga-images-zybo | 2 +- 35 files changed, 1080 insertions(+), 658 deletions(-) delete mode 100644 common/bootrom/.gitignore delete mode 100644 common/bootrom/Makefile delete mode 100644 common/bootrom/bootrom.S delete mode 100755 common/bootrom/bootrom.img delete mode 100644 common/bootrom/linker.ld create mode 100644 common/csrc/zynq_driver.cc create mode 100644 common/csrc/zynq_driver.h delete mode 100644 common/csrc/zynq_tsi_driver.cc delete mode 100644 common/csrc/zynq_tsi_driver.h create mode 100644 common/project/build.properties create mode 100644 common/src/main/scala/Drivers.scala create mode 100644 common/src/main/scala/Serdes.scala delete mode 100644 common/src/main/scala/SerialDriver.scala create mode 100644 common/src/main/scala/ZynqAdapter.scala diff --git a/.gitignore b/.gitignore index 230796b..00feb3c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ zedboard/src/tcl/zedboard_rocketchip_*.tcl zedboard/src/tcl/make_bitstream_*.tcl zedboard/src/verilog/rocketchip_wrapper.v zedboard/src/verilog/Top.*.v +zedboard/src/verilog/AsyncResetReg.v +zedboard/src/verilog/plusarg_reader.v zedboard/deliver_output zedboard/soft_build @@ -22,6 +24,8 @@ zybo/src/tcl/zybo_rocketchip_*.tcl zybo/src/tcl/make_bitstream_*.tcl zybo/src/verilog/rocketchip_wrapper.v zybo/src/verilog/Top.*.v +zybo/src/verilog/AsyncResetReg.v +zybo/src/verilog/plusarg_reader.v zybo/deliver_output zybo/soft_build @@ -30,5 +34,7 @@ zc706/src/tcl/zc706_rocketchip_*.tcl zc706/src/tcl/make_bitstream_*.tcl zc706/src/verilog/rocketchip_wrapper.v zc706/src/verilog/Top.*.v +zc706/src/verilog/AsyncResetReg.v +zc706/src/verilog/plusarg_reader.v zc706/deliver_output zc706/soft_build diff --git a/common/Makefrag b/common/Makefrag index 22fbcea..3d989f1 100644 --- a/common/Makefrag +++ b/common/Makefrag @@ -6,15 +6,17 @@ TOP_MODULE_PROJECT ?= zynq TOP_MODULE ?= Top CFG_PROJECT ?= $(TOP_MODULE_PROJECT) CONFIG ?= ZynqConfig +SCALA_VERSION=2.11.12 EXTRA_PACKAGES=testchipip base_dir = $(abspath ..) common = $(base_dir)/common common_build = $(common)/build +testchipip = $(base_dir)/testchipip output_delivery = deliver_output SHELL := /bin/bash -bootrom_img = $(common)/bootrom/bootrom.img +bootrom_img = $(testchipip)/bootrom/bootrom.rv64.img $(testchipip)/bootrom/bootrom.rv32.img rocketchip_stamp = $(common)/lib/rocketchip.stamp extra_stamps = $(addprefix $(common)/lib/,$(addsuffix .stamp,$(EXTRA_PACKAGES))) @@ -28,6 +30,8 @@ verilog_srcs = \ src/verilog/clocking.vh \ src/verilog/rocketchip_wrapper.v \ src/verilog/$(TOP_MODULE).$(CONFIG).v \ + src/verilog/AsyncResetReg.v \ + src/verilog/plusarg_reader.v \ bootimage = fpga-images-$(BOARD)/boot.bin bootimage: $(bootimage) @@ -65,6 +69,8 @@ src/tcl/make_bitstream_$(CONFIG).tcl: $(common)/make_bitstream.tcl sed 's/BOARD_NAME_HERE/$(BOARD)/g;s/CHISEL_CONFIG_HERE/$(CONFIG)/g' \ $(common)/make_bitstream.tcl > src/tcl/make_bitstream_$(CONFIG).tcl +src/verilog/%.v: $(ROCKET_DIR)/vsrc/%.v + cp $< $@ $(ROCKET_DIR)/lib/firrtl.jar: $(FIRRTL_JAR) mkdir -p $(@D) @@ -97,7 +103,8 @@ rocket: src/verilog/$(TOP_MODULE).$(CONFIG).v # Project generation # ------------------------------------------------------------------------------ project = $(proj_name)/$(proj_name).xpr -$(project): | $(verilog_srcs) src/tcl/$(proj_name).tcl +$(project): src/tcl/$(proj_name).tcl | $(verilog_srcs) + rm -rf $(proj_name) vivado -mode tcl -source src/tcl/$(proj_name).tcl; project: $(project) @@ -198,24 +205,35 @@ $(output_delivery)/boot.bin: # ------------------------------------------------------------------------------ fesvr-main = fesvr-zynq -fesvr-srcs = $(common)/csrc/fesvr_zynq.cc $(common)/csrc/zynq_tsi_driver.cc -fesvr-hdrs = $(common)/csrc/zynq_tsi_driver.h -fesvr-lib = $(common_build)/libfesvr.so +fesvr-srcs = \ + $(common)/csrc/fesvr_zynq.cc \ + $(common)/csrc/zynq_driver.cc \ + $(testchipip)/csrc/blkdev.cc \ + +fesvr-hdrs = \ + $(common)/csrc/zynq_driver.h \ + $(testchipip)/csrc/blkdev.h \ + +fesvr-lib = $(common_build)/libfesvr.so CXX_FPGA = arm-xilinx-linux-gnueabi-g++ CXXFLAGS_FPGA = -O2 -std=c++11 -Wall -L$(common_build) -lfesvr \ - -Wl,-rpath,/usr/local/lib -I $(common)/csrc -I \ - $(ROCKET_DIR)/riscv-tools/riscv-fesvr/ + -Wl,-rpath,/usr/local/lib \ + -I $(common)/csrc -I $(testchipip)/csrc -I \ + -I $(ROCKET_DIR)/riscv-tools/riscv-fesvr/ \ + -Wl,-rpath,/usr/local/lib \ $(fesvr-lib): mkdir -p $(common_build) - cd $(common_build); $(ROCKET_DIR)/riscv-tools/riscv-fesvr/configure \ - --host=arm-xilinx-linux-gnueabi; make + cd $(common_build) && \ + $(ROCKET_DIR)/riscv-tools/riscv-fesvr/configure \ + --host=arm-xilinx-linux-gnueabi && \ + make libfesvr.so -$(common_build)/$(fesvr_main): $(fesvr-lib) $(fesvr-srcs) $(fesvr-hdrs) +$(common_build)/$(fesvr-main): $(fesvr-lib) $(fesvr-srcs) $(fesvr-hdrs) $(CXX_FPGA) $(CXXFLAGS_FPGA) -o $(common_build)/$(fesvr-main) $(fesvr-srcs) -fesvr-zynq: $(common_build)/$(fesvr_main) +fesvr-zynq: $(common_build)/$(fesvr-main) clean: rm -f *.log *.jou *.str diff --git a/common/bootrom/.gitignore b/common/bootrom/.gitignore deleted file mode 100644 index 3b54c5f..0000000 --- a/common/bootrom/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.elf -*.dump diff --git a/common/bootrom/Makefile b/common/bootrom/Makefile deleted file mode 100644 index 19c1a40..0000000 --- a/common/bootrom/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -bootrom_img = bootrom.img - -GCC=riscv64-unknown-elf-gcc -OBJCOPY=riscv64-unknown-elf-objcopy -OBJDUMP=riscv64-unknown-elf-objdump - -all: $(bootrom_img) - -%.img: %.elf - $(OBJCOPY) -O binary --change-addresses=-0x1000 --only-section .text $< $@ - -%.elf: %.S linker.ld - $(GCC) -Tlinker.ld $< -nostdlib -static -o $@ - -%.dump: %.elf - $(OBJDUMP) -d $< > $@ diff --git a/common/bootrom/bootrom.S b/common/bootrom/bootrom.S deleted file mode 100644 index 86aece9..0000000 --- a/common/bootrom/bootrom.S +++ /dev/null @@ -1,35 +0,0 @@ -.text -.global _start -_start: - // This boot ROM doesn't know about any boot devices, so it just spins, - // waiting for the serial interface to load the program and interrupt it - j setup_wfi_loop // reset vector - .word 0 // reserved - .word 0 // reserved - .word 0 // pointer to config string -default_trap_vec: - j boot_trap // default trap vector - .word 0 - .word 0 - .word 0 - -setup_wfi_loop: - la a0, default_trap_vec - csrw mtvec, a0 - li a0, 8 // MIE or MSIP bit - csrw mie, a0 // set only MSIP in mie CSR - csrw mideleg, zero // no delegation - csrs mstatus, a0 // set MIE in mstatus CSR -wfi_loop: - wfi - j wfi_loop - -boot_trap: - csrr a0, mhartid - sll a0, a0, 2 // offset for hart msip - li a1, 0x2000000 // base address of clint - add a0, a0, a1 - sw zero, 0(a0) // clear the interrupt - li a0, 0x80000000 // program reset vector - csrw mepc, a0 // return from interrupt to start of user program - mret diff --git a/common/bootrom/bootrom.img b/common/bootrom/bootrom.img deleted file mode 100755 index a258726f661ada3b034f2182ef8b5eceff5a19b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104 zcmd02U|?cE0{ILM%t%}YaaINfVOG}v#R8!Q!mJGp#R9Gd#R3Kf#R{wj#S8%g`5*58 pFIIK +#define BLKDEV_NTAGS 2 + +static inline int copy_argv(int argc, char **argv, char **new_argv) +{ + int optind = 1; + int new_argc = argc; + + new_argv[0] = argv[0]; + + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '+') { + optind = i - 1; + new_argc = argc - i + 1; + break; + } + } + + for (int i = 1; i < new_argc; i++) + new_argv[i] = argv[i + optind]; + + return new_argc; +} + int main(int argc, char** argv) { - zynq_tsi_driver_t tsi_driver; - tsi_t tsi(std::vector(argv + 1, argv + argc)); + char **new_argv = (char **) malloc(sizeof(char *) * argc); + int new_argc = copy_argv(argc, argv, new_argv); + tsi_t tsi(new_argc, new_argv); - while(!tsi.done()){ - tsi_driver.poll(&tsi); - } - return tsi.exit_code(); + BlockDevice *blkdev = NULL; + NetworkDevice *netdev = NULL; + NetworkSwitch *netsw = NULL; + zynq_driver_t *driver; + + for (int i = 1; i < argc; i++) { + const char *name = NULL; + + if (strncmp(argv[i], "+blkdev=", 8) == 0) { + name = argv[i] + 8; + blkdev = new BlockDevice(name, BLKDEV_NTAGS); + } else if (strncmp(argv[i], "+netdev=", 8) == 0) { + name = argv[i] + 8; + netsw = new NetworkSwitch(name); + netdev = new NetworkDevice(random_macaddr()); + netsw->add_device(netdev); + } + } + + driver = new zynq_driver_t(&tsi, blkdev, netdev, netsw); + + while(!tsi.done()){ + driver->poll(); + } + + delete driver; + if (blkdev != NULL) + delete blkdev; + if (netdev != NULL) + delete netdev; + + return tsi.exit_code(); } diff --git a/common/csrc/zynq_driver.cc b/common/csrc/zynq_driver.cc new file mode 100644 index 0000000..ec10820 --- /dev/null +++ b/common/csrc/zynq_driver.cc @@ -0,0 +1,194 @@ +#include "zynq_driver.h" + +#include +#include +#include +#include + +#define ZYNQ_BASE_PADDR 0x43C00000L + +#define TSI_OUT_FIFO_DATA 0x00 +#define TSI_OUT_FIFO_COUNT 0x04 +#define TSI_IN_FIFO_DATA 0x08 +#define TSI_IN_FIFO_COUNT 0x0C +#define SYSTEM_RESET 0x10 +#define BLKDEV_REQ_FIFO_DATA 0x20 +#define BLKDEV_REQ_FIFO_COUNT 0x24 +#define BLKDEV_DATA_FIFO_DATA 0x28 +#define BLKDEV_DATA_FIFO_COUNT 0x2C +#define BLKDEV_RESP_FIFO_DATA 0x30 +#define BLKDEV_RESP_FIFO_COUNT 0x34 +#define BLKDEV_NSECTORS 0x38 +#define BLKDEV_MAX_REQUEST_LENGTH 0x3C +#define NET_OUT_FIFO_DATA 0x40 +#define NET_OUT_FIFO_COUNT 0x44 +#define NET_IN_FIFO_DATA 0x48 +#define NET_IN_FIFO_COUNT 0x4C +#define NET_MACADDR_LO 0x50 +#define NET_MACADDR_HI 0x54 + +#define BLKDEV_REQ_NWORDS 3 +#define BLKDEV_DATA_NWORDS 3 +#define NET_FLIT_NWORDS 3 + +zynq_driver_t::zynq_driver_t(tsi_t *tsi, BlockDevice *bdev, + NetworkDevice *netdev, NetworkSwitch *netsw) +{ + this->tsi = tsi; + this->bdev = bdev; + this->netdev = netdev; + this->netsw = netsw; + + fd = open("/dev/mem", O_RDWR|O_SYNC); + assert(fd != -1); + dev = (uint8_t *) mmap( + 0, sysconf(_SC_PAGESIZE), + PROT_READ|PROT_WRITE, MAP_SHARED, fd, ZYNQ_BASE_PADDR); + assert(dev != MAP_FAILED); + + // reset the target + write(SYSTEM_RESET, 1); + write(SYSTEM_RESET, 0); + + // set nsectors and max_request_length + if (bdev == NULL) { + write(BLKDEV_NSECTORS, 0); + write(BLKDEV_MAX_REQUEST_LENGTH, 0); + } else { + write(BLKDEV_NSECTORS, bdev->nsectors()); + write(BLKDEV_MAX_REQUEST_LENGTH, bdev->max_request_length()); + } + + // set MAC address + if (netdev != NULL) { + write_macaddr(netdev->macaddr()); + } +} + +zynq_driver_t::~zynq_driver_t() +{ + munmap(dev, sysconf(_SC_PAGESIZE)); + close(fd); +} + +uint32_t zynq_driver_t::read(int off) +{ + volatile uint32_t *ptr = (volatile uint32_t *) (this->dev + off); + return *ptr; +} + +void zynq_driver_t::write(int off, uint32_t word) +{ + volatile uint32_t *ptr = (volatile uint32_t *) (this->dev + off); + *ptr = word; +} + +struct blkdev_request zynq_driver_t::read_blkdev_request() +{ + uint32_t word; + struct blkdev_request req; + + // tag + write + word = read(BLKDEV_REQ_FIFO_DATA); + req.write = word & 0x1; + req.tag = word >> 1; + // offset, then len + req.offset = read(BLKDEV_REQ_FIFO_DATA); + req.len = read(BLKDEV_REQ_FIFO_DATA); + + return req; +} + +struct blkdev_data zynq_driver_t::read_blkdev_req_data() +{ + struct blkdev_data data; + + data.tag = read(BLKDEV_DATA_FIFO_DATA); + data.data = read(BLKDEV_DATA_FIFO_DATA) & 0xffffffffU; + data.data |= ((uint64_t) read(BLKDEV_DATA_FIFO_DATA)) << 32; + + return data; +} + +void zynq_driver_t::write_blkdev_response(struct blkdev_data &resp) +{ + write(BLKDEV_RESP_FIFO_DATA, resp.tag); + write(BLKDEV_RESP_FIFO_DATA, resp.data & 0xffffffffU); + write(BLKDEV_RESP_FIFO_DATA, resp.data >> 32); +} + +struct network_flit zynq_driver_t::read_net_out() +{ + struct network_flit flt; + + flt.data = read(NET_OUT_FIFO_DATA) & 0xffffffff; + flt.data |= ((uint64_t) read(NET_OUT_FIFO_DATA)) << 32; + flt.last = read(NET_OUT_FIFO_DATA) & 0x1; + + return flt; +} + +void zynq_driver_t::write_net_in(struct network_flit &flt) +{ + write(NET_IN_FIFO_DATA, flt.data & 0xffffffff); + write(NET_IN_FIFO_DATA, flt.data >> 32); + write(NET_IN_FIFO_DATA, flt.last); +} + +void zynq_driver_t::write_macaddr(uint64_t macaddr) +{ + write(NET_MACADDR_LO, macaddr & 0xffffffff); + write(NET_MACADDR_HI, macaddr >> 32); +} + +void zynq_driver_t::poll(void) +{ + if (tsi != NULL) { + while (read(TSI_OUT_FIFO_COUNT) > 0) { + uint32_t out_data = read(TSI_OUT_FIFO_DATA); + tsi->send_word(out_data); + } + + while (tsi->data_available() && read(TSI_IN_FIFO_COUNT) > 0) { + uint32_t in_data = tsi->recv_word(); + write(TSI_IN_FIFO_DATA, in_data); + } + + tsi->switch_to_host(); + } + + if (netdev != NULL) { + while (read(NET_OUT_FIFO_COUNT) >= NET_FLIT_NWORDS) { + struct network_flit flt = read_net_out(); + netdev->send_out(flt); + } + + while (netdev->in_valid() && read(NET_IN_FIFO_COUNT) >= NET_FLIT_NWORDS) { + struct network_flit flt = netdev->recv_in(); + write_net_in(flt); + } + + netdev->switch_to_host(); + netsw->distribute(); + netsw->switch_to_worker(); + } + + if (bdev != NULL) { + while (read(BLKDEV_REQ_FIFO_COUNT) >= BLKDEV_REQ_NWORDS) { + struct blkdev_request req = read_blkdev_request(); + bdev->send_request(req); + } + + while (read(BLKDEV_DATA_FIFO_COUNT) >= BLKDEV_DATA_NWORDS) { + struct blkdev_data data = read_blkdev_req_data(); + bdev->send_data(data); + } + + while (bdev->resp_valid() && read(BLKDEV_RESP_FIFO_COUNT) >= BLKDEV_DATA_NWORDS) { + struct blkdev_data resp = bdev->recv_response(); + write_blkdev_response(resp); + } + + bdev->switch_to_host(); + } +} diff --git a/common/csrc/zynq_driver.h b/common/csrc/zynq_driver.h new file mode 100644 index 0000000..15676b0 --- /dev/null +++ b/common/csrc/zynq_driver.h @@ -0,0 +1,37 @@ +#ifndef __ZYNQ_DRIVER_H +#define __ZYNQ_DRIVER_H + +#include "fesvr/tsi.h" +#include "blkdev.h" +#include "device.h" +#include "switch.h" +#include + +class zynq_driver_t { + public: + zynq_driver_t(tsi_t *tsi, BlockDevice *bdev, + NetworkDevice *netdev, NetworkSwitch *netsw); + ~zynq_driver_t(); + + void poll(void); + + private: + uint8_t *dev; + int fd; + tsi_t *tsi; + BlockDevice *bdev; + NetworkDevice *netdev; + NetworkSwitch *netsw; + + protected: + uint32_t read(int off); + void write(int off, uint32_t word); + struct blkdev_request read_blkdev_request(); + struct blkdev_data read_blkdev_req_data(); + void write_blkdev_response(struct blkdev_data &resp); + struct network_flit read_net_out(); + void write_net_in(struct network_flit &flt); + void write_macaddr(uint64_t macaddr); +}; + +#endif diff --git a/common/csrc/zynq_tsi_driver.cc b/common/csrc/zynq_tsi_driver.cc deleted file mode 100644 index c0d9927..0000000 --- a/common/csrc/zynq_tsi_driver.cc +++ /dev/null @@ -1,59 +0,0 @@ -#include "zynq_tsi_driver.h" - -#include -#include -#include -#include - -#define SAI_BASE_PADDR 0x43C00000L -#define SAI_OUT_FIFO_DATA 0x00 -#define SAI_OUT_FIFO_COUNT 0x04 -#define SAI_IN_FIFO_DATA 0x08 -#define SAI_IN_FIFO_COUNT 0x0C -#define SAI_SYS_RESET 0x10 - -zynq_tsi_driver_t::zynq_tsi_driver_t() -{ - fd = open("/dev/mem", O_RDWR|O_SYNC); - assert(fd != -1); - dev = (uint8_t *) mmap(0, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, SAI_BASE_PADDR); - assert(dev != MAP_FAILED); - - // reset the target - write(SAI_SYS_RESET, 1); - write(SAI_SYS_RESET, 0); -} - - -zynq_tsi_driver_t::~zynq_tsi_driver_t() -{ - munmap(dev, sysconf(_SC_PAGESIZE)); - close(fd); -} - -void zynq_tsi_driver_t::poll(tsi_t *tsi) -{ - while (read(SAI_OUT_FIFO_COUNT) > 0) { - uint32_t out_data = read(SAI_OUT_FIFO_DATA); - tsi->send_word(out_data); - } - - while (tsi->data_available() && read(SAI_IN_FIFO_COUNT) > 0) { - uint32_t in_data = tsi->recv_word(); - write(SAI_IN_FIFO_DATA, in_data); - } - - tsi->switch_to_host(); -} - -uint32_t zynq_tsi_driver_t::read(int off) -{ - volatile uint32_t *ptr = (volatile uint32_t *) (this->dev + off); - return *ptr; -} - -void zynq_tsi_driver_t::write(int off, uint32_t word) -{ - volatile uint32_t *ptr = (volatile uint32_t *) (this->dev + off); - *ptr = word; -} diff --git a/common/csrc/zynq_tsi_driver.h b/common/csrc/zynq_tsi_driver.h deleted file mode 100644 index 98e6871..0000000 --- a/common/csrc/zynq_tsi_driver.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ZYNQ_SAI_DRIVER_H -#define __ZYNQ_SAI_DRIVER_H - -#include "fesvr/tsi.h" -#include - -class zynq_tsi_driver_t { - public: - zynq_tsi_driver_t(); - ~zynq_tsi_driver_t(); - - void poll(tsi_t *tsi); - - private: - uint8_t *dev; - int fd; - - uint32_t read(int off); - void write(int off, uint32_t word); -}; - -#endif diff --git a/common/generate-pkg-mk.sh b/common/generate-pkg-mk.sh index 25e74a4..e668d04 100755 --- a/common/generate-pkg-mk.sh +++ b/common/generate-pkg-mk.sh @@ -10,7 +10,7 @@ do ${common_dir}/lib/${pkg}.stamp: \$(call lookup_scala_srcs, ${pkg_dir}) \$(rocketchip_stamp) rm -f ${pkg_dir}/lib ln -s ${common_dir}/lib ${pkg_dir}/lib - cd ${pkg_dir} && \$(SBT) package + cd ${pkg_dir} && \$(SBT) ++\$(SCALA_VERSION) package cp ${pkg_dir}/target/scala-2.11/*.jar ${common_dir}/lib touch \$@ MAKE diff --git a/common/project/build.properties b/common/project/build.properties new file mode 100644 index 0000000..64317fd --- /dev/null +++ b/common/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.15 diff --git a/common/project/build.scala b/common/project/build.scala index f5c4230..ac128a0 100644 --- a/common/project/build.scala +++ b/common/project/build.scala @@ -5,7 +5,7 @@ object BuildSettings extends Build { override lazy val settings = super.settings ++ Seq( organization := "berkeley", version := "1.2", - scalaVersion := "2.11.7", + scalaVersion := "2.11.12", parallelExecution in Global := false, traceLevel := 15, scalacOptions ++= Seq("-deprecation","-unchecked") diff --git a/common/rocketchip_wrapper.v b/common/rocketchip_wrapper.v index f9d5ca5..6014600 100644 --- a/common/rocketchip_wrapper.v +++ b/common/rocketchip_wrapper.v @@ -99,7 +99,7 @@ module rocketchip_wrapper wire [3:0] S_AXI_arcache; wire [2:0] S_AXI_arprot; wire [3:0] S_AXI_arqos; - wire [3:0] S_AXI_arregion; + //wire [3:0] S_AXI_arregion; wire S_AXI_awready; wire S_AXI_awvalid; @@ -112,7 +112,7 @@ module rocketchip_wrapper wire [3:0] S_AXI_awcache; wire [2:0] S_AXI_awprot; wire [3:0] S_AXI_awqos; - wire [3:0] S_AXI_awregion; + //wire [3:0] S_AXI_awregion; wire S_AXI_wready; wire S_AXI_wvalid; @@ -215,7 +215,7 @@ module rocketchip_wrapper .S_AXI_arprot(S_AXI_arprot), .S_AXI_arqos(S_AXI_arqos), .S_AXI_arready(S_AXI_arready), - .S_AXI_arregion(S_AXI_arregion), + .S_AXI_arregion(4'b0), .S_AXI_arsize(S_AXI_arsize), .S_AXI_arvalid(S_AXI_arvalid), // @@ -228,7 +228,7 @@ module rocketchip_wrapper .S_AXI_awprot(S_AXI_awprot), .S_AXI_awqos(S_AXI_awqos), .S_AXI_awready(S_AXI_awready), - .S_AXI_awregion(S_AXI_awregion), + .S_AXI_awregion(4'b0), .S_AXI_awsize(S_AXI_awsize), .S_AXI_awvalid(S_AXI_awvalid), // @@ -272,10 +272,10 @@ module rocketchip_wrapper .io_ps_axi_slave_aw_bits_size (M_AXI_awsize), .io_ps_axi_slave_aw_bits_burst (M_AXI_awburst), .io_ps_axi_slave_aw_bits_id (M_AXI_awid), - .io_ps_axi_slave_aw_bits_lock (), - .io_ps_axi_slave_aw_bits_prot (), - .io_ps_axi_slave_aw_bits_qos (), - .io_ps_axi_slave_aw_bits_region (), + .io_ps_axi_slave_aw_bits_lock (1'b0), + .io_ps_axi_slave_aw_bits_cache (4'b0), + .io_ps_axi_slave_aw_bits_prot (3'b0), + .io_ps_axi_slave_aw_bits_qos (4'b0), .io_ps_axi_slave_ar_ready (M_AXI_arready), .io_ps_axi_slave_ar_valid (M_AXI_arvalid), @@ -284,10 +284,10 @@ module rocketchip_wrapper .io_ps_axi_slave_ar_bits_size (M_AXI_arsize), .io_ps_axi_slave_ar_bits_burst (M_AXI_arburst), .io_ps_axi_slave_ar_bits_id (M_AXI_arid), - .io_ps_axi_slave_ar_bits_lock (), - .io_ps_axi_slave_ar_bits_prot (), - .io_ps_axi_slave_ar_bits_qos (), - .io_ps_axi_slave_ar_bits_region (), + .io_ps_axi_slave_ar_bits_lock (1'b0), + .io_ps_axi_slave_ar_bits_cache (4'b0), + .io_ps_axi_slave_ar_bits_prot (3'b0), + .io_ps_axi_slave_ar_bits_qos (4'b0), .io_ps_axi_slave_w_valid (M_AXI_wvalid), .io_ps_axi_slave_w_ready (M_AXI_wready), @@ -318,7 +318,6 @@ module rocketchip_wrapper .io_mem_axi_ar_bits_lock (S_AXI_arlock), .io_mem_axi_ar_bits_prot (S_AXI_arprot), .io_mem_axi_ar_bits_qos (S_AXI_arqos), - .io_mem_axi_ar_bits_region(S_AXI_arregion), .io_mem_axi_aw_valid (S_AXI_awvalid), .io_mem_axi_aw_ready (S_AXI_awready), .io_mem_axi_aw_bits_addr (mem_awaddr), @@ -330,7 +329,6 @@ module rocketchip_wrapper .io_mem_axi_aw_bits_lock (S_AXI_awlock), .io_mem_axi_aw_bits_prot (S_AXI_awprot), .io_mem_axi_aw_bits_qos (S_AXI_awqos), - .io_mem_axi_aw_bits_region(S_AXI_awregion), .io_mem_axi_w_valid (S_AXI_wvalid), .io_mem_axi_w_ready (S_AXI_wready), .io_mem_axi_w_bits_strb (S_AXI_wstrb), diff --git a/common/src/main/scala/Configs.scala b/common/src/main/scala/Configs.scala index 7ae2c38..d6d2d74 100644 --- a/common/src/main/scala/Configs.scala +++ b/common/src/main/scala/Configs.scala @@ -1,58 +1,66 @@ package zynq -import cde.{Parameters, Config, CDEMatchError} -import rocketchip._ -import rocket._ -import coreplex.BuildTiles -import uncore.devices.NTiles -import uncore.tilelink.TLId -import uncore.agents.NAcquireTransactors -import testchipip._ import chisel3._ +import freechips.rocketchip.config.{Parameters, Config} +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.devices.tilelink.BootROMParams +import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} +import freechips.rocketchip.tile.{RocketTileParams, BuildCore, XLen} +import testchipip._ -class WithZynqAdapter extends Config( - (pname, site, here) => pname match { - case SerialInterfaceWidth => 32 - case SerialFIFODepth => 16 - case ResetCycles => 10 - case BuildSerialDriver => - (p: Parameters) => Module(new SimSerialWrapper(p(SerialInterfaceWidth))) - case _ => throw new CDEMatchError - }) +class WithBootROM extends Config((site, here, up) => { + case BootROMParams => BootROMParams( + contentFileName = s"../testchipip/bootrom/bootrom.rv${site(XLen)}.img") +}) -class WithSmallCores extends Config( - (pname, site, here) => pname match { - case MulDivKey => Some(MulDivConfig()) - case FPUKey => None - case NTLBEntries => 4 - case BtbKey => BtbParameters(nEntries = 0) - case NAcquireTransactors => 2 - case _ => throw new CDEMatchError - }, - knobValues = { - case "L1D_SETS" => 64 - case "L1D_WAYS" => 1 - case "L1I_SETS" => 64 - case "L1I_WAYS" => 1 - case "L1D_MSHRS" => 0 - case _ => throw new CDEMatchError - }) +class WithZynqAdapter extends Config((site, here, up) => { + case SerialFIFODepth => 16 + case ResetCycles => 10 + case ZynqAdapterBase => BigInt(0x43C00000L) + case ExtMem => up(ExtMem, site).copy(idBits = 6) + case ExtIn => up(ExtIn, site).copy(beatBytes = 4, idBits = 12) + case BlockDeviceKey => BlockDeviceConfig(nTrackers = 2) + case BlockDeviceFIFODepth => 16 + case NetworkFIFODepth => 16 +}) -class ZynqConfig extends Config(new WithZynqAdapter ++ new DefaultFPGAConfig) -class ZynqSmallConfig extends Config(new WithSmallCores ++ new ZynqConfig) +class WithNMediumCores(n: Int) extends Config((site, here, up) => { + case RocketTilesKey => { + val medium = RocketTileParams( + core = RocketCoreParams(mulDiv = Some(MulDivParams( + mulUnroll = 8, + mulEarlyOut = true, + divEarlyOut = true)), + fpu = None), + dcache = Some(DCacheParams( + rowBits = site(SystemBusKey).beatBytes*8, + nSets = 64, + nWays = 1, + nTLBEntries = 4, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes))), + icache = Some(ICacheParams( + rowBits = site(SystemBusKey).beatBytes*8, + nSets = 64, + nWays = 1, + nTLBEntries = 4, + blockBytes = site(CacheBlockBytes)))) + List.fill(n)(medium) ++ up(RocketTilesKey, site) + } +}) -class WithIntegrationTest extends Config( - (pname, site, here) => pname match { - case BuildSerialDriver => - (p: Parameters) => Module(new IntegrationTestSerial()(p)) - case BuildTiles => Seq.fill(site(NTiles)) { - (_reset: Bool, p: Parameters) => Module(new DummyTile()(p.alterPartial({ - case TileId => 0 - case TLId => "L1toL2" - case NUncachedTileLinkPorts => 1 - }))) - } - case _ => throw new CDEMatchError - }) +class DefaultConfig extends Config( + new WithBootROM ++ new freechips.rocketchip.system.DefaultConfig) +class DefaultMediumConfig extends Config( + new WithBootROM ++ new WithNMediumCores(1) ++ + new freechips.rocketchip.system.BaseConfig) +class DefaultSmallConfig extends Config( + new WithBootROM ++ new freechips.rocketchip.system.DefaultSmallConfig) -class IntegrationTestConfig extends Config(new WithIntegrationTest ++ new ZynqConfig) +class ZynqConfig extends Config(new WithZynqAdapter ++ new DefaultConfig) +class ZynqMediumConfig extends Config(new WithZynqAdapter ++ new DefaultMediumConfig) +class ZynqSmallConfig extends Config(new WithZynqAdapter ++ new DefaultSmallConfig) + +class ZynqFPGAConfig extends Config(new WithoutTLMonitors ++ new ZynqConfig) +class ZynqMediumFPGAConfig extends Config(new WithoutTLMonitors ++ new ZynqMediumConfig) +class ZynqSmallFPGAConfig extends Config(new WithoutTLMonitors ++ new ZynqSmallConfig) diff --git a/common/src/main/scala/Drivers.scala b/common/src/main/scala/Drivers.scala new file mode 100644 index 0000000..b84fe9c --- /dev/null +++ b/common/src/main/scala/Drivers.scala @@ -0,0 +1,273 @@ +package zynq + +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ +import testchipip._ +import testchipip.SerialAdapter._ + +class InFIFODriver(name: String, addr: BigInt, maxSpace: Int) + (implicit p: Parameters) extends LazyModule { + + val node = TLHelper.makeClientNode( + name = name, sourceId = IdRange(0, 1)) + + lazy val module = new LazyModuleImp(this) { + val (tl, edge) = node.out(0) + val dataBits = edge.bundle.dataBits + val beatBytes = dataBits / 8 + + val io = IO(new Bundle { + val in = Flipped(Decoupled(UInt(dataBits.W))) + }) + + val timeout = 64 + val timer = RegInit(0.U(log2Ceil(timeout).W)) + val space = RegInit(0.U(log2Ceil(maxSpace + 1).W)) + + val (s_start :: s_read_acq :: s_read_gnt :: + s_req :: s_write_acq :: s_write_gnt :: Nil) = Enum(6) + val state = RegInit(s_start) + val data = Reg(UInt(dataBits.W)) + + val put_acq = edge.Put( + fromSource = 0.U, + toAddress = addr.U, + lgSize = log2Ceil(beatBytes).U, + data = data)._2 + + val get_acq = edge.Get( + fromSource = 0.U, + toAddress = (addr + beatBytes).U, + lgSize = log2Ceil(beatBytes).U)._2 + + tl.a.valid := state.isOneOf(s_read_acq, s_write_acq) + tl.a.bits := Mux(state === s_read_acq, get_acq, put_acq) + tl.d.ready := state.isOneOf(s_read_gnt, s_write_gnt) + io.in.ready := state === s_req + + when (state === s_start) { + when (space =/= 0.U) { + state := s_req + } .elsewhen (timer === 0.U) { + timer := (timeout - 1).U + state := s_read_acq + } .otherwise { + timer := timer - 1.U + } + } + + when (state === s_read_acq && tl.a.ready) { state := s_read_gnt } + when (state === s_read_gnt && tl.d.valid) { + space := tl.d.bits.data + state := s_start + } + + when (io.in.fire()) { + data := io.in.bits + space := space - 1.U + state := s_write_acq + } + + when (state === s_write_acq && tl.a.ready) { state := s_write_gnt } + when (state === s_write_gnt && tl.d.valid) { state := s_start } + } +} + +class OutFIFODriver(name: String, addr: BigInt, maxCount: Int) + (implicit p: Parameters) extends LazyModule { + + val node = TLHelper.makeClientNode( + name = name, sourceId = IdRange(0, 1)) + + lazy val module = new LazyModuleImp(this) { + val (tl, edge) = node.out(0) + val dataBits = edge.bundle.dataBits + val beatBytes = dataBits / 8 + val lgSize = log2Ceil(beatBytes) + + val io = IO(new Bundle { + val out = Decoupled(UInt(dataBits.W)) + }) + + val timeout = 64 + val timer = RegInit(0.U(log2Ceil(timeout).W)) + val count = RegInit(0.U(log2Ceil(maxCount + 1).W)) + val (s_start :: s_count_acq :: s_count_gnt :: + s_fifo_acq :: s_fifo_gnt :: Nil) = Enum(5) + val state = RegInit(s_start) + + tl.a.valid := state.isOneOf(s_count_acq, s_fifo_acq) + tl.a.bits := edge.Get( + fromSource = 0.U, + toAddress = Mux(state === s_count_acq, (addr + beatBytes).U, addr.U), + lgSize = lgSize.U)._2 + + tl.d.ready := + (state === s_count_gnt) || + (state === s_fifo_gnt && io.out.ready) + + io.out.valid := state === s_fifo_gnt && tl.d.valid + io.out.bits := tl.d.bits.data + + when (state === s_start) { + when (count =/= 0.U) { + state := s_fifo_acq + } .elsewhen (timer === 0.U) { + timer := (timeout - 1).U + state := s_count_acq + } .otherwise { + timer := timer - 1.U + } + } + + when (tl.a.fire()) { + state := Mux(state === s_count_acq, s_count_gnt, s_fifo_gnt) + } + + when (tl.d.fire()) { + count := Mux(state === s_count_gnt, tl.d.bits.data, count - 1.U) + state := s_start + } + } +} + +class SetRegisterDriver(name: String, addr: BigInt, n: Int) + (implicit p: Parameters) extends LazyModule { + + val node = TLHelper.makeClientNode( + name = name, sourceId = IdRange(0, 1)) + + lazy val module = new LazyModuleImp(this) { + val (tl, edge) = node.out(0) + val dataBits = edge.bundle.dataBits + val beatBytes = dataBits / 8 + val lgSize = log2Ceil(beatBytes) + + val io = IO(new Bundle { + val values = Input(Vec(n, UInt(dataBits.W))) + }) + + val (s_start :: s_write_acq :: s_write_gnt :: s_wait :: Nil) = Enum(4) + val state = RegInit(s_start) + val values = Reg(Vec(n, UInt(dataBits.W))) + + val value_diff = Cat(io.values.zip(values).map { + case (iovalue, value) => iovalue != value + }.reverse) + val value_set = RegInit(UInt(n.W), ~0.U(n.W)) + val value_set_oh = PriorityEncoderOH(value_set) + val value_idx = OHToUInt(value_set_oh) + + tl.a.valid := state === s_write_acq + tl.a.bits := edge.Put( + fromSource = 0.U, + toAddress = addr.U + (value_idx << lgSize.U), + lgSize = lgSize.U, + data = values(value_idx))._2 + tl.d.ready := state === s_write_gnt + + when (state === s_start) { + state := s_write_acq + for (i <- 0 until n) { + when (value_set(i)) { + values(i) := io.values(i) + } + } + } + when (tl.a.fire()) { state := s_write_gnt } + when (tl.d.fire()) { + value_set := value_set & ~value_set_oh + state := s_wait + } + when (state === s_wait) { + when (value_set.orR) { + state := s_write_acq + } .elsewhen (value_diff.orR) { + value_set := value_diff + state := s_start + } + } + } +} + +class SerialDriver(implicit p: Parameters) extends LazyModule { + val base = p(ZynqAdapterBase) + val depth = p(SerialFIFODepth) + + val node = TLIdentityNode() + val xbar = LazyModule(new TLXbar) + val outdrv = LazyModule(new OutFIFODriver("serial-out", base, depth)) + val indrv = LazyModule(new InFIFODriver("serial-in", base + BigInt(8), depth)) + + xbar.node := outdrv.node + xbar.node := indrv.node + node := xbar.node + + lazy val module = new LazyModuleImp(this) { + val (tl, edge) = node.out(0) + require(edge.bundle.dataBits == SERIAL_IF_WIDTH) + + val io = IO(new Bundle { + val serial = new SerialIO(SERIAL_IF_WIDTH) + }) + + indrv.module.io.in <> io.serial.in + io.serial.out <> outdrv.module.io.out + } +} + +class ResetDriver(implicit p: Parameters) extends LazyModule { + val base = p(ZynqAdapterBase) + + val node = TLIdentityNode() + val driver = LazyModule(new SetRegisterDriver("reset", base + BigInt(0x10), 1)) + + node := driver.node + + lazy val module = new LazyModuleImp(this) { + driver.module.io.values(0) := 0.U + } +} + +class BlockDeviceDriver(implicit p: Parameters) extends LazyModule { + val base = p(ZynqAdapterBase) + val depth = p(BlockDeviceFIFODepth) + + val node = TLIdentityNode() + val xbar = LazyModule(new TLXbar) + val reqdrv = LazyModule(new OutFIFODriver( + "bdev-req", base + BigInt(0x20), depth)) + val datadrv = LazyModule(new OutFIFODriver( + "bdev-data", base + BigInt(0x28), depth)) + val respdrv = LazyModule(new InFIFODriver( + "bdev-resp", base + BigInt(0x30), depth)) + val infodrv = LazyModule(new SetRegisterDriver( + "bdev-info", base + BigInt(0x38), 2)) + + xbar.node := reqdrv.node + xbar.node := datadrv.node + xbar.node := respdrv.node + xbar.node := infodrv.node + node := xbar.node + + lazy val module = new LazyModuleImp(this) { + val (tl, edge) = node.out(0) + val dataBits = edge.bundle.dataBits + + val io = IO(new Bundle { + val bdev = new BlockDeviceIO + }) + + val desser = Module(new BlockDeviceDesser(dataBits)) + io.bdev <> desser.io.bdev + desser.io.ser.req <> reqdrv.module.io.out + desser.io.ser.data <> datadrv.module.io.out + respdrv.module.io.in <> desser.io.ser.resp + infodrv.module.io.values := Seq( + io.bdev.info.nsectors, io.bdev.info.max_req_len) + } +} diff --git a/common/src/main/scala/Generator.scala b/common/src/main/scala/Generator.scala index d46afe8..e002ae1 100644 --- a/common/src/main/scala/Generator.scala +++ b/common/src/main/scala/Generator.scala @@ -1,6 +1,6 @@ package zynq -object Generator extends util.GeneratorApp { - val longName = names.topModuleClass + "." + names.configs +object Generator extends testchipip.GeneratorApp { + override lazy val longName = names.topModuleClass + "." + names.configs generateFirrtl } diff --git a/common/src/main/scala/Serdes.scala b/common/src/main/scala/Serdes.scala new file mode 100644 index 0000000..ca9909d --- /dev/null +++ b/common/src/main/scala/Serdes.scala @@ -0,0 +1,162 @@ +package zynq + +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.config.Parameters +import testchipip._ + +class BlockDeviceSerialIO(w: Int) extends Bundle { + val req = Decoupled(UInt(w.W)) + val data = Decoupled(UInt(w.W)) + val resp = Flipped(Decoupled(UInt(w.W))) + + override def cloneType = new BlockDeviceSerialIO(w).asInstanceOf[this.type] +} + +class BlockDeviceSerdes(w: Int)(implicit p: Parameters) + extends BlockDeviceModule { + val io = IO(new Bundle { + val bdev = Flipped(new BlockDeviceIO) + val ser = new BlockDeviceSerialIO(w) + }) + + require(w >= sectorBits) + require(w >= (tagBits + 1)) + require(dataBitsPerBeat % w == 0) + + val reqWords = 3 + val dataWords = 1 + dataBitsPerBeat / w + + val req = Reg(new BlockDeviceRequest) + val data = Reg(new BlockDeviceData) + val resp = Reg(new BlockDeviceData) + + val (req_idx, req_done) = Counter(io.ser.req.fire(), reqWords) + val req_send = RegInit(false.B) + + val (data_idx, data_done) = Counter(io.ser.data.fire(), dataWords) + val data_send = RegInit(false.B) + + val (resp_idx, resp_done) = Counter(io.ser.resp.fire(), dataWords) + val resp_send = RegInit(false.B) + + when (io.bdev.req.fire()) { + req := io.bdev.req.bits + req_send := true.B + } + when (req_done) { req_send := false.B } + + when (io.bdev.data.fire()) { + data := io.bdev.data.bits + data_send := true.B + } + when (data_done) { data_send := false.B } + + when (io.ser.resp.fire()) { + when (resp_idx === 0.U) { + resp.tag := io.ser.resp.bits + resp.data := 0.U + } .otherwise { + val shift_amt = (resp_idx - 1.U) << log2Ceil(w).U + resp.data := resp.data | (io.ser.resp.bits << shift_amt) + } + } + when (resp_done) { resp_send := true.B } + when (io.bdev.resp.fire()) { resp_send := false.B } + + io.bdev.req.ready := !req_send + io.bdev.data.ready := !data_send + io.bdev.resp.valid := resp_send + io.bdev.resp.bits := resp + io.bdev.info := DontCare + + val req_vec = Vec(Cat(req.tag, req.write), req.offset, req.len) + val data_vec = Vec(data.tag +: Seq.tabulate(dataBitsPerBeat/w) { + i => data.data((i + 1) * w - 1, i * w) + }) + + io.ser.req.valid := req_send + io.ser.req.bits := req_vec(req_idx) + io.ser.data.valid := data_send + io.ser.data.bits := data_vec(data_idx) + io.ser.resp.ready := !resp_send +} + +class BlockDeviceDesser(w: Int)(implicit p: Parameters) extends BlockDeviceModule { + val io = IO(new Bundle { + val bdev = new BlockDeviceIO + val ser = Flipped(new BlockDeviceSerialIO(w)) + }) + + require(w >= sectorBits) + require(w >= (tagBits + 1)) + require(dataBitsPerBeat % w == 0) + + val reqWords = 3 + val dataWords = 1 + dataBitsPerBeat / w + + val req = Reg(new BlockDeviceRequest) + val data = Reg(new BlockDeviceData) + val resp = Reg(new BlockDeviceData) + + val (req_idx, req_done) = Counter(io.ser.req.fire(), reqWords) + val req_send = RegInit(false.B) + + val (data_idx, data_done) = Counter(io.ser.data.fire(), dataWords) + val data_send = RegInit(false.B) + + val (resp_idx, resp_done) = Counter(io.ser.resp.fire(), dataWords) + val resp_send = RegInit(false.B) + + when (io.ser.req.fire()) { + switch (req_idx) { + is (0.U) { + req.write := io.ser.req.bits(0) + req.tag := io.ser.req.bits(tagBits, 1) + } + is (1.U) { + req.offset := io.ser.req.bits + } + is (2.U) { + req.len := io.ser.req.bits + } + } + } + when (req_done) { req_send := true.B } + when (io.bdev.req.fire()) { + req_send := false.B + } + + when (io.ser.data.fire()) { + when (data_idx === 0.U) { + data.tag := io.ser.data.bits + data.data := 0.U + } .otherwise { + val shift_amt = (data_idx - 1.U) << log2Ceil(w).U + data.data := data.data | (io.ser.data.bits << shift_amt) + } + } + when (data_done) { data_send := true.B } + when (io.bdev.data.fire()) { data_send := false.B } + + when (io.bdev.resp.fire()) { + resp := io.bdev.resp.bits + resp_send := true.B + } + when (resp_done) { resp_send := false.B } + + io.bdev.req.valid := req_send + io.bdev.req.bits := req + io.bdev.data.valid := data_send + io.bdev.data.bits := data + io.bdev.resp.ready := !resp_send + + val resp_vec = Vec(resp.tag +: Seq.tabulate(dataBitsPerBeat/w) { + i => resp.data((i + 1) * w - 1, i * w) + }) + + io.ser.req.ready := !req_send + io.ser.data.ready := !data_send + io.ser.resp.valid := resp_send + io.ser.resp.bits := resp_vec(resp_idx) +} diff --git a/common/src/main/scala/SerialDriver.scala b/common/src/main/scala/SerialDriver.scala deleted file mode 100644 index dcb5e83..0000000 --- a/common/src/main/scala/SerialDriver.scala +++ /dev/null @@ -1,160 +0,0 @@ -package zynq - -import chisel3._ -import chisel3.util._ -import junctions._ -import junctions.NastiConstants._ -import cde.{Parameters, Field} -import _root_.util._ -import testchipip._ -import rocket.XLen - -case object BuildSerialDriver extends Field[Parameters => SerialDriver] - -class IntegrationTestDriver(implicit p: Parameters) extends NastiModule()(p) { - val io = IO(new Bundle { - val nasti = new NastiIO - val exit = Output(Bool()) - }) - - require(p(XLen) == 64) - require(p(SerialInterfaceWidth) == 32) - require(nastiXDataBits == 32) - - val startAddr = 0x80000000L - val testLen = 0x40 - val readAddr = Reg(UInt(4.W)) - - val (cmd_read :: cmd_write :: Nil) = Enum(2) - - val (s_idle :: s_write_addr :: s_write_data :: s_write_resp :: - s_read_addr :: s_read_data :: s_done :: Nil) = Enum(7) - val state = Reg(init = s_idle) - - val testData = Vec(Seq.tabulate(testLen)(i => (i * 3).U)) - val idx = Reg(UInt(32.W)) - - val writeData = MuxCase(0.U, Seq( - (idx === 0.U) -> cmd_write, - (idx === 1.U) -> startAddr.U, - (idx === 3.U) -> (testLen - 1).U, - (idx >= 5.U && idx < (5 + testLen).U) -> testData(idx - 5.U), - (idx === (5 + testLen).U) -> cmd_read, - (idx === (6 + testLen).U) -> startAddr.U, - (idx === (8 + testLen).U) -> (testLen - 1).U)) - - val lastWriteIdx = 9 + testLen - - when (state === s_idle) { - idx := 0.U - readAddr := 0x0.U - state := s_write_addr - } - - when (io.nasti.aw.fire()) { - state := s_write_data - } - - when (io.nasti.w.fire()) { - state := s_write_resp - } - - when (io.nasti.b.fire()) { - when (idx === lastWriteIdx.U) { - idx := 0.U - state := s_read_addr - } .otherwise { - idx := idx + 1.U - state := s_write_addr - } - } - - when (io.nasti.ar.fire()) { - state := s_read_data - } - - when (io.nasti.r.fire()) { - switch (readAddr) { - is (0x0.U) { - when (idx === (testLen - 1).U) { - state := s_read_addr - readAddr := 0x4.U - } .otherwise { - idx := idx + 1.U - state := s_read_addr - } - } - is (0x4.U) { readAddr := 0xC.U; state := s_read_addr } - is (0xC.U) { state := s_done } - } - } - - io.exit := (state === s_done) - - io.nasti.aw.valid := (state === s_write_addr) - io.nasti.aw.bits := NastiWriteAddressChannel( - id = 0.U, - addr = 0x43C00008L.U, - size = 2.U) - - io.nasti.w.valid := (state === s_write_data) - io.nasti.w.bits := NastiWriteDataChannel(data = writeData) - - io.nasti.ar.valid := (state === s_read_addr) - io.nasti.ar.bits := NastiReadAddressChannel( - id = 0.U, - addr = 0x43C00000L.U | readAddr, - size = 2.U) - - io.nasti.b.ready := (state === s_write_resp) - io.nasti.r.ready := (state === s_read_data) - - val expectedData = MuxLookup(readAddr, 0.U, Seq( - 0xC.U -> p(SerialFIFODepth).U, - 0x4.U -> 0.U, - 0x0.U -> testData(idx))) - - assert(!io.nasti.b.valid || io.nasti.b.bits.resp === RESP_OKAY, - "Integration test write error") - assert(!io.nasti.r.valid || io.nasti.r.bits.data === expectedData, - "Integration test data mismatch") -} - -class IntegrationTestReset(implicit p: Parameters) extends Module { - val io = IO(new Bundle { - val nasti = new NastiIO - }) - - val (s_idle :: s_write_addr :: s_write_data :: s_done :: Nil) = Enum(4) - val state = Reg(init = s_idle) - - when (state === s_idle) { state := s_write_addr } - when (io.nasti.aw.fire()) { state := s_write_data } - when (io.nasti.w.fire()) { state := s_done } - - io.nasti.aw.valid := state === s_write_addr - io.nasti.aw.bits := NastiWriteAddressChannel( - id = 0.U, - addr = 0x43C00010L.U, - size = 2.U) - - io.nasti.w.valid := state === s_write_data - io.nasti.w.bits := NastiWriteDataChannel(data = 0.U) - - io.nasti.b.ready := (state === s_done) - io.nasti.ar.valid := false.B - io.nasti.r.ready := false.B -} - -class IntegrationTestSerial(implicit p: Parameters) extends SerialDriver(p(SerialInterfaceWidth)) { - val testParams = AdapterParams(p) - val slave = Module(new ZynqAXISlave(2)(testParams)) - val driver = Module(new IntegrationTestDriver()(testParams)) - val resetter = Module(new IntegrationTestReset()(testParams)) - - io.exit := driver.io.exit - slave.io.nasti(0) <> driver.io.nasti - slave.io.nasti(1) <> resetter.io.nasti - slave.io.serial <> io.serial - driver.reset := slave.io.sys_reset -} diff --git a/common/src/main/scala/TestHarness.scala b/common/src/main/scala/TestHarness.scala index 06495ea..85275c8 100644 --- a/common/src/main/scala/TestHarness.scala +++ b/common/src/main/scala/TestHarness.scala @@ -2,47 +2,75 @@ package zynq import chisel3._ import chisel3.util.Queue -import cde.Parameters -import diplomacy.LazyModule -import rocketchip._ -import rocket.Tile -import uncore.tilelink.{ClientTileLinkIO, ClientUncachedTileLinkIO} -import uncore.coherence.ClientMetadata -import junctions.SerialIO +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.subsystem.ExtIn +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import freechips.rocketchip.tilelink._ +import testchipip._ +import testchipip.SerialAdapter._ class TestHarness(implicit val p: Parameters) extends Module { val io = IO(new Bundle { val success = Output(Bool()) }) - val dut = LazyModule(new FPGAZynqTop(p)).module - val mem = Module(new SimAXIMem(BigInt(p(ExtMemSize)))) - val ser = p(BuildSerialDriver)(p) + val config = p(ExtIn) + val driver = Module(LazyModule(new TestHarnessDriver).module) + val dut = Module(LazyModule(new FPGAZynqTop).module) - mem.io.axi <> dut.io.mem_axi.head - ser.io.serial <> dut.io.serial - io.success := ser.io.exit + dut.reset := driver.io.sys_reset + dut.debug := DontCare + dut.tieOffInterrupts() + dut.dontTouchPorts() + dut.connectSimAXIMem() + + driver.io.serial <> dut.serial + driver.io.bdev <> dut.bdev + io.success := driver.io.success } -class DummyTile(implicit p: Parameters) extends Tile()(p) { - def tieOff(cached: ClientTileLinkIO) { - cached.acquire.valid := false.B - cached.grant.ready := false.B - cached.finish.valid := false.B +class TestHarnessDriver(implicit p: Parameters) extends LazyModule { + val xbar = LazyModule(new TLXbar) + val config = p(ExtIn) + val base = p(ZynqAdapterBase) - val prb = Queue(cached.probe) - cached.release.valid := prb.valid - prb.ready := cached.release.ready - cached.release.bits := ClientMetadata.onReset.makeRelease(prb.bits) + val zynq = LazyModule(new ZynqAdapterCore(base, config.beatBytes)) + val converter = LazyModule(new TLToAXI4) + + val serDriver = LazyModule(new SerialDriver) + val resetDriver = LazyModule(new ResetDriver) + val blkdevDriver = LazyModule(new BlockDeviceDriver) + + xbar.node := serDriver.node + xbar.node := resetDriver.node + xbar.node := blkdevDriver.node + converter.node := xbar.node + zynq.node := converter.node + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val serial = Flipped(new SerialIO(SERIAL_IF_WIDTH)) + val bdev = Flipped(new BlockDeviceIO) + val sys_reset = Output(Bool()) + val success = Output(Bool()) + }) + + val simSerial = Module(new SimSerial(SERIAL_IF_WIDTH)) + val simBlockDev = Module(new SimBlockDevice) + simSerial.io.clock := clock + simSerial.io.reset := reset + simBlockDev.io.clock := clock + simBlockDev.io.reset := reset + serDriver.module.reset := zynq.module.io.sys_reset + blkdevDriver.module.reset := zynq.module.io.sys_reset + + zynq.module.io.serial <> io.serial + simSerial.io.serial <> serDriver.module.io.serial + zynq.module.io.bdev <> io.bdev + simBlockDev.io.bdev <> blkdevDriver.module.io.bdev + + io.sys_reset := zynq.module.io.sys_reset + io.success := simSerial.io.exit } - - def tieOff(uncached: ClientUncachedTileLinkIO) { - uncached.acquire.valid := false.B - uncached.grant.ready := false.B - } - - io.cached.foreach(tieOff(_)) - io.uncached.foreach(tieOff(_)) - - require(io.slave.isEmpty) } diff --git a/common/src/main/scala/Top.scala b/common/src/main/scala/Top.scala index 3f734d6..2e61440 100644 --- a/common/src/main/scala/Top.scala +++ b/common/src/main/scala/Top.scala @@ -1,242 +1,56 @@ - package zynq import chisel3._ -import chisel3.util._ -import diplomacy.{LazyModule, LazyModuleImp} -import junctions._ -import junctions.NastiConstants._ -import cde.{Parameters, Field} -import rocketchip._ -import uncore.devices.{DebugBusIO} -import uncore.tilelink.ClientUncachedTileLinkIOCrossbar +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.util.DontTouch import testchipip._ -import coreplex.BaseCoreplexBundle -import java.io.File - -case object SerialFIFODepth extends Field[Int] -case object ResetCycles extends Field[Int] +case object ZynqAdapterBase extends Field[BigInt] class Top(implicit val p: Parameters) extends Module { - val io = IO(new Bundle { - val ps_axi_slave = Flipped(new NastiIO()(AdapterParams(p))) - val mem_axi = new NastiIO - }) + val address = p(ZynqAdapterBase) + val config = p(ExtIn) + val target = Module(LazyModule(new FPGAZynqTop).module) + val adapter = Module(LazyModule(new ZynqAdapter(address, config)).module) - val target = LazyModule(new FPGAZynqTop(p)).module - val slave = Module(new ZynqAXISlave(1)(AdapterParams(p))) - - require(target.io.mem_axi.size == 1) - require(target.io.mem_ahb.isEmpty) - require(target.io.mem_tl.isEmpty) - require(target.io.mem_clk.isEmpty) - require(target.io.mem_rst.isEmpty) - - io.mem_axi <> target.io.mem_axi.head - - slave.io.nasti.head <> io.ps_axi_slave - slave.io.serial <> target.io.serial - target.reset := slave.io.sys_reset -} - -class ZynqAXISlave(nPorts: Int)(implicit p: Parameters) extends Module { - val io = IO(new Bundle { - val nasti = Flipped(Vec(nPorts, new NastiIO())) - val sys_reset = Output(Bool()) - val serial = Flipped(new SerialIO(p(SerialInterfaceWidth))) - }) - - def routeSel(addr: UInt): UInt = { - // 0x00 - 0x0F go to FIFO - // 0x10 goes to Reset generator - UIntToOH(addr(4)) - } - - val xbar = Module(new NastiCrossbar(nPorts, 2, routeSel _)) - val fifo = Module(new NastiFIFO) - val resetter = Module(new ResetController) - - xbar.io.masters <> io.nasti - fifo.io.nasti <> xbar.io.slaves(0) - fifo.io.serial <> io.serial - resetter.io.nasti <> xbar.io.slaves(1) - io.sys_reset := resetter.io.sys_reset -} - -class ResetController(implicit p: Parameters) extends NastiModule()(p) { - val io = IO(new Bundle { - val nasti = Flipped(new NastiIO()) - val sys_reset = Output(Bool()) - }) - - val reg_reset = Reg(init = true.B) - - val readId = Reg(UInt(nastiXIdBits.W)) - - val r_addr :: r_data :: Nil = Enum(2) - val r_state = Reg(init = r_addr) - - io.nasti.ar.ready := r_state === r_addr - io.nasti.r.valid := r_state === r_data - io.nasti.r.bits := NastiReadDataChannel( - id = readId, - data = reg_reset) - - when (io.nasti.ar.fire()) { - readId := io.nasti.ar.bits.id - r_state := r_data - } - - when (io.nasti.r.fire()) { - r_state := r_addr - } - - val writeId = Reg(UInt(nastiXIdBits.W)) - - val w_addr :: w_data :: w_resp :: Nil = Enum(3) - val w_state = Reg(init = w_addr) - val timer = Reg(init = (p(ResetCycles) - 1).U) - - // Make sure reset period lasts for a certain number of cycles - when (timer =/= 0.U) { timer := timer - 1.U } - - when (io.nasti.aw.fire()) { - writeId := io.nasti.aw.bits.id - w_state := w_data - } - - when (io.nasti.w.fire()) { - timer := (p(ResetCycles) - 1).U - reg_reset := io.nasti.w.bits.data(0) - w_state := w_resp - } - - when (io.nasti.b.fire()) { - w_state := w_addr - } - - io.nasti.aw.ready := w_state === w_addr - io.nasti.w.ready := w_state === w_data - io.nasti.b.valid := w_state === w_resp && timer === 0.U - io.nasti.b.bits := NastiWriteResponseChannel(id = writeId) - - io.sys_reset := reg_reset -} - -class NastiFIFO(implicit p: Parameters) extends NastiModule()(p) { - val w = p(SerialInterfaceWidth) - val depth = p(SerialFIFODepth) + require(target.mem_axi4.size == 1) val io = IO(new Bundle { - val nasti = Flipped(new NastiIO()) - val serial = Flipped(new SerialIO(w)) + val ps_axi_slave = Flipped(adapter.axi.cloneType) + val mem_axi = target.mem_axi4.head.cloneType }) - require(nastiXDataBits == 32) - require(nastiXDataBits == w) + io.mem_axi <> target.mem_axi4.head + adapter.axi <> io.ps_axi_slave + adapter.io.serial <> target.serial + adapter.io.bdev <> target.bdev - val outq = Module(new Queue(UInt(w.W), depth)) - val inq = Module(new Queue(UInt(w.W), depth)) - val writing = Reg(init = false.B) - val reading = Reg(init = false.B) - val responding = Reg(init = false.B) - val len = Reg(UInt(nastiXLenBits.W)) - val bid = Reg(UInt(nastiXIdBits.W)) - val rid = Reg(UInt(nastiXIdBits.W)) - - io.serial.in <> inq.io.deq - outq.io.enq <> io.serial.out - - val nRegisters = 3 - val addrLSB = log2Up(w / 8) - val addrMSB = addrLSB + log2Up(nRegisters) - 1 - val araddr = io.nasti.ar.bits.addr(addrMSB, addrLSB) - val awaddr = io.nasti.aw.bits.addr(addrMSB, addrLSB) - val raddr = Reg(araddr.cloneType) - val waddr = Reg(awaddr.cloneType) - - inq.io.enq.valid := io.nasti.w.valid && writing && (waddr === 2.U) - io.nasti.w.ready := (inq.io.enq.ready || waddr =/= 2.U) && writing - inq.io.enq.bits := io.nasti.w.bits.data - - /** - * Address Map - * 0x00 - out FIFO data - * 0x04 - out FIFO data available (words) - * 0x08 - in FIFO data - * 0x0C - in FIFO space available (words) - */ - io.nasti.r.valid := reading && (raddr =/= 0.U || outq.io.deq.valid) - outq.io.deq.ready := reading && raddr === 0.U && io.nasti.r.ready - io.nasti.r.bits := NastiReadDataChannel( - id = rid, - data = MuxLookup(raddr, 0.U, Seq( - 0.U -> outq.io.deq.bits, - 1.U -> outq.io.count, - 3.U -> (depth.U - inq.io.count))), - last = len === 0.U) - - io.nasti.aw.ready := !writing && !responding - io.nasti.ar.ready := !reading - io.nasti.b.valid := responding - io.nasti.b.bits := NastiWriteResponseChannel( - id = bid, - // writing to anything other that the in FIFO is an error - resp = Mux(waddr === 2.U, RESP_OKAY, RESP_SLVERR)) - - when (io.nasti.aw.fire()) { - writing := true.B - waddr := awaddr - bid := io.nasti.aw.bits.id - } - when (io.nasti.w.fire() && io.nasti.w.bits.last) { - writing := false.B - responding := true.B - } - when (io.nasti.b.fire()) { responding := false.B } - when (io.nasti.ar.fire()) { - len := io.nasti.ar.bits.len - rid := io.nasti.ar.bits.id - raddr := araddr - reading := true.B - } - when (io.nasti.r.fire()) { - len := len - 1.U - when (len === 0.U) { reading := false.B } - } - - def addressOK(chan: NastiAddressChannel): Bool = - (chan.len === 0.U || chan.burst === BURST_FIXED) && - chan.size === log2Up(w/8).U && - chan.addr(log2Up(nastiWStrobeBits)-1, 0) === 0.U - - def dataOK(chan: NastiWriteDataChannel): Bool = - chan.strb(w/8-1, 0).andR - - assert(!io.nasti.aw.valid || addressOK(io.nasti.aw.bits), - s"NastiFIFO aw can only accept aligned fixed bursts of size $w") - - assert(!io.nasti.ar.valid || addressOK(io.nasti.ar.bits), - s"NastiFIFO ar can only accept aligned fixed bursts of size $w") - - assert(!io.nasti.w.valid || dataOK(io.nasti.w.bits), - s"NastiFIFO w cannot accept partial writes") + target.debug := DontCare + target.tieOffInterrupts() + target.dontTouchPorts() + target.reset := adapter.io.sys_reset } -class FPGAZynqTop(q: Parameters) extends BaseTop(q) - with PeripheryBootROM with PeripheryCoreplexLocalInterrupter - with PeripherySerial with PeripheryMasterMem { - override lazy val module = Module( - new FPGAZynqTopModule(p, this, new FPGAZynqTopBundle(p))) +class FPGAZynqTop(implicit p: Parameters) extends RocketSubsystem + with HasMasterAXI4MemPort + with HasSystemErrorSlave + with HasPeripheryBootROM + with HasSyncExtInterrupts + with HasNoDebug + with HasPeripherySerial + with HasPeripheryBlockDevice { + override lazy val module = new FPGAZynqTopModule(this) } -class FPGAZynqTopBundle(p: Parameters) extends BaseTopBundle(p) - with PeripheryBootROMBundle with PeripheryCoreplexLocalInterrupterBundle - with PeripheryMasterMemBundle with PeripherySerialBundle - -class FPGAZynqTopModule(p: Parameters, l: FPGAZynqTop, b: => FPGAZynqTopBundle) - extends BaseTopModule(p, l, b) - with PeripheryBootROMModule with PeripheryCoreplexLocalInterrupterModule - with PeripheryMasterMemModule with PeripherySerialModule - with HardwiredResetVector with DirectConnection with NoDebug +class FPGAZynqTopModule(outer: FPGAZynqTop) extends RocketSubsystemModuleImp(outer) + with HasRTCModuleImp + with HasMasterAXI4MemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasExtInterruptsModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp + with HasPeripheryBlockDeviceModuleImp + with DontTouch diff --git a/common/src/main/scala/ZynqAdapter.scala b/common/src/main/scala/ZynqAdapter.scala new file mode 100644 index 0000000..75613d0 --- /dev/null +++ b/common/src/main/scala/ZynqAdapter.scala @@ -0,0 +1,124 @@ +package zynq + +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.subsystem.SlavePortParams +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, IdRange} +import freechips.rocketchip.regmapper.{RegField, HasRegMap} +import testchipip._ +import testchipip.SerialAdapter._ + +case object SerialFIFODepth extends Field[Int] +case object BlockDeviceFIFODepth extends Field[Int] +case object NetworkFIFODepth extends Field[Int] +case object ResetCycles extends Field[Int] + +trait ZynqAdapterCoreBundle extends Bundle { + implicit val p: Parameters + + val sys_reset = Output(Bool()) + val serial = Flipped(new SerialIO(SERIAL_IF_WIDTH)) + val bdev = Flipped(new BlockDeviceIO) +} + +trait ZynqAdapterCoreModule extends HasRegMap + with HasBlockDeviceParameters { + implicit val p: Parameters + val io: ZynqAdapterCoreBundle + val w = SERIAL_IF_WIDTH + + val serDepth = p(SerialFIFODepth) + val bdevDepth = p(BlockDeviceFIFODepth) + val serCountBits = log2Ceil(serDepth + 1) + val bdevCountBits = log2Ceil(bdevDepth + 1) + + val ser_out_fifo = Module(new Queue(UInt(w.W), serDepth)) + val ser_in_fifo = Module(new Queue(UInt(w.W), serDepth)) + + ser_out_fifo.io.enq <> io.serial.out + io.serial.in <> ser_in_fifo.io.deq + + val sys_reset = RegInit(true.B) + io.sys_reset := sys_reset + + val bdev_req_fifo = Module(new Queue(UInt(w.W), bdevDepth)) + val bdev_data_fifo = Module(new Queue(UInt(w.W), bdevDepth)) + val bdev_resp_fifo = Module(new Queue(UInt(w.W), bdevDepth)) + val bdev_info = Reg(new BlockDeviceInfo) + val bdev_serdes = Module(new BlockDeviceSerdes(w)) + + bdev_serdes.io.bdev <> io.bdev + bdev_req_fifo.io.enq <> bdev_serdes.io.ser.req + bdev_data_fifo.io.enq <> bdev_serdes.io.ser.data + bdev_serdes.io.ser.resp <> bdev_resp_fifo.io.deq + io.bdev.info := bdev_info + + val ser_in_space = (serDepth.U - ser_in_fifo.io.count) + val bdev_resp_space = (bdevDepth.U - bdev_resp_fifo.io.count) + + /** + * Address Map + * 0x00 - serial out FIFO data + * 0x04 - serial out FIFO data available (words) + * 0x08 - serial in FIFO data + * 0x0C - serial in FIFO space available (words) + * 0x10 - system reset + * 0x20 - req FIFO data + * 0x24 - req FIFO data available (words) + * 0x28 - data FIFO data + * 0x2C - data FIFO data available (words) + * 0x30 - resp FIFO data + * 0x34 - resp FIFO space available (words) + * 0x38 - nsectors + * 0x3C - max request length + */ + regmap( + 0x00 -> Seq(RegField.r(w, ser_out_fifo.io.deq)), + 0x04 -> Seq(RegField.r(serCountBits, ser_out_fifo.io.count)), + 0x08 -> Seq(RegField.w(w, ser_in_fifo.io.enq)), + 0x0C -> Seq(RegField.r(serCountBits, ser_in_space)), + 0x10 -> Seq(RegField(1, sys_reset)), + 0x20 -> Seq(RegField.r(w, bdev_req_fifo.io.deq)), + 0x24 -> Seq(RegField.r(bdevCountBits, bdev_req_fifo.io.count)), + 0x28 -> Seq(RegField.r(w, bdev_data_fifo.io.deq)), + 0x2C -> Seq(RegField.r(bdevCountBits, bdev_data_fifo.io.count)), + 0x30 -> Seq(RegField.w(w, bdev_resp_fifo.io.enq)), + 0x34 -> Seq(RegField.r(bdevCountBits, bdev_resp_space)), + 0x38 -> Seq(RegField(sectorBits, bdev_info.nsectors)), + 0x3C -> Seq(RegField(sectorBits, bdev_info.max_req_len))) +} + +class ZynqAdapterCore(address: BigInt, beatBytes: Int)(implicit p: Parameters) + extends AXI4RegisterRouter( + address, beatBytes = beatBytes, concurrency = 1)( + new AXI4RegBundle((), _) with ZynqAdapterCoreBundle)( + new AXI4RegModule((), _, _) with ZynqAdapterCoreModule) + +class ZynqAdapter(address: BigInt, config: SlavePortParams)(implicit p: Parameters) + extends LazyModule { + + val node = AXI4MasterNode(Seq(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + name = "Zynq Adapter", + id = IdRange(0, 1 << config.idBits)))))) + + val core = LazyModule(new ZynqAdapterCore(address, config.beatBytes)) + core.node := AXI4Fragmenter() := node + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val sys_reset = Output(Bool()) + val serial = Flipped(new SerialIO(SERIAL_IF_WIDTH)) + val bdev = Flipped(new BlockDeviceIO) + }) + val axi = IO(Flipped(node.out(0)._1.cloneType)) + node.out(0)._1 <> axi + + val coreIO = core.module.io + io.sys_reset := coreIO.sys_reset + coreIO.serial <> io.serial + coreIO.bdev <> io.bdev + } +} diff --git a/common/zynq_rocketchip.tcl b/common/zynq_rocketchip.tcl index f9d4755..c0a7e89 100644 --- a/common/zynq_rocketchip.tcl +++ b/common/zynq_rocketchip.tcl @@ -92,6 +92,8 @@ set files [list \ "[file normalize "$origin_dir/src/verilog/clocking.vh"]"\ "[file normalize "$origin_dir/src/verilog/Top.CHISEL_CONFIG_HERE.v"]"\ "[file normalize "$origin_dir/src/verilog/rocketchip_wrapper.v"]"\ + "[file normalize "$origin_dir/src/verilog/AsyncResetReg.v"]" \ + "[file normalize "$origin_dir/src/verilog/plusarg_reader.v"]" \ ] add_files -norecurse -fileset $obj $files diff --git a/rocket-chip b/rocket-chip index f3299ae..7cd3352 160000 --- a/rocket-chip +++ b/rocket-chip @@ -1 +1 @@ -Subproject commit f3299ae91d3f01d0349eb4746886e303e8fb1b41 +Subproject commit 7cd3352c3b802c3c50cb864aee828c6106414bb3 diff --git a/simulation/.gitignore b/simulation/.gitignore index c025b5d..deec1cb 100644 --- a/simulation/.gitignore +++ b/simulation/.gitignore @@ -1,7 +1,4 @@ -/DVEfiles -/csrc -/simv-* -/output -/src/verilog/*.v -/ucli.key -/vc_hdrs.h +* +!Makefile +!.gitignore +!src/verilog/.gitkeep diff --git a/simulation/Makefile b/simulation/Makefile index 55b5f57..8c64ff2 100644 --- a/simulation/Makefile +++ b/simulation/Makefile @@ -13,17 +13,22 @@ include ../common/Makefrag sim_vsrcs = \ src/verilog/$(TOP_MODULE).$(CONFIG).v \ $(base_dir)/rocket-chip/vsrc/TestDriver.v \ - $(base_dir)/testchipip/vsrc/SimSerial.v + $(base_dir)/rocket-chip/vsrc/AsyncResetReg.v \ + $(base_dir)/rocket-chip/vsrc/plusarg_reader.v \ + $(base_dir)/testchipip/vsrc/SimSerial.v \ + $(base_dir)/testchipip/vsrc/SimBlockDevice.v \ sim_csrcs = \ - $(base_dir)/testchipip/csrc/SimSerial.cc + $(base_dir)/testchipip/csrc/SimSerial.cc \ + $(base_dir)/testchipip/csrc/SimBlockDevice.cc \ + $(base_dir)/testchipip/csrc/blkdev.cc \ VCS = vcs -full64 VCS_OPTS = -notice -line +lint=all,noVCDE,noONGS,noUI -error=PCWM-L -timescale=1ns/10ps -quiet \ +rad +v2k +vcs+lic+wait \ +vc+list -CC "-I$(VCS_HOME)/include" \ - -CC "-I$(RISCV)/include" \ + -CC "-I$(RISCV)/include -I$(base_dir)/testchipip/csrc" \ -CC "-std=c++11" \ -CC "-Wl,-rpath,$(RISCV)/lib" \ $(RISCV)/lib/libfesvr.so \ diff --git a/testchipip b/testchipip index 4b6fe07..8bf7e85 160000 --- a/testchipip +++ b/testchipip @@ -1 +1 @@ -Subproject commit 4b6fe076cfab3c685fd6201559221cbad858c77e +Subproject commit 8bf7e85ceb8a33ecca4234ab8edfca4206bc665b diff --git a/zc706/Makefile b/zc706/Makefile index 07bb367..0a5e725 100644 --- a/zc706/Makefile +++ b/zc706/Makefile @@ -2,5 +2,6 @@ BOARD = zc706 UBOOT_CONFIG = zc70x BOARD_MODEL = xilinx.com:zc706:part0:1.0 PART = xc7z045ffg900-2 +CONFIG = ZynqFPGAConfig include ../common/Makefrag diff --git a/zc706/fpga-images-zc706 b/zc706/fpga-images-zc706 index c2ece5e..deaccdf 160000 --- a/zc706/fpga-images-zc706 +++ b/zc706/fpga-images-zc706 @@ -1 +1 @@ -Subproject commit c2ece5e916a8f4205ab70163be9a2aa1766fab6a +Subproject commit deaccdfd820da31f9fbd2284dfbe454581bafdc0 diff --git a/zedboard/Makefile b/zedboard/Makefile index 4840139..3bc2a57 100644 --- a/zedboard/Makefile +++ b/zedboard/Makefile @@ -2,5 +2,6 @@ BOARD = zedboard UBOOT_CONFIG = zed BOARD_MODEL = em.avnet.com:zed:part0:1.0 PART = xc7z020clg484-1 +CONFIG = ZynqFPGAConfig include ../common/Makefrag diff --git a/zedboard/fpga-images-zedboard b/zedboard/fpga-images-zedboard index 7b0028b..968b9dd 160000 --- a/zedboard/fpga-images-zedboard +++ b/zedboard/fpga-images-zedboard @@ -1 +1 @@ -Subproject commit 7b0028b2d646b7ce84f01b56f6857e4be2c7e77f +Subproject commit 968b9dd258c2dfef2d9108335889b993737f5650 diff --git a/zybo/Makefile b/zybo/Makefile index 3646d6a..3081007 100644 --- a/zybo/Makefile +++ b/zybo/Makefile @@ -1,6 +1,6 @@ BOARD = zybo UBOOT_CONFIG = $(BOARD) PART = xc7z010clg400-1 -CONFIG ?= ZynqSmallConfig +CONFIG = ZynqMediumFPGAConfig include ../common/Makefrag diff --git a/zybo/fpga-images-zybo b/zybo/fpga-images-zybo index cf72fa9..b329336 160000 --- a/zybo/fpga-images-zybo +++ b/zybo/fpga-images-zybo @@ -1 +1 @@ -Subproject commit cf72fa94a43f2260279a849824e28ff2656e885a +Subproject commit b329336fba43cab825c12a2fd0e1f7db0fbf5394 From 4ad153c4077bca5daf44570f337281d4e9d510b2 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Wed, 18 Apr 2018 17:43:58 -0700 Subject: [PATCH 2/5] shrink the medium config --- common/src/main/scala/Configs.scala | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/common/src/main/scala/Configs.scala b/common/src/main/scala/Configs.scala index d6d2d74..b842f67 100644 --- a/common/src/main/scala/Configs.scala +++ b/common/src/main/scala/Configs.scala @@ -27,11 +27,8 @@ class WithZynqAdapter extends Config((site, here, up) => { class WithNMediumCores(n: Int) extends Config((site, here, up) => { case RocketTilesKey => { val medium = RocketTileParams( - core = RocketCoreParams(mulDiv = Some(MulDivParams( - mulUnroll = 8, - mulEarlyOut = true, - divEarlyOut = true)), - fpu = None), + core = RocketCoreParams(fpu = None), + btb = None, dcache = Some(DCacheParams( rowBits = site(SystemBusKey).beatBytes*8, nSets = 64, @@ -45,7 +42,7 @@ class WithNMediumCores(n: Int) extends Config((site, here, up) => { nWays = 1, nTLBEntries = 4, blockBytes = site(CacheBlockBytes)))) - List.fill(n)(medium) ++ up(RocketTilesKey, site) + List.tabulate(n)(i => medium.copy(hartId = i)) } }) From 1e9c73ffc68d773ada5060743fe64cf1a52b4da0 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Wed, 18 Apr 2018 11:05:40 -0700 Subject: [PATCH 3/5] update generated bitstreams --- zc706/fpga-images-zc706 | 2 +- zedboard/fpga-images-zedboard | 2 +- zybo/fpga-images-zybo | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zc706/fpga-images-zc706 b/zc706/fpga-images-zc706 index deaccdf..71d3462 160000 --- a/zc706/fpga-images-zc706 +++ b/zc706/fpga-images-zc706 @@ -1 +1 @@ -Subproject commit deaccdfd820da31f9fbd2284dfbe454581bafdc0 +Subproject commit 71d3462105b646ec4985c3d3442fc1103dff8f2a diff --git a/zedboard/fpga-images-zedboard b/zedboard/fpga-images-zedboard index 968b9dd..7e0080e 160000 --- a/zedboard/fpga-images-zedboard +++ b/zedboard/fpga-images-zedboard @@ -1 +1 @@ -Subproject commit 968b9dd258c2dfef2d9108335889b993737f5650 +Subproject commit 7e0080ee9e29e399d80d74d9756f20cece7aeef0 diff --git a/zybo/fpga-images-zybo b/zybo/fpga-images-zybo index b329336..7582b50 160000 --- a/zybo/fpga-images-zybo +++ b/zybo/fpga-images-zybo @@ -1 +1 @@ -Subproject commit b329336fba43cab825c12a2fd0e1f7db0fbf5394 +Subproject commit 7582b50a24081de2a3ced8bf57f83d2825a052d2 From 94893f1d629c628d96e44eac3608755dc9dcb91e Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Wed, 18 Apr 2018 12:43:25 -0700 Subject: [PATCH 4/5] add instructions for using block device to README --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dbf827..2429fe0 100644 --- a/README.md +++ b/README.md @@ -302,7 +302,13 @@ There are two options to obtain riscv-linux: #### Method 1) Build from Source -To build [riscv-linux](http://github.com/riscv/riscv-linux) for Rocket, follow the instructions [here](https://github.com/riscv/riscv-tools#linuxman). Since we currently have no support for a real block device the projects of this repository, you'll need to include an initramfs with your complete filesystem. +To build [riscv-linux](http://github.com/riscv/riscv-linux) for Rocket, follow the instructions [here](https://github.com/riscv/riscv-tools#linuxman). +These instructions will show you how to create a linux image that boots from an initramfs. +We also now have support for block devices, so you can also boot from an ext2 image created by [buildroot](https://github.com/sifive/buildroot). +To configure linux to boot from a block device, instead of selecting "Initial RAM filesystem and RAM disk", +add the arguments "root=/dev/generic-blkdev rw" to the kernel command line +under "Kernel Hacking" -> "Built-in Kernel Command String". To use the block +device, you will need to use the ucbbar-all branch of riscv-linux. Next, you'll need to build an instance of the Berkeley Bootloader(BBL) that contains your linux image as a payload. BBL is provided alongside the proxy kernel at [this repository](https://github.com/riscv/riscv-pk). @@ -351,6 +357,11 @@ To boot riscv-linux, run: After linux boots you'll be presented with a busybox prompt from riscv-linux running on rocket! +If you are using a root filesystem on a seperate filesystem image, you can +boot linux by running + + root@zynq:~# ./fesvr-zynq +blkdev=rootfs.ext2 bbl + Appendices ------------ From 040a8ad2acd58115966ee78469562aaa0e8ca47c Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Fri, 20 Apr 2018 15:25:12 -0400 Subject: [PATCH 5/5] Update readme to include deprecation note. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2429fe0..b67adba 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ Rocket Chip on Zynq FPGAs ========================= +### Warning: This repository is deprecated and does not track Rocket Chip master. +#### Those looking for an FPGA prototype of Rocket Chip should checkout SiFive’s [Freedom platform](https://github.com/sifive/freedom). Those looking for an FPGA-accelerated simulation environment should see [FireSim](https://fires.im/) ([repo, TBR](https://github.com/firesim/firesim)) which will be released in the Summer This repository contains the files needed to run the RISC-V [rocket chip](https://github.com/ucb-bar/rocket-chip) on various Zynq FPGA boards ([Zybo](http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,1198&Prod=ZYBO), [Zedboard](http://zedboard.org/product/zedboard), [ZC706](http://www.xilinx.com/products/boards-and-kits/EK-Z7-ZC706-G.htm)) with Vivado 2016.2. Efforts have been made to not only automate the process of generating files for these boards, but to also reduce duplication as well as the size of this repo. Prebuilt images are available in git submodules, and they are only shallowly cloned if requested.