Merge pull request #82 from ucb-bar/new-devices-no-nic
Merge new-devices (without NIC)
This commit is contained in:
commit
816d941ca0
|
@ -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
|
||||
|
|
15
README.md
15
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.
|
||||
|
@ -302,7 +304,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 +359,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
|
||||
|
||||
<a name="appendices"></a> Appendices
|
||||
------------
|
||||
|
||||
|
|
|
@ -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-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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
*.elf
|
||||
*.dump
|
|
@ -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 $< > $@
|
|
@ -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
|
Binary file not shown.
|
@ -1,5 +0,0 @@
|
|||
SECTIONS
|
||||
{
|
||||
. = 0x1000;
|
||||
.text : { *(.text) }
|
||||
}
|
|
@ -1,14 +1,66 @@
|
|||
#include "zynq_tsi_driver.h"
|
||||
#include "zynq_driver.h"
|
||||
#include "fesvr/tsi.h"
|
||||
#include <vector>
|
||||
|
||||
#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<std::string>(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);
|
||||
|
||||
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()){
|
||||
tsi_driver.poll(&tsi);
|
||||
driver->poll();
|
||||
}
|
||||
|
||||
delete driver;
|
||||
if (blkdev != NULL)
|
||||
delete blkdev;
|
||||
if (netdev != NULL)
|
||||
delete netdev;
|
||||
|
||||
return tsi.exit_code();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#include "zynq_driver.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
|
@ -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 <stdint.h>
|
||||
|
||||
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
|
|
@ -1,59 +0,0 @@
|
|||
#include "zynq_tsi_driver.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef __ZYNQ_SAI_DRIVER_H
|
||||
#define __ZYNQ_SAI_DRIVER_H
|
||||
|
||||
#include "fesvr/tsi.h"
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
sbt.version=0.13.15
|
|
@ -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")
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -1,58 +1,63 @@
|
|||
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
|
||||
class WithBootROM extends Config((site, here, up) => {
|
||||
case BootROMParams => BootROMParams(
|
||||
contentFileName = s"../testchipip/bootrom/bootrom.rv${site(XLen)}.img")
|
||||
})
|
||||
|
||||
class WithZynqAdapter extends Config((site, here, up) => {
|
||||
case SerialFIFODepth => 16
|
||||
case ResetCycles => 10
|
||||
case BuildSerialDriver =>
|
||||
(p: Parameters) => Module(new SimSerialWrapper(p(SerialInterfaceWidth)))
|
||||
case _ => throw new CDEMatchError
|
||||
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 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 ZynqConfig extends Config(new WithZynqAdapter ++ new DefaultFPGAConfig)
|
||||
class ZynqSmallConfig extends Config(new WithSmallCores ++ new ZynqConfig)
|
||||
|
||||
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
|
||||
})))
|
||||
class WithNMediumCores(n: Int) extends Config((site, here, up) => {
|
||||
case RocketTilesKey => {
|
||||
val medium = RocketTileParams(
|
||||
core = RocketCoreParams(fpu = None),
|
||||
btb = 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.tabulate(n)(i => medium.copy(hartId = i))
|
||||
}
|
||||
case _ => throw new CDEMatchError
|
||||
})
|
||||
|
||||
class IntegrationTestConfig extends Config(new WithIntegrationTest ++ new ZynqConfig)
|
||||
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 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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
target.debug := DontCare
|
||||
target.tieOffInterrupts()
|
||||
target.dontTouchPorts()
|
||||
target.reset := adapter.io.sys_reset
|
||||
}
|
||||
|
||||
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")
|
||||
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 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 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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f3299ae91d3f01d0349eb4746886e303e8fb1b41
|
||||
Subproject commit 7cd3352c3b802c3c50cb864aee828c6106414bb3
|
|
@ -1,7 +1,4 @@
|
|||
/DVEfiles
|
||||
/csrc
|
||||
/simv-*
|
||||
/output
|
||||
/src/verilog/*.v
|
||||
/ucli.key
|
||||
/vc_hdrs.h
|
||||
*
|
||||
!Makefile
|
||||
!.gitignore
|
||||
!src/verilog/.gitkeep
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 4b6fe076cfab3c685fd6201559221cbad858c77e
|
||||
Subproject commit 8bf7e85ceb8a33ecca4234ab8edfca4206bc665b
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c2ece5e916a8f4205ab70163be9a2aa1766fab6a
|
||||
Subproject commit 71d3462105b646ec4985c3d3442fc1103dff8f2a
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7b0028b2d646b7ce84f01b56f6857e4be2c7e77f
|
||||
Subproject commit 7e0080ee9e29e399d80d74d9756f20cece7aeef0
|
|
@ -1,6 +1,6 @@
|
|||
BOARD = zybo
|
||||
UBOOT_CONFIG = $(BOARD)
|
||||
PART = xc7z010clg400-1
|
||||
CONFIG ?= ZynqSmallConfig
|
||||
CONFIG = ZynqMediumFPGAConfig
|
||||
|
||||
include ../common/Makefrag
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cf72fa94a43f2260279a849824e28ff2656e885a
|
||||
Subproject commit 7582b50a24081de2a3ced8bf57f83d2825a052d2
|
Loading…
Reference in New Issue