diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..26700ed --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,40 @@ +name: Build docker + +on: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: sc64env + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1007d8b..be46a87 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: Build +name: Build fw/hw/sw on: push: @@ -18,19 +18,14 @@ jobs: with: submodules: true - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install avra - - name: Build script - run: ./build_release.sh + run: ./build.sh - name: Upload artifact uses: actions/upload-artifact@v2 with: name: SummerCart64 - path: packages/SummerCart64.zip + path: SummerCart64.zip - name: Get release if: github.event_name == 'release' && github.event.action == 'created' diff --git a/.gitignore b/.gitignore index d36fec2..f83604f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -/packages **/.vscode -/sw/test +*.zip diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..497d557 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run -it --mount type=bind,src="$(pwd)",target="/workdir" polprzewodnikowy/sc64env:0.9 /bin/bash ./docker/build.sh diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..4add992 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,93 @@ +FROM ubuntu:18.04 AS base + + +FROM base AS build_base +SHELL ["/bin/bash", "-c"] +WORKDIR /tmp/scratchpad +ENV DEBIAN_FRONTEND="noninteractive" +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y \ + autoconf \ + automake \ + autotools-dev \ + bc \ + bison \ + build-essential \ + bzip2 \ + curl \ + expect \ + file \ + flex \ + g++ \ + gawk \ + gcc \ + gcc-multilib \ + git \ + gperf \ + libexpat-dev \ + libgmp-dev \ + libmpc-dev \ + libmpfr-dev \ + libpng-dev \ + libtool \ + make \ + patchutils \ + python3 \ + texinfo \ + texinfo \ + wget \ + zlib1g-dev + + +FROM build_base AS build_riscv +RUN git clone --branch 2021.09.21 https://github.com/riscv/riscv-gnu-toolchain && \ + pushd ./riscv-gnu-toolchain && \ + ./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32 && \ + make -j$(nproc) && \ + popd && \ + rm -rf ./riscv-gnu-toolchain + + +FROM build_base AS build_n64 +ENV N64_INST=/opt/n64 +ENV FORCE_DEFAULT_GCC=true +RUN git clone https://github.com/DragonMinded/libdragon && \ + pushd ./libdragon && \ + git checkout fc4b6708df7439b9386bb6631e24d8909d78d6ae && \ + pushd ./tools && \ + ./build-toolchain.sh && \ + popd && \ + make install && \ + make tools-install && \ + popd && \ + rm -rf ./libdragon + + +FROM build_base AS build_quartus +ADD setup_quartus.sh . +RUN mkdir -p ./quartus && \ + pushd ./quartus && \ + wget -q http://download.altera.com/akdlm/software/acdsinst/20.1std.1/720/ib_tar/Quartus-lite-20.1.1.720-linux.tar && \ + tar xvf Quartus-lite-20.1.1.720-linux.tar && \ + popd && \ + ./setup_quartus.sh 20.1 && \ + rm -rf ./quartus setup_quartus.sh + + +FROM base AS release +WORKDIR /workdir +ENV DEBIAN_FRONTEND="noninteractive" +ENV LC_ALL="en_US.UTF-8" +ENV N64_INST="/usr/local" +ENV PATH="${PATH}:/opt/intelFPGA_lite/20.1/quartus/bin" +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y avra make python3 libglib2.0-0 libtcmalloc-minimal4 libmpc3 locales zip && \ + echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \ + locale-gen en_US.UTF-8 && \ + /usr/sbin/update-locale LANG=en_US.UTF-8 +COPY --from=build_riscv /opt/riscv /usr/local +COPY --from=build_n64 /opt/n64 /usr/local +COPY --from=build_quartus /opt/intelFPGA_lite /opt/intelFPGA_lite +ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4" diff --git a/docker/build.sh b/docker/build.sh new file mode 100644 index 0000000..49191ee --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash + + +PACKAGE_FILE_NAME="SummerCart64" +FILES=( + "./fw/output_files/SummerCart64.pof" + "./hw/v1/ftdi-template.xml" + "./sw/cic/UltraCIC-III.hex" + "./sw/riscv/build/controller.rom" + "./LICENSE" +) + + +pushd sw/cic +echo "Building UltraCIC-III software" +avra UltraCIC-III.asm -D attiny45 +popd + + +pushd sw/n64 +echo "Building N64 bootloader software" +make clean all +popd + + +pushd sw/riscv +echo "Building RISC-V controller software" +make clean all +popd + + +pushd fw +echo "Building FPGA firmware" +quartus_sh --flow compile SummerCart64.qpf +popd + + +echo "Zipping files" +if [[ -e "./${PACKAGE_FILE_NAME}.zip" ]]; then + rm -f "./${PACKAGE_FILE_NAME}.zip" +fi +zip -r "./${PACKAGE_FILE_NAME}.zip" ${FILES[@]} diff --git a/docker/setup_quartus.sh b/docker/setup_quartus.sh new file mode 100644 index 0000000..a17964c --- /dev/null +++ b/docker/setup_quartus.sh @@ -0,0 +1,25 @@ +#!/usr/bin/expect + +set timeout -1 + +set version [lindex $argv 0] + +spawn ./quartus/setup.sh + +expect { + "Press \\\[Enter\\\] to continue:" { send "\r"; exp_continue } + "Do you accept this license? \\\[y/n\\\]" { send "y\r"; exp_continue } + "Installation directory \\\[/root/intelFPGA_lite/$version\\\]:" { send "/opt/intelFPGA_lite/$version\r"; exp_continue } + "Quartus Prime Lite Edition (Free) \\\[Y/n\\\] :" { send "y\r"; exp_continue } + "Quartus Prime Lite Edition (Free) - Quartus Prime Help" { send "n\r"; exp_continue } + "Quartus Prime Lite Edition (Free) - Devices \\\[Y/n\\\] " { send "y\r"; exp_continue } + "Quartus Prime Lite Edition (Free) - Devices - MAX 10 FPGA" { send "y\r"; exp_continue } + "Quartus Prime Lite Edition (Free) - Devices - " { send "n\r"; exp_continue } + "ModelSim - Intel FPGA Starter Edition (Free)" { send "n\r"; exp_continue } + "ModelSim - Intel FPGA Edition" { send "n\r"; exp_continue } + "Is the selection above correct? \\\[Y/n\\\]:" { send "y\r"; exp_continue } + "Create shortcuts on Desktop \\\[Y/n\\\]:" { send "n\r"; exp_continue } + "Launch Quartus Prime Lite Edition \\\[Y/n\\\]:" { send "n\r"; exp_continue } + "Provide your feedback at" { send "n\r"; exp_continue } + eof { } +} diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 4a92f40..1987b3c 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -54,7 +54,7 @@ set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip set_global_assignment -name SDC_FILE SummerCart64.sdc set_global_assignment -name SIGNALTAP_FILE stp.stp set_global_assignment -name SYSTEMVERILOG_FILE cpu/picorv32/picorv32.v -set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bootloader.sv +set_global_assignment -name SYSTEMVERILOG_FILE ../sw/riscv/build/cpu_bootloader.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv diff --git a/fw/rtl/cpu/cpu_bootloader.sv b/fw/rtl/cpu/cpu_bootloader.sv deleted file mode 100644 index 8700cbd..0000000 --- a/fw/rtl/cpu/cpu_bootloader.sv +++ /dev/null @@ -1,49 +0,0 @@ -module cpu_bootloader ( - if_system.sys sys, - if_cpu_bus bus -); - - always_ff @(posedge sys.clk) begin - bus.ack <= 1'b0; - if (bus.request) begin - bus.ack <= 1'b1; - end - end - - always_comb begin - bus.rdata = 32'd0; - if (bus.ack) begin - case (bus.address[6:2]) - 0: bus.rdata = 32'h00000793; - 1: bus.rdata = 32'h00000713; - 2: bus.rdata = 32'h50000637; - 3: bus.rdata = 32'h02000593; - 4: bus.rdata = 32'h00062683; - 5: bus.rdata = 32'h0016f693; - 6: bus.rdata = 32'hfe068ce3; - 7: bus.rdata = 32'h00464683; - 8: bus.rdata = 32'h00f696b3; - 9: bus.rdata = 32'h00878793; - 10: bus.rdata = 32'h00d76733; - 11: bus.rdata = 32'hfeb792e3; - 12: bus.rdata = 32'h00000793; - 13: bus.rdata = 32'h500005b7; - 14: bus.rdata = 32'h0005a683; - 15: bus.rdata = 32'h0016f693; - 16: bus.rdata = 32'hfe068ce3; - 17: bus.rdata = 32'h0045c683; - 18: bus.rdata = 32'h00178613; - 19: bus.rdata = 32'h0ff6f693; - 20: bus.rdata = 32'h00d78023; - 21: bus.rdata = 32'h00e61863; - 22: bus.rdata = 32'hf0000297; - 23: bus.rdata = 32'hfa828293; - 24: bus.rdata = 32'h00028067; - 25: bus.rdata = 32'h00060793; - 26: bus.rdata = 32'hfd1ff06f; - default: bus.rdata = 32'd0; - endcase - end - end - -endmodule diff --git a/sw/n64/Makefile b/sw/n64/Makefile index 2a746ae..f835a6f 100644 --- a/sw/n64/Makefile +++ b/sw/n64/Makefile @@ -16,7 +16,7 @@ HEADER_NAME = header PROG_NAME = SummerLoader64 -ROM_SIZE = 90k +ROM_SIZE = 1028k SOURCE_DIR = src BUILD_DIR = build @@ -35,7 +35,6 @@ CFLAGS = $(COMMONFLAGS) -std=gnu11 -Os -Wall -I$(ROOTDIR)/mips64-elf/include $(I LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld #-L./libsc64/lib -lsc64_libdragon N64_FLAGS = -l $(ROM_SIZE) -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME).z64 -N64_FLAGS_PADDED = -l 1028k -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME)_padded.z64 all: make_output_dir $(BUILD_DIR)/$(PROG_NAME).z64 @@ -45,9 +44,8 @@ $(BUILD_DIR)/$(PROG_NAME).z64: $(BUILD_DIR)/$(PROG_NAME).elf $(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).elf $(BUILD_DIR)/$(PROG_NAME).bin -O binary $(OBJDUMP) -S $(BUILD_DIR)/$(PROG_NAME).elf > $(BUILD_DIR)/$(PROG_NAME).lst $(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) $(BUILD_DIR)/$(PROG_NAME).bin - $(N64TOOL) $(N64_FLAGS_PADDED) -t $(PROG_NAME) $(BUILD_DIR)/$(PROG_NAME).bin $(CHKSUM64) $(BUILD_DIR)/$(PROG_NAME).z64 - $(CHKSUM64) $(BUILD_DIR)/$(PROG_NAME)_padded.z64 + truncate --size=90k $(BUILD_DIR)/$(PROG_NAME).z64 $(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).z64 $(BUILD_DIR)/$(PROG_NAME).hex -I binary -O ihex $(BUILD_DIR)/$(PROG_NAME).elf: $(OBJ_FILES) diff --git a/sw/n64/build.sh b/sw/n64/build.sh index 03550f5..5ed11b2 100644 --- a/sw/n64/build.sh +++ b/sw/n64/build.sh @@ -1,9 +1,3 @@ #!/bin/bash -#--mount type=bind,src=`realpath "$(pwd)/../libsc64"`,target="/src/libsc64" \ -build_in_docker() { - docker run -t \ - --mount type=bind,src=`realpath $(pwd)`,target="/src" \ - $1 /bin/bash -c "cd /src && make clean && make -f $2 all" -} -build_in_docker "anacierdem/libdragon:6.0.2" "Makefile" +docker run -it --mount type=bind,src="$(pwd)",target="/workdir" polprzewodnikowy/sc64env:0.9 /bin/bash -c "make clean all" diff --git a/sw/riscv/Makefile b/sw/riscv/Makefile index b113732..d4db2a9 100644 --- a/sw/riscv/Makefile +++ b/sw/riscv/Makefile @@ -1,4 +1,4 @@ -TOOLCHAIN = riscv64-unknown-elf- +TOOLCHAIN = riscv32-unknown-elf- CC = $(TOOLCHAIN)gcc OBJCOPY = $(TOOLCHAIN)objcopy SIZE = $(TOOLCHAIN)size @@ -9,7 +9,6 @@ LDFLAGS = -nostartfiles -Wl,--gc-sections SRC_DIR = src BUILD_DIR = build -BOOTLOADER_DIR = ../../fw/rtl/cpu SRCS = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIR))) OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRCS:.c=.o))) @@ -19,7 +18,7 @@ VPATH = $(SRC_DIR) $(@info $(shell mkdir -p ./$(BUILD_DIR) &> /dev/null)) -all: $(BOOTLOADER_DIR)/cpu_bootloader.sv $(BUILD_DIR)/controller.rom +all: $(BUILD_DIR)/cpu_bootloader.sv $(BUILD_DIR)/controller.rom $(BUILD_DIR)/%.o: %.c $(CC) $(FLAGS) $(CFLAGS) -c $< -o $@ @@ -36,7 +35,7 @@ $(BUILD_DIR)/controller.rom: $(BUILD_DIR)/uc.elf @echo 'Size of controller:' @$(SIZE) -B $(BUILD_DIR)/controller.elf -$(BOOTLOADER_DIR)/cpu_bootloader.sv: $(BUILD_DIR)/uc.elf +$(BUILD_DIR)/cpu_bootloader.sv: $(BUILD_DIR)/uc.elf $(OBJCOPY) -j .bootloader $(BUILD_DIR)/uc.elf $(BUILD_DIR)/bootloader.elf $(OBJCOPY) -O binary $(BUILD_DIR)/bootloader.elf $(BUILD_DIR)/bootloader.bin python3 tools/bin2sv.py tools/cpu_bootloader_template.sv $@ < $(BUILD_DIR)/bootloader.bin diff --git a/sw/riscv/build.sh b/sw/riscv/build.sh new file mode 100644 index 0000000..5ed11b2 --- /dev/null +++ b/sw/riscv/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run -it --mount type=bind,src="$(pwd)",target="/workdir" polprzewodnikowy/sc64env:0.9 /bin/bash -c "make clean all"