| @ -1,140 +0,0 @@ | |||
| # Color definitions ------------------------------- | |||
| NO_COLOR="\033[0m" | |||
| RED="\033[38;5;009m" | |||
| GREEN="\033[38;5;010m" | |||
| YELLOW="\033[38;5;011m" | |||
| ORANGE="\033[38;5;214m" | |||
| LIGHTPURPLE="\033[38;5;177m" | |||
| PURPLE="\033[38;5;135m" | |||
| CYAN="\033[38;5;014m" | |||
| LIGHTBLUE="\033[38;5;39m" | |||
| BLUE="\033[38;5;75m" | |||
| DARKBLUE="\033[38;5;33m" | |||
| LIGHTGRAY="\033[38;5;252m" | |||
| DARKGRAY="\033[38;5;242m" | |||
| BRIGHTRED="\033[91m" | |||
| BOLD="\033[1m" | |||
| # PATHS (adapt to your system)---------------------- | |||
| PATH_RISCV=/opt/riscv/ | |||
| PATH_RISC_BIN=$(PATH_RISCV)bin/ | |||
| PATH_VERILATOR_BIN?=/usr/local/bin/verilator | |||
| PREFIX?=$(PATH_RISC_BIN)riscv64-unknown-elf | |||
| # TOOLS -------------------------------------------- | |||
| AR?=$(PREFIX)-ar | |||
| GCC?=$(PREFIX)-gcc | |||
| CLANG=clang | |||
| GDB?=$(PREFIX)-gdb | |||
| OBJDUMP?=$(PREFIX)-objdump | |||
| OBJCOPY?=$(PREFIX)-objcopy | |||
| RISCVPATH=$(PATH_RISCV)riscv64-unknown-elf | |||
| OPENOCD?=$(PATH_RISC_BIN)openocd | |||
| ECHO?=echo | |||
| # GCC FLAGS --------------------------------------- | |||
| CC=$(GCC) | |||
| GCC_CFLAGS_COMMON := -g \ | |||
| -O3 \ | |||
| -fno-builtin-printf \ | |||
| -Wno-unused-parameter \ | |||
| -Wall -Wextra -Wredundant-decls \ | |||
| -Wshadow -Wno-unused-function \ | |||
| -fno-common \ | |||
| -I$(RISCVPATH)/include | |||
| GCC_CFLAGS_MURAX=-fstrict-volatile-bitfields --specs=nosys.specs | |||
| RISCV_ARCH?=rv32im | |||
| RISCV_ABI?=ilp32 | |||
| RISCV_CMODEL?=medany | |||
| RISCV_ARCHFLAGS +=-march=$(RISCV_ARCH) | |||
| RISCV_ARCHFLAGS +=-mabi=$(RISCV_ABI) | |||
| RISCV_ARCHFLAGS +=-mcmodel=$(RISCV_CMODEL) | |||
| GCC_RISCV_ARCHFLAGS=$(RISCV_ARCHFLAGS) | |||
| CFLAGS += $(GCC_CFLAGS_COMMON) \ | |||
| $(GCC_CFLAGS_MURAX) \ | |||
| $(GCC_RISCV_ARCHFLAGS) | |||
| # Linker flags -------------------------------------- | |||
| PLATFORM ?= pqvexriscvsim | |||
| LDSCRIPT = $(PLATFORM).ld | |||
| LDFLAGS = -L$(RISCVPATH)/lib/rv32imac/ilp32 | |||
| LDFLAGS += $(GCC_RISCV_ARCHFLAGS) | |||
| LDFLAGS += --specs=nosys.specs | |||
| LDFLAGS += -Wl,-T$(LDSCRIPT) | |||
| LDFLAGS += -nostartfiles -ffreestanding -Wl,--gc-sections | |||
| LDFLAGS += -L. | |||
| LDFLAGS += -Wl,--start-group -l$(PLATFORM)bsp -lc -Wl,--end-group | |||
| # Object files -------------------------------------- | |||
| SDK_ASM_SRCS := $(wildcard *.S) | |||
| SDK_C_SRCS := $(wildcard *.c) | |||
| SDK_C_OBJS := $(SDK_C_SRCS:.c=.o) | |||
| SDK_ASM_OBJS := $(SDK_ASM_SRCS:.S=.o) | |||
| SDK_OBJS := $(SDK_C_OBJS) $(SDK_ASM_OBJS) | |||
| # Target all ---------------------------------------- | |||
| .PHONY: all | |||
| all: main.hex main.bin | |||
| # LIBWRAP | |||
| include vexriscv/vexriscv.mk | |||
| # Targets -------------------------------------------- | |||
| main.bin: main | |||
| @$(ECHO) $(PURPLE)"obj "$@""$(LIGHTGRAY) | |||
| $(OBJCOPY) -O binary $< $@ | |||
| main.hex: main | |||
| @$(ECHO) $(PURPLE)"obj "$@""$(LIGHTGRAY) | |||
| $(OBJCOPY) -O ihex $< $@ | |||
| main: $(LIBWRAP) $(SDK_OBJS) $(LDSCRIPT) | |||
| @$(ECHO) $(LIGHTPURPLE)"building "$@""$(LIGHTGRAY) | |||
| $(GCC) $(GCC_RISCV_ARCHFLAGS) $(GCC_CFLAGS_COMMON) $(SDK_OBJS) -o $@ $(LDFLAGS) | |||
| %.o: %.S | |||
| @$(ECHO) $(ORANGE)"building "$@" (.S)"$(LIGHTGRAY) | |||
| $(CC) $(CFLAGS) -c -o $@ $^ | |||
| %.o: %.c | |||
| @$(ECHO) $(ORANGE)"building "$@" (.c)"$(LIGHTGRAY) | |||
| $(CC) $(CFLAGS) -c -o $@ $^ | |||
| .PHONY: clean | |||
| clean: | |||
| @$(ECHO) $(RED)"cleaning..."$(LIGHTGRAY) | |||
| rm -f main main.bin main.hex $(SDK_OBJS) $(LIBWRAP_OBJS) $(LIBWRAP) | |||
| help: | |||
| @$(ECHO) $(RED)"Compile & Simulate"$(LIGHTGRAY) | |||
| @$(ECHO) $(LIGHTGRAY)"1. "$(CYAN)"make"$(LIGHTGRAY) | |||
| @$(ECHO) $(LIGHTGRAY)"2. open 3 terminals"$(LIGHTGRAY) | |||
| @$(ECHO) $(LIGHTGRAY)"3. Terminal 2: "$(CYAN)"make startsim"$(LIGHTGRAY) | |||
| @$(ECHO) $(LIGHTGRAY)"4. Terminal 3: "$(CYAN)"make openocd"$(LIGHTGRAY) | |||
| @$(ECHO) $(LIGHTGRAY)"5. Terminal 1: "$(CYAN)"make flash"$(LIGHTGRAY) | |||
| # Targets for starting simulation, openocd and gdb ---------------------------- | |||
| # startsim: | |||
| # cd ../Building_Tools/pqriscv-vexriscv/ ; sbt "runMain mupq.PQVexRiscvSim --ram 256,128" | |||
| # openocd: | |||
| # cd ../Building_Tools/pqriscv-vexriscv/ ; /opt/verilator/bin/openocd --file pqvexriscvsim.cfg | |||
| #flash: | |||
| # /opt/riscv/bin/riscv64-unknown-elf-gdb -ex 'set remotetimeout 15' -ex 'target remote :3333' -ex 'load' -ex 'break main' -ex 'continue' main | |||
| @ -1,97 +0,0 @@ | |||
| # .global crtStart | |||
| # .global main | |||
| # .global irqCallback | |||
| # crtStart: | |||
| # j crtInit | |||
| # nop | |||
| # nop | |||
| # nop | |||
| # nop | |||
| # nop | |||
| # nop | |||
| # nop | |||
| # .global trap_entry | |||
| # trap_entry: | |||
| # sw x1, - 1*4(sp) | |||
| # sw x5, - 2*4(sp) | |||
| # sw x6, - 3*4(sp) | |||
| # sw x7, - 4*4(sp) | |||
| # sw x10, - 5*4(sp) | |||
| # sw x11, - 6*4(sp) | |||
| # sw x12, - 7*4(sp) | |||
| # sw x13, - 8*4(sp) | |||
| # sw x14, - 9*4(sp) | |||
| # sw x15, -10*4(sp) | |||
| # sw x16, -11*4(sp) | |||
| # sw x17, -12*4(sp) | |||
| # sw x28, -13*4(sp) | |||
| # sw x29, -14*4(sp) | |||
| # sw x30, -15*4(sp) | |||
| # sw x31, -16*4(sp) | |||
| # addi sp,sp,-16*4 | |||
| # call irqCallback | |||
| # lw x1 , 15*4(sp) | |||
| # lw x5, 14*4(sp) | |||
| # lw x6, 13*4(sp) | |||
| # lw x7, 12*4(sp) | |||
| # lw x10, 11*4(sp) | |||
| # lw x11, 10*4(sp) | |||
| # lw x12, 9*4(sp) | |||
| # lw x13, 8*4(sp) | |||
| # lw x14, 7*4(sp) | |||
| # lw x15, 6*4(sp) | |||
| # lw x16, 5*4(sp) | |||
| # lw x17, 4*4(sp) | |||
| # lw x28, 3*4(sp) | |||
| # lw x29, 2*4(sp) | |||
| # lw x30, 1*4(sp) | |||
| # lw x31, 0*4(sp) | |||
| # addi sp,sp,16*4 | |||
| # mret | |||
| # .text | |||
| # crtInit: | |||
| # .option push | |||
| # .option norelax | |||
| # la gp, __global_pointer$ | |||
| # .option pop | |||
| # la sp, _stack_start | |||
| # bss_init: | |||
| # la a0, _bss_start | |||
| # la a1, _bss_end | |||
| # bss_loop: | |||
| # beq a0,a1,bss_done | |||
| # sw zero,0(a0) | |||
| # add a0,a0,4 | |||
| # j bss_loop | |||
| # bss_done: | |||
| # ctors_init: | |||
| # la a0, _ctors_start | |||
| # addi sp,sp,-4 | |||
| # ctors_loop: | |||
| # la a1, _ctors_end | |||
| # beq a0,a1,ctors_done | |||
| # lw a3,0(a0) | |||
| # add a0,a0,4 | |||
| # sw a0,0(sp) | |||
| # jalr a3 | |||
| # lw a0,0(sp) | |||
| # j ctors_loop | |||
| # ctors_done: | |||
| # addi sp,sp,4 | |||
| # li a0, 0x880 //880 enable timer + external interrupts | |||
| # csrw mie,a0 | |||
| # li a0, 0x1808 //1808 enable interrupts | |||
| # csrw mstatus,a0 | |||
| # call main | |||
| # infinitLoop: | |||
| # j infinitLoop | |||
| @ -1,14 +0,0 @@ | |||
| OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") | |||
| OUTPUT_ARCH(riscv) | |||
| ENTRY( _start ) | |||
| __ram_size = 128K; | |||
| MEMORY | |||
| { | |||
| rom (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K | |||
| ram (wxa!ri) : ORIGIN = 0x80020000, LENGTH = 64K | |||
| } | |||
| INCLUDE volatile-split.ld | |||
| @ -1,141 +0,0 @@ | |||
| /* SECTIONS for non-volatile chip configuration, i.e. chips with flash */ | |||
| SECTIONS | |||
| { | |||
| .init : | |||
| { | |||
| KEEP (*(SORT_NONE(.init))) | |||
| } >rom | |||
| .text : | |||
| { | |||
| *(.text.unlikely .text.unlikely.*) | |||
| *(.text.startup .text.startup.*) | |||
| *(.text .text.*) | |||
| *(.gnu.linkonce.t.*) | |||
| } >rom | |||
| .fini : | |||
| { | |||
| KEEP (*(SORT_NONE(.fini))) | |||
| } >rom | |||
| PROVIDE (__etext = .); | |||
| PROVIDE (_etext = .); | |||
| PROVIDE (etext = .); | |||
| .rodata : | |||
| { | |||
| *(.rdata) | |||
| *(.rodata .rodata.*) | |||
| *(.gnu.linkonce.r.*) | |||
| . = ALIGN(8); | |||
| *(.srodata.cst16) | |||
| *(.srodata.cst8) | |||
| *(.srodata.cst4) | |||
| *(.srodata.cst2) | |||
| *(.srodata .srodata.*) | |||
| } >rom | |||
| . = ALIGN(4); | |||
| .preinit_array : | |||
| { | |||
| PROVIDE_HIDDEN (__preinit_array_start = .); | |||
| KEEP (*(.preinit_array)) | |||
| PROVIDE_HIDDEN (__preinit_array_end = .); | |||
| } >rom | |||
| .init_array : | |||
| { | |||
| PROVIDE_HIDDEN (__init_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) | |||
| KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) | |||
| PROVIDE_HIDDEN (__init_array_end = .); | |||
| } >rom | |||
| .fini_array : | |||
| { | |||
| PROVIDE_HIDDEN (__fini_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) | |||
| KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) | |||
| PROVIDE_HIDDEN (__fini_array_end = .); | |||
| } >rom | |||
| .ctors : | |||
| { | |||
| /* gcc uses crtbegin.o to find the start of | |||
| the constructors, so we make sure it is | |||
| first. Because this is a wildcard, it | |||
| doesn't matter if the user does not | |||
| actually link against crtbegin.o; the | |||
| linker won't look for a file to match a | |||
| wildcard. The wildcard also means that it | |||
| doesn't matter which directory crtbegin.o | |||
| is in. */ | |||
| KEEP (*crtbegin.o(.ctors)) | |||
| KEEP (*crtbegin?.o(.ctors)) | |||
| /* We don't want to include the .ctor section from | |||
| the crtend.o file until after the sorted ctors. | |||
| The .ctor section from the crtend file contains the | |||
| end of ctors marker and it must be last */ | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | |||
| KEEP (*(SORT(.ctors.*))) | |||
| KEEP (*(.ctors)) | |||
| } >rom | |||
| .dtors : | |||
| { | |||
| KEEP (*crtbegin.o(.dtors)) | |||
| KEEP (*crtbegin?.o(.dtors)) | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | |||
| KEEP (*(SORT(.dtors.*))) | |||
| KEEP (*(.dtors)) | |||
| } >rom | |||
| .lalign : | |||
| { | |||
| . = ALIGN(4); | |||
| } >rom | |||
| .dalign : | |||
| { | |||
| . = ALIGN(4); | |||
| } >ram AT>rom | |||
| .data : | |||
| { | |||
| PROVIDE( _data = . ); | |||
| *(.data .data.*) | |||
| *(.gnu.linkonce.d.*) | |||
| . = ALIGN(8); | |||
| PROVIDE( __global_pointer$ = . + 0x800 ); | |||
| *(.sdata .sdata.*) | |||
| *(.gnu.linkonce.s.*) | |||
| } >ram AT>rom | |||
| PROVIDE( _data_lma = LOADADDR(.data) ); | |||
| . = ALIGN(4); | |||
| PROVIDE( _edata = . ); | |||
| PROVIDE( edata = . ); | |||
| PROVIDE( _fbss = . ); | |||
| PROVIDE( __bss_start = . ); | |||
| .bss : | |||
| { | |||
| *(.sbss*) | |||
| *(.gnu.linkonce.sb.*) | |||
| *(.bss .bss.*) | |||
| *(.gnu.linkonce.b.*) | |||
| *(COMMON) | |||
| . = ALIGN(4); | |||
| } >ram | |||
| . = ALIGN(8); | |||
| PROVIDE( _end = . ); | |||
| PROVIDE( end = . ); | |||
| } | |||
| PROVIDE(_sp = ORIGIN(ram) + LENGTH(ram)); | |||
| PROVIDE(_heap_end = ORIGIN(ram) + LENGTH(ram)); | |||
| @ -1,14 +0,0 @@ | |||
| OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") | |||
| OUTPUT_ARCH(riscv) | |||
| ENTRY( _start ) | |||
| __ram_size = 128K; | |||
| MEMORY | |||
| { | |||
| rom (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K | |||
| ram (wxa!ri) : ORIGIN = 0x80020000, LENGTH = 64K | |||
| } | |||
| INCLUDE volatile-split.ld | |||
| @ -1,45 +0,0 @@ | |||
| PLATFORM ?= murax | |||
| LIBWRAP_CFLAGS += -Os -Wall -Wextra | |||
| LIBWRAP_CFLAGS += $(GCC_RISCV_ARCHFLAGS) -fstrict-volatile-bitfields --specs=nosys.specs | |||
| ifeq ($(PLATFORM),murax) | |||
| LIBWRAP_CFLAGS += -DVEXRISCV_VOLATILE | |||
| endif | |||
| ifeq ($(PLATFORM),pqvexriscvup5k) | |||
| LIBWRAP_CFLAGS += -DVEXRISCV_VOLATILE -DVEXRISCV_RWMTVEC | |||
| endif | |||
| ifeq ($(PLATFORM),pqvexriscvicoboard) | |||
| LIBWRAP_CFLAGS += -DVEXRISCV_VOLATILE -DVEXRISCV_RWMTVEC | |||
| endif | |||
| ifeq ($(PLATFORM),pqvexriscvsim) | |||
| LIBWRAP_CFLAGS += -DVEXRISCV_RWMTVEC | |||
| endif | |||
| LIBWRAP_DIR := $(dir $(lastword $(MAKEFILE_LIST))) | |||
| LIBWRAP_SRCS_C = init.c | |||
| LIBWRAP_SRCS_ASM = start.s | |||
| LIBWRAP_OBJS_ = $(LIBWRAP_SRCS_C:.c=.o) $(LIBWRAP_SRCS_ASM:.s=.o) | |||
| LIBWRAP_OBJS = $(addprefix $(LIBWRAP_DIR)$(PLATFORM)_,$(LIBWRAP_OBJS_)) | |||
| LIBWRAP = lib$(PLATFORM)bsp.a | |||
| $(LIBWRAP): $(LIBWRAP_OBJS) | |||
| @$(ECHO) $(LIGHTBLUE)"building "$@""$(LIGHTGRAY) | |||
| $(AR) rcs $@ $^ | |||
| $(LIBWRAP_DIR)$(PLATFORM)_%.o: $(LIBWRAP_DIR)%.c | |||
| @$(ECHO) $(DARKBLUE)" "$(LIBWRAP_DIR)" "$(LIGHTGRAY) | |||
| @$(ECHO) $(DARKBLUE)"building "$@" (.c)"$(LIGHTGRAY) | |||
| $(GCC) $(LIBWRAP_CFLAGS) -c -o $@ $< | |||
| $(LIBWRAP_DIR)$(PLATFORM)_%.o: $(LIBWRAP_DIR)%.S | |||
| @$(ECHO) $(DARKBLUE)"building "$@" (.S)"$(LIGHTGRAY) | |||
| $(GCC) $(LIBWRAP_CFLAGS) -c -o $@ $< | |||
| @ -1,8 +0,0 @@ | |||
| #include "weak_under_alias.h" | |||
| void __weak__init() {} | |||
| void __weak__fini() {} | |||
| weak_under_alias(_init); | |||
| weak_under_alias(_fini); | |||
| @ -1,141 +0,0 @@ | |||
| /* SECTIONS for non-volatile chip configuration, i.e. chips with flash */ | |||
| SECTIONS | |||
| { | |||
| .init : | |||
| { | |||
| KEEP (*(SORT_NONE(.init))) | |||
| } >rom | |||
| .text : | |||
| { | |||
| *(.text.unlikely .text.unlikely.*) | |||
| *(.text.startup .text.startup.*) | |||
| *(.text .text.*) | |||
| *(.gnu.linkonce.t.*) | |||
| } >rom | |||
| .fini : | |||
| { | |||
| KEEP (*(SORT_NONE(.fini))) | |||
| } >rom | |||
| PROVIDE (__etext = .); | |||
| PROVIDE (_etext = .); | |||
| PROVIDE (etext = .); | |||
| .rodata : | |||
| { | |||
| *(.rdata) | |||
| *(.rodata .rodata.*) | |||
| *(.gnu.linkonce.r.*) | |||
| . = ALIGN(8); | |||
| *(.srodata.cst16) | |||
| *(.srodata.cst8) | |||
| *(.srodata.cst4) | |||
| *(.srodata.cst2) | |||
| *(.srodata .srodata.*) | |||
| } >rom | |||
| . = ALIGN(4); | |||
| .preinit_array : | |||
| { | |||
| PROVIDE_HIDDEN (__preinit_array_start = .); | |||
| KEEP (*(.preinit_array)) | |||
| PROVIDE_HIDDEN (__preinit_array_end = .); | |||
| } >rom | |||
| .init_array : | |||
| { | |||
| PROVIDE_HIDDEN (__init_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) | |||
| KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) | |||
| PROVIDE_HIDDEN (__init_array_end = .); | |||
| } >rom | |||
| .fini_array : | |||
| { | |||
| PROVIDE_HIDDEN (__fini_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) | |||
| KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) | |||
| PROVIDE_HIDDEN (__fini_array_end = .); | |||
| } >rom | |||
| .ctors : | |||
| { | |||
| /* gcc uses crtbegin.o to find the start of | |||
| the constructors, so we make sure it is | |||
| first. Because this is a wildcard, it | |||
| doesn't matter if the user does not | |||
| actually link against crtbegin.o; the | |||
| linker won't look for a file to match a | |||
| wildcard. The wildcard also means that it | |||
| doesn't matter which directory crtbegin.o | |||
| is in. */ | |||
| KEEP (*crtbegin.o(.ctors)) | |||
| KEEP (*crtbegin?.o(.ctors)) | |||
| /* We don't want to include the .ctor section from | |||
| the crtend.o file until after the sorted ctors. | |||
| The .ctor section from the crtend file contains the | |||
| end of ctors marker and it must be last */ | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | |||
| KEEP (*(SORT(.ctors.*))) | |||
| KEEP (*(.ctors)) | |||
| } >rom | |||
| .dtors : | |||
| { | |||
| KEEP (*crtbegin.o(.dtors)) | |||
| KEEP (*crtbegin?.o(.dtors)) | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | |||
| KEEP (*(SORT(.dtors.*))) | |||
| KEEP (*(.dtors)) | |||
| } >rom | |||
| .lalign : | |||
| { | |||
| . = ALIGN(4); | |||
| } >rom | |||
| .dalign : | |||
| { | |||
| . = ALIGN(4); | |||
| } >ram AT>rom | |||
| .data : | |||
| { | |||
| PROVIDE( _data = . ); | |||
| *(.data .data.*) | |||
| *(.gnu.linkonce.d.*) | |||
| . = ALIGN(8); | |||
| PROVIDE( __global_pointer$ = . + 0x800 ); | |||
| *(.sdata .sdata.*) | |||
| *(.gnu.linkonce.s.*) | |||
| } >ram AT>rom | |||
| PROVIDE( _data_lma = LOADADDR(.data) ); | |||
| . = ALIGN(4); | |||
| PROVIDE( _edata = . ); | |||
| PROVIDE( edata = . ); | |||
| PROVIDE( _fbss = . ); | |||
| PROVIDE( __bss_start = . ); | |||
| .bss : | |||
| { | |||
| *(.sbss*) | |||
| *(.gnu.linkonce.sb.*) | |||
| *(.bss .bss.*) | |||
| *(.gnu.linkonce.b.*) | |||
| *(COMMON) | |||
| . = ALIGN(4); | |||
| } >ram | |||
| . = ALIGN(8); | |||
| PROVIDE( _end = . ); | |||
| PROVIDE( end = . ); | |||
| } | |||
| PROVIDE(_sp = ORIGIN(ram) + LENGTH(ram)); | |||
| PROVIDE(_heap_end = ORIGIN(ram) + LENGTH(ram)); | |||
| @ -1,156 +0,0 @@ | |||
| .section .init | |||
| .global _start | |||
| .type _start,@function | |||
| _start: | |||
| #ifndef VEXRISCV_RWMTVEC | |||
| j _crtInit | |||
| nop | |||
| nop | |||
| nop | |||
| nop | |||
| nop | |||
| nop | |||
| nop | |||
| j trap_entry | |||
| _crtInit: | |||
| #endif | |||
| .cfi_startproc | |||
| .cfi_undefined ra | |||
| .option push | |||
| .option norelax | |||
| la gp, __global_pointer$ | |||
| .option pop | |||
| la sp, _sp | |||
| #ifndef VEXRISCV_VOLATILE | |||
| /* Load data section */ | |||
| la a0, _data_lma | |||
| la a1, _data | |||
| la a2, _edata | |||
| bgeu a1, a2, 2f | |||
| 1: | |||
| lw t0, (a0) | |||
| sw t0, (a1) | |||
| addi a0, a0, 4 | |||
| addi a1, a1, 4 | |||
| bltu a1, a2, 1b | |||
| 2: | |||
| #endif | |||
| /* Clear bss section */ | |||
| la a0, __bss_start | |||
| la a1, _end | |||
| bgeu a0, a1, 2f | |||
| 1: | |||
| sw zero, (a0) | |||
| addi a0, a0, 4 | |||
| bltu a0, a1, 1b | |||
| 2: | |||
| /* Call global constructors */ | |||
| la a0, __libc_fini_array | |||
| call atexit | |||
| call __libc_init_array | |||
| auipc ra, 0 | |||
| addi sp, sp, -16 | |||
| sw ra, 8(sp) | |||
| /* Enable Interrupts and set trap vector */ | |||
| #ifndef VEXRISCV_RWMTVEC | |||
| la a0, trap_entry | |||
| csrw mtvec, a0 | |||
| #endif | |||
| li a0, 0x880 //880 enable timer + external interrupts | |||
| csrw mie, a0 | |||
| li a0, 0x1808 //1808 enable interrupts | |||
| csrw mstatus, a0 | |||
| /* argc = argv = 0 */ | |||
| li a0, 0 | |||
| li a1, 0 | |||
| call main | |||
| tail exit | |||
| 1: | |||
| j 1b | |||
| .cfi_endproc | |||
| .align 4 | |||
| .weak trap_entry | |||
| .global trap_entry | |||
| trap_entry: | |||
| addi sp, sp, -32*4 | |||
| sw x1, 1*4(sp) | |||
| sw x2, 2*4(sp) | |||
| sw x3, 3*4(sp) | |||
| sw x4, 4*4(sp) | |||
| sw x5, 5*4(sp) | |||
| sw x6, 6*4(sp) | |||
| sw x7, 7*4(sp) | |||
| sw x8, 8*4(sp) | |||
| sw x9, 9*4(sp) | |||
| sw x10, 10*4(sp) | |||
| sw x11, 11*4(sp) | |||
| sw x12, 12*4(sp) | |||
| sw x13, 13*4(sp) | |||
| sw x14, 14*4(sp) | |||
| sw x15, 15*4(sp) | |||
| sw x16, 16*4(sp) | |||
| sw x17, 17*4(sp) | |||
| sw x18, 18*4(sp) | |||
| sw x19, 19*4(sp) | |||
| sw x20, 20*4(sp) | |||
| sw x21, 21*4(sp) | |||
| sw x22, 22*4(sp) | |||
| sw x23, 23*4(sp) | |||
| sw x24, 24*4(sp) | |||
| sw x25, 25*4(sp) | |||
| sw x26, 26*4(sp) | |||
| sw x27, 27*4(sp) | |||
| sw x28, 28*4(sp) | |||
| sw x29, 29*4(sp) | |||
| sw x30, 30*4(sp) | |||
| sw x31, 31*4(sp) | |||
| call irqCallback | |||
| lw x1, 1*4(sp) | |||
| lw x2, 2*4(sp) | |||
| lw x3, 3*4(sp) | |||
| lw x4, 4*4(sp) | |||
| lw x5, 5*4(sp) | |||
| lw x6, 6*4(sp) | |||
| lw x7, 7*4(sp) | |||
| lw x8, 8*4(sp) | |||
| lw x9, 9*4(sp) | |||
| lw x10, 10*4(sp) | |||
| lw x11, 11*4(sp) | |||
| lw x12, 12*4(sp) | |||
| lw x13, 13*4(sp) | |||
| lw x14, 14*4(sp) | |||
| lw x15, 15*4(sp) | |||
| lw x16, 16*4(sp) | |||
| lw x17, 17*4(sp) | |||
| lw x18, 18*4(sp) | |||
| lw x19, 19*4(sp) | |||
| lw x20, 20*4(sp) | |||
| lw x21, 21*4(sp) | |||
| lw x22, 22*4(sp) | |||
| lw x23, 23*4(sp) | |||
| lw x24, 24*4(sp) | |||
| lw x25, 25*4(sp) | |||
| lw x26, 26*4(sp) | |||
| lw x27, 27*4(sp) | |||
| lw x28, 28*4(sp) | |||
| lw x29, 29*4(sp) | |||
| lw x30, 30*4(sp) | |||
| lw x31, 31*4(sp) | |||
| addi sp, sp, 32*4 | |||
| mret | |||
| .weak irqCallback | |||
| irqCallback: | |||
| 1: | |||
| j 1b | |||
| @ -1,137 +0,0 @@ | |||
| /* SECTIONS for volatile chip configuration, i.e. chips without flash */ | |||
| SECTIONS | |||
| { | |||
| .init : | |||
| { | |||
| KEEP (*(SORT_NONE(.init))) | |||
| } >rom | |||
| .text : | |||
| { | |||
| *(.text.unlikely .text.unlikely.*) | |||
| *(.text.startup .text.startup.*) | |||
| *(.text .text.*) | |||
| *(.gnu.linkonce.t.*) | |||
| } >rom | |||
| .fini : | |||
| { | |||
| KEEP (*(SORT_NONE(.fini))) | |||
| } >rom | |||
| PROVIDE (__etext = .); | |||
| PROVIDE (_etext = .); | |||
| PROVIDE (etext = .); | |||
| . = ALIGN(4); | |||
| .preinit_array : | |||
| { | |||
| PROVIDE_HIDDEN (__preinit_array_start = .); | |||
| KEEP (*(.preinit_array)) | |||
| PROVIDE_HIDDEN (__preinit_array_end = .); | |||
| } >rom | |||
| .init_array : | |||
| { | |||
| PROVIDE_HIDDEN (__init_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) | |||
| KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) | |||
| PROVIDE_HIDDEN (__init_array_end = .); | |||
| } >rom | |||
| .fini_array : | |||
| { | |||
| PROVIDE_HIDDEN (__fini_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) | |||
| KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) | |||
| PROVIDE_HIDDEN (__fini_array_end = .); | |||
| } >rom | |||
| .ctors : | |||
| { | |||
| /* gcc uses crtbegin.o to find the start of | |||
| the constructors, so we make sure it is | |||
| first. Because this is a wildcard, it | |||
| doesn't matter if the user does not | |||
| actually link against crtbegin.o; the | |||
| linker won't look for a file to match a | |||
| wildcard. The wildcard also means that it | |||
| doesn't matter which directory crtbegin.o | |||
| is in. */ | |||
| KEEP (*crtbegin.o(.ctors)) | |||
| KEEP (*crtbegin?.o(.ctors)) | |||
| /* We don't want to include the .ctor section from | |||
| the crtend.o file until after the sorted ctors. | |||
| The .ctor section from the crtend file contains the | |||
| end of ctors marker and it must be last */ | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | |||
| KEEP (*(SORT(.ctors.*))) | |||
| KEEP (*(.ctors)) | |||
| } >rom | |||
| .dtors : | |||
| { | |||
| KEEP (*crtbegin.o(.dtors)) | |||
| KEEP (*crtbegin?.o(.dtors)) | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | |||
| KEEP (*(SORT(.dtors.*))) | |||
| KEEP (*(.dtors)) | |||
| } >rom | |||
| .dalign : | |||
| { | |||
| . = ALIGN(4); | |||
| PROVIDE( _data = . ); | |||
| } >rom | |||
| /* RODATA is usally in ROM, however in volatile configurations this doesn't | |||
| make a lot of sense. */ | |||
| .rodata : | |||
| { | |||
| *(.rdata) | |||
| *(.rodata .rodata.*) | |||
| *(.gnu.linkonce.r.*) | |||
| } >ram | |||
| .data : | |||
| { | |||
| *(.data .data.*) | |||
| *(.gnu.linkonce.d.*) | |||
| . = ALIGN(8); | |||
| PROVIDE( __global_pointer$ = . + 0x800 ); | |||
| *(.sdata .sdata.*) | |||
| *(.gnu.linkonce.s.*) | |||
| . = ALIGN(8); | |||
| *(.srodata.cst16) | |||
| *(.srodata.cst8) | |||
| *(.srodata.cst4) | |||
| *(.srodata.cst2) | |||
| *(.srodata .srodata.*) | |||
| } >ram | |||
| . = ALIGN(4); | |||
| PROVIDE( _edata = . ); | |||
| PROVIDE( edata = . ); | |||
| PROVIDE( _fbss = . ); | |||
| PROVIDE( __bss_start = . ); | |||
| .bss : | |||
| { | |||
| *(.sbss*) | |||
| *(.gnu.linkonce.sb.*) | |||
| *(.bss .bss.*) | |||
| *(.gnu.linkonce.b.*) | |||
| *(COMMON) | |||
| . = ALIGN(4); | |||
| } >ram | |||
| . = ALIGN(8); | |||
| PROVIDE( _end = . ); | |||
| PROVIDE( end = . ); | |||
| } | |||
| PROVIDE(_sp = ORIGIN(ram) + LENGTH(ram)); | |||
| PROVIDE(_heap_end = ORIGIN(ram) + LENGTH(ram)); | |||
| @ -1,7 +0,0 @@ | |||
| #ifndef WEAK_UNDER_ALIAS_H | |||
| #define WEAK_UNDER_ALIAS_H | |||
| #define weak_under_alias(name) \ | |||
| extern __typeof (__weak_##name) name __attribute__ ((weak, alias ("__weak_"#name))) | |||
| #endif /* WEAK_UNDER_ALIAS_H */ | |||
| @ -1,60 +0,0 @@ | |||
| #include "hal.h" | |||
| #include <stddef.h> | |||
| /* Murax UART */ | |||
| typedef struct { | |||
| volatile uint32_t DATA; | |||
| volatile uint32_t STATUS; | |||
| volatile uint32_t CLOCK_DIVIDER; | |||
| volatile uint32_t FRAME_CONFIG; | |||
| } Uart_Reg; | |||
| enum UartParity { NONE = 0, EVEN = 1, ODD = 2 }; | |||
| enum UartStop { ONE = 0, TWO = 1 }; | |||
| typedef struct { | |||
| uint32_t dataLength; | |||
| enum UartParity parity; | |||
| enum UartStop stop; | |||
| uint32_t clockDivider; | |||
| } Uart_Config; | |||
| static uint32_t uart_writeAvailability(Uart_Reg* reg) | |||
| { | |||
| return (reg->STATUS >> 16) & 0xFF; | |||
| } | |||
| static void uart_write(Uart_Reg* reg, uint32_t data) | |||
| { | |||
| while (uart_writeAvailability(reg) == 0) | |||
| ; | |||
| reg->DATA = data; | |||
| } | |||
| #define UART ((Uart_Reg*)(0xF0010000)) | |||
| void hal_send(const uint8_t* in, const size_t len) { | |||
| for (size_t i = 0; i < len; i++) { | |||
| uart_write(UART, in[i]); | |||
| } | |||
| } | |||
| void hal_send_str(const char* in) | |||
| { | |||
| const char* cur = in; | |||
| while(*cur) { | |||
| uart_write(UART, *cur); | |||
| cur += 1; | |||
| } | |||
| } | |||
| __attribute__((naked)) uint64_t hal_get_time(void) | |||
| { | |||
| #define LE "\n\t" | |||
| asm volatile (LE"csrr a1, mcycleh" | |||
| LE"csrr a0, mcycle" | |||
| LE"csrr a2, mcycleh" | |||
| LE"bne a1, a2, hal_get_time" | |||
| LE"ret"); | |||
| } | |||
| @ -1,21 +0,0 @@ | |||
| #include <stdio.h> | |||
| #include <stdint.h> | |||
| #include <stddef.h> | |||
| #include <errno.h> | |||
| #undef errno | |||
| extern int errno; | |||
| #include "hal.h" | |||
| void _putchar(char c) { | |||
| hal_send((uint8_t*)&c, 1); | |||
| } | |||
| void _write(int fd, const void* ptr, size_t len) { | |||
| // Don't care about the fd. Just put everything on the UART console. | |||
| (void)fd; | |||
| hal_send(ptr, len); | |||
| } | |||
| @ -1,18 +0,0 @@ | |||
| #ifndef VECRISCV_HAL_H_ | |||
| #define VECRISCV_HAL_H_ | |||
| #include <stddef.h> | |||
| #include <stdint.h> | |||
| #include <sys/types.h> | |||
| #define printf printf_ | |||
| void hal_send(const uint8_t* in, const size_t len); | |||
| void hal_send_str(const char* in); | |||
| int printf_(const char* format, ...); | |||
| void _putchar(char c); | |||
| void _write(int fd, const void* ptr, size_t len); | |||
| #endif /* VECRISCV_HAL_H_ */ | |||
| @ -1,29 +0,0 @@ | |||
| #include <stdbool.h> | |||
| #include "hal.h" | |||
| // typedef struct { | |||
| // volatile uint32_t state; | |||
| // } My_Mem; | |||
| // #define MY_MEM ((My_Mem*)(0xF0030000)) | |||
| int main(void) | |||
| { | |||
| printf("HELLO WORLD\n"); | |||
| uint32_t state = 10000; | |||
| // uint32_t state_return; | |||
| while (1) | |||
| { | |||
| printf("State in : %i\n", state); | |||
| // MY_MEM->state = state; | |||
| // state_return = MY_MEM->state; | |||
| state = state + 1; | |||
| printf("State out: %i\n", state); | |||
| } | |||
| return 0; | |||
| } | |||
| @ -1,16 +0,0 @@ | |||
| /* Public domain. */ | |||
| #include <stddef.h> | |||
| int | |||
| memcmp (const void *str1, const void *str2, size_t count) | |||
| { | |||
| const unsigned char *s1 = str1; | |||
| const unsigned char *s2 = str2; | |||
| while (count-- > 0) | |||
| { | |||
| if (*s1++ != *s2++) | |||
| return s1[-1] < s2[-1] ? -1 : 1; | |||
| } | |||
| return 0; | |||
| } | |||
| @ -1,61 +0,0 @@ | |||
| /* Public domain. */ | |||
| #include <stddef.h> | |||
| /* | |||
| ** Copyright 2001, Travis Geiselbrecht. All rights reserved. | |||
| ** Distributed under the terms of the NewOS License. | |||
| */ | |||
| /* | |||
| * Copyright (c) 2008 Travis Geiselbrecht | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files | |||
| * (the "Software"), to deal in the Software without restriction, | |||
| * including without limitation the rights to use, copy, modify, merge, | |||
| * publish, distribute, sublicense, and/or sell copies of the Software, | |||
| * and to permit persons to whom the Software is furnished to do so, | |||
| * subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <string.h> | |||
| #include <sys/types.h> | |||
| typedef long word; | |||
| #define lsize sizeof(word) | |||
| #define lmask (lsize - 1) | |||
| void *memcpy(void *dest, const void *src, size_t count) | |||
| { | |||
| char *d = (char *)dest; | |||
| const char *s = (const char *)src; | |||
| int len; | |||
| if(count == 0 || dest == src) | |||
| return dest; | |||
| if(((long)d | (long)s) & lmask) { | |||
| // src and/or dest do not align on word boundary | |||
| if((((long)d ^ (long)s) & lmask) || (count < lsize)) | |||
| len = count; // copy the rest of the buffer with the byte mover | |||
| else | |||
| len = lsize - ((long)d & lmask); // move the ptrs up to a word boundary | |||
| count -= len; | |||
| for(; len > 0; len--) | |||
| *d++ = *s++; | |||
| } | |||
| for(len = count / lsize; len > 0; len--) { | |||
| *(word *)d = *(word *)s; | |||
| d += lsize; | |||
| s += lsize; | |||
| } | |||
| for(len = count & lmask; len > 0; len--) | |||
| *d++ = *s++; | |||
| return dest; | |||
| } | |||
| @ -1,64 +0,0 @@ | |||
| /* | |||
| ** Copyright 2005, Michael Noisternig. All rights reserved. | |||
| ** Copyright 2001, Travis Geiselbrecht. All rights reserved. | |||
| ** Distributed under the terms of the NewOS License. | |||
| */ | |||
| /* | |||
| * Copyright (c) 2008 Travis Geiselbrecht | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files | |||
| * (the "Software"), to deal in the Software without restriction, | |||
| * including without limitation the rights to use, copy, modify, merge, | |||
| * publish, distribute, sublicense, and/or sell copies of the Software, | |||
| * and to permit persons to whom the Software is furnished to do so, | |||
| * subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <string.h> | |||
| #include <sys/types.h> | |||
| // void * | |||
| // memset(void *s, int c, size_t count) | |||
| // { | |||
| // char *xs = (char *) s; | |||
| // // size_t len = (-(size_t)s) & (sizeof(size_t)-1); | |||
| // // int cc = c & 0xff; | |||
| // // if ( count > len ) { | |||
| // // count -= len; | |||
| // // cc |= cc << 8; | |||
| // // cc |= cc << 16; | |||
| // // // write to non-aligned memory byte-wise | |||
| // // for ( ; len > 0; len-- ) | |||
| // // *xs++ = c; | |||
| // // // write to aligned memory dword-wise | |||
| // // for ( len = count/sizeof(size_t); len > 0; len-- ) { | |||
| // // *((size_t *)xs) = cc; | |||
| // // xs += sizeof(size_t); | |||
| // // } | |||
| // // count &= sizeof(size_t)-1; | |||
| // // } | |||
| // // write remaining bytes | |||
| // for ( ; count > 0; count-- ) | |||
| // *xs++ = (char) c; | |||
| // return s; | |||
| // } | |||
| void * | |||
| memset (void *dest, int val, size_t len) | |||
| { | |||
| unsigned char *ptr = dest; | |||
| while (len-- > 0) | |||
| *ptr++ = (unsigned char) val; | |||
| return dest; | |||
| } | |||
| @ -1,987 +0,0 @@ | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| // \author (c) Marco Paland (info@paland.com) | |||
| // 2014-2019, PALANDesign Hannover, Germany | |||
| // | |||
| // \license The MIT License (MIT) | |||
| // | |||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| // of this software and associated documentation files (the "Software"), to deal | |||
| // in the Software without restriction, including without limitation the rights | |||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| // copies of the Software, and to permit persons to whom the Software is | |||
| // furnished to do so, subject to the following conditions: | |||
| // | |||
| // The above copyright notice and this permission notice shall be included in | |||
| // all copies or substantial portions of the Software. | |||
| // | |||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| // THE SOFTWARE. | |||
| // | |||
| // \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on | |||
| // embedded systems with a very limited resources. These routines are thread | |||
| // safe and reentrant! | |||
| // Use this instead of the bloated standard/newlib printf cause these use | |||
| // malloc for printf (and may not be thread safe). | |||
| // | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| #include <stdbool.h> | |||
| #include <stdint.h> | |||
| #include "printf.h" | |||
| // define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the | |||
| // printf_config.h header file | |||
| // default: undefined | |||
| #ifdef PRINTF_INCLUDE_CONFIG_H | |||
| #include "printf_config.h" | |||
| #endif | |||
| // 'ntoa' conversion buffer size, this must be big enough to hold one converted | |||
| // numeric number including padded zeros (dynamically created on stack) | |||
| // default: 32 byte | |||
| #ifndef PRINTF_NTOA_BUFFER_SIZE | |||
| #define PRINTF_NTOA_BUFFER_SIZE 32U | |||
| #endif | |||
| // 'ftoa' conversion buffer size, this must be big enough to hold one converted | |||
| // float number including padded zeros (dynamically created on stack) | |||
| // default: 32 byte | |||
| #ifndef PRINTF_FTOA_BUFFER_SIZE | |||
| #define PRINTF_FTOA_BUFFER_SIZE 32U | |||
| #endif | |||
| // support for the floating point type (%f) | |||
| // default: activated | |||
| // #ifndef PRINTF_DISABLE_SUPPORT_FLOAT | |||
| // #define PRINTF_SUPPORT_FLOAT | |||
| // #endif | |||
| // support for exponential floating point notation (%e/%g) | |||
| // default: activated | |||
| // #ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |||
| // #define PRINTF_SUPPORT_EXPONENTIAL | |||
| // #endif | |||
| // define the default floating point precision | |||
| // default: 6 digits | |||
| // #ifndef PRINTF_DEFAULT_FLOAT_PRECISION | |||
| // #define PRINTF_DEFAULT_FLOAT_PRECISION 6U | |||
| // #endif | |||
| // define the largest float suitable to print with %f | |||
| // default: 1e9 | |||
| // #ifndef PRINTF_MAX_FLOAT | |||
| // #define PRINTF_MAX_FLOAT 1e9 | |||
| // #endif | |||
| // support for the long long types (%llu or %p) | |||
| // default: activated | |||
| #ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG | |||
| #define PRINTF_SUPPORT_LONG_LONG | |||
| #endif | |||
| // support for the ptrdiff_t type (%t) | |||
| // ptrdiff_t is normally defined in <stddef.h> as long or long long type | |||
| // default: activated | |||
| // #ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T | |||
| // #define PRINTF_SUPPORT_PTRDIFF_T | |||
| // #endif | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| // internal flag definitions | |||
| #define FLAGS_ZEROPAD (1U << 0U) | |||
| #define FLAGS_LEFT (1U << 1U) | |||
| #define FLAGS_PLUS (1U << 2U) | |||
| #define FLAGS_SPACE (1U << 3U) | |||
| #define FLAGS_HASH (1U << 4U) | |||
| #define FLAGS_UPPERCASE (1U << 5U) | |||
| #define FLAGS_CHAR (1U << 6U) | |||
| #define FLAGS_SHORT (1U << 7U) | |||
| #define FLAGS_LONG (1U << 8U) | |||
| #define FLAGS_LONG_LONG (1U << 9U) | |||
| #define FLAGS_PRECISION (1U << 10U) | |||
| #define FLAGS_ADAPT_EXP (1U << 11U) | |||
| // import float.h for DBL_MAX | |||
| // #if defined(PRINTF_SUPPORT_FLOAT) | |||
| // #include <float.h> | |||
| // #endif | |||
| // output function type | |||
| typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); | |||
| // wrapper (used as buffer) for output function type | |||
| typedef struct { | |||
| void (*fct)(char character, void* arg); | |||
| void* arg; | |||
| } out_fct_wrap_type; | |||
| // Sometimes div modulo is not available, we implement one with shift/and/or | |||
| static int divmod(int* Qptr, int* Rptr, const int N, const int D) { | |||
| if (D == 0) { | |||
| return -1; | |||
| } | |||
| int Q = 0; | |||
| int R = 0; | |||
| for (int i = 8*sizeof(int) - 1; i >= 0; i--) { | |||
| R <<= 1; | |||
| R |= (N >> i) & 0x1; | |||
| if (R >= D) { | |||
| R -= D; | |||
| Q |= 1 << i; | |||
| } | |||
| } | |||
| *Qptr = Q; | |||
| *Rptr = R; | |||
| return 0; | |||
| } | |||
| // Sometimes div modulo is not available, we implement one with shift/and/or | |||
| static int divmod_long_long(long long* Qptr, long long* Rptr, const long long N, const int D) { | |||
| if (D == 0) { | |||
| return -1; | |||
| } | |||
| long long Q = 0; | |||
| long long R = 0; | |||
| for (long long i = 8*sizeof(long long) - 1; i >= 0; i--) { | |||
| R <<= 1; | |||
| R |= (N >> i) & 0x1; | |||
| if (R >= D) { | |||
| R -= D; | |||
| Q |= 1 << i; | |||
| } | |||
| } | |||
| *Qptr = Q; | |||
| *Rptr = R; | |||
| return 0; | |||
| } | |||
| // internal buffer output | |||
| static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) | |||
| { | |||
| if (idx < maxlen) { | |||
| ((char*)buffer)[idx] = character; | |||
| } | |||
| } | |||
| // internal null output | |||
| static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) | |||
| { | |||
| (void)character; (void)buffer; (void)idx; (void)maxlen; | |||
| } | |||
| // internal _putchar wrapper | |||
| static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) | |||
| { | |||
| (void)buffer; (void)idx; (void)maxlen; | |||
| if (character) { | |||
| _putchar(character); | |||
| } | |||
| } | |||
| // internal output function wrapper | |||
| static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) | |||
| { | |||
| (void)idx; (void)maxlen; | |||
| if (character) { | |||
| // buffer is the output fct pointer | |||
| ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); | |||
| } | |||
| } | |||
| // internal secure strlen | |||
| // \return The length of the string (excluding the terminating 0) limited by 'maxsize' | |||
| static inline unsigned int _strnlen_s(const char* str, size_t maxsize) | |||
| { | |||
| const char* s; | |||
| for (s = str; *s && maxsize--; ++s); | |||
| return (unsigned int)(s - str); | |||
| } | |||
| // internal test if char is a digit (0-9) | |||
| // \return true if char is a digit | |||
| static inline bool _is_digit(char ch) | |||
| { | |||
| return (ch >= '0') && (ch <= '9'); | |||
| } | |||
| // internal ASCII string to unsigned int conversion | |||
| static unsigned int _atoi(const char** str) | |||
| { | |||
| unsigned int i = 0U; | |||
| while (_is_digit(**str)) { | |||
| i = i * 10U + (unsigned int)(*((*str)++) - '0'); | |||
| } | |||
| return i; | |||
| } | |||
| // output the specified string in reverse, taking care of any zero-padding | |||
| static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) | |||
| { | |||
| const size_t start_idx = idx; | |||
| // pad spaces up to given width | |||
| if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { | |||
| for (size_t i = len; i < width; i++) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| // reverse string | |||
| while (len) { | |||
| out(buf[--len], buffer, idx++, maxlen); | |||
| } | |||
| // append pad spaces up to given width | |||
| if (flags & FLAGS_LEFT) { | |||
| while (idx - start_idx < width) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| return idx; | |||
| } | |||
| // internal itoa format | |||
| static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) | |||
| { | |||
| // pad leading zeros | |||
| if (!(flags & FLAGS_LEFT)) { | |||
| if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { | |||
| width--; | |||
| } | |||
| while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { | |||
| buf[len++] = '0'; | |||
| } | |||
| while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { | |||
| buf[len++] = '0'; | |||
| } | |||
| } | |||
| // handle hash | |||
| if (flags & FLAGS_HASH) { | |||
| if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { | |||
| len--; | |||
| if (len && (base == 16U)) { | |||
| len--; | |||
| } | |||
| } | |||
| if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { | |||
| buf[len++] = 'x'; | |||
| } | |||
| else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { | |||
| buf[len++] = 'X'; | |||
| } | |||
| else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { | |||
| buf[len++] = 'b'; | |||
| } | |||
| if (len < PRINTF_NTOA_BUFFER_SIZE) { | |||
| buf[len++] = '0'; | |||
| } | |||
| } | |||
| if (len < PRINTF_NTOA_BUFFER_SIZE) { | |||
| if (negative) { | |||
| buf[len++] = '-'; | |||
| } | |||
| else if (flags & FLAGS_PLUS) { | |||
| buf[len++] = '+'; // ignore the space if the '+' exists | |||
| } | |||
| else if (flags & FLAGS_SPACE) { | |||
| buf[len++] = ' '; | |||
| } | |||
| } | |||
| return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); | |||
| } | |||
| // internal itoa for 'long' type | |||
| static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) | |||
| { | |||
| char buf[PRINTF_NTOA_BUFFER_SIZE]; | |||
| size_t len = 0U; | |||
| int q, r; | |||
| // no hash for 0 values | |||
| if (!value) { | |||
| flags &= ~FLAGS_HASH; | |||
| } | |||
| // write if precision != 0 and value is != 0 | |||
| if (!(flags & FLAGS_PRECISION) || value) { | |||
| q = 0, r = 0; | |||
| len = 0; | |||
| do { | |||
| divmod(&q, &r, value, base); | |||
| const char digit = (char)(r); | |||
| // buf[idx2++] = '0' + digit; | |||
| buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; | |||
| value = q; | |||
| } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); | |||
| // while (idx2 > 0) { | |||
| // _putchar(buf[--idx2]); | |||
| // written++; | |||
| // } | |||
| // idx++; | |||
| // do { | |||
| // const char digit = (char)(value % base); | |||
| // buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; | |||
| // value /= base; | |||
| // } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); | |||
| } | |||
| return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); | |||
| } | |||
| // // internal itoa for 'long long' type | |||
| #if defined(PRINTF_SUPPORT_LONG_LONG) | |||
| static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) | |||
| { | |||
| char buf[PRINTF_NTOA_BUFFER_SIZE]; | |||
| size_t len = 0U; | |||
| long long q, r; | |||
| // no hash for 0 values | |||
| if (!value) { | |||
| flags &= ~FLAGS_HASH; | |||
| } | |||
| // write if precision != 0 and value is != 0 | |||
| if (!(flags & FLAGS_PRECISION) || value) { | |||
| q = 0, r = 0; | |||
| len = 0; | |||
| do { | |||
| divmod_long_long(&q, &r, value, base); | |||
| const char digit = (char)(r); | |||
| // buf[idx2++] = '0' + digit; | |||
| buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; | |||
| value = q; | |||
| } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); | |||
| // do { | |||
| // const char digit = (char)(value % base); | |||
| // buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; | |||
| // value /= base; | |||
| // } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); | |||
| } | |||
| return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); | |||
| } | |||
| #endif // PRINTF_SUPPORT_LONG_LONG | |||
| // #if defined(PRINTF_SUPPORT_FLOAT) | |||
| // | |||
| // #if defined(PRINTF_SUPPORT_EXPONENTIAL) | |||
| // // forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT | |||
| // static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); | |||
| // #endif | |||
| // | |||
| // | |||
| // // internal ftoa for fixed decimal floating point | |||
| // static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) | |||
| // { | |||
| // char buf[PRINTF_FTOA_BUFFER_SIZE]; | |||
| // size_t len = 0U; | |||
| // double diff = 0.0; | |||
| // | |||
| // // powers of 10 | |||
| // static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; | |||
| // | |||
| // // test for special values | |||
| // if (value != value) | |||
| // return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); | |||
| // if (value < -DBL_MAX) | |||
| // return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); | |||
| // if (value > DBL_MAX) | |||
| // return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); | |||
| // | |||
| // // test for very large values | |||
| // // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad | |||
| // if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { | |||
| // #if defined(PRINTF_SUPPORT_EXPONENTIAL) | |||
| // return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); | |||
| // #else | |||
| // return 0U; | |||
| // #endif | |||
| // } | |||
| // | |||
| // // test for negative | |||
| // bool negative = false; | |||
| // if (value < 0) { | |||
| // negative = true; | |||
| // value = 0 - value; | |||
| // } | |||
| // | |||
| // // set default precision, if not set explicitly | |||
| // if (!(flags & FLAGS_PRECISION)) { | |||
| // prec = PRINTF_DEFAULT_FLOAT_PRECISION; | |||
| // } | |||
| // // limit precision to 9, cause a prec >= 10 can lead to overflow errors | |||
| // while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { | |||
| // buf[len++] = '0'; | |||
| // prec--; | |||
| // } | |||
| // | |||
| // int whole = (int)value; | |||
| // double tmp = (value - whole) * pow10[prec]; | |||
| // unsigned long frac = (unsigned long)tmp; | |||
| // diff = tmp - frac; | |||
| // | |||
| // if (diff > 0.5) { | |||
| // ++frac; | |||
| // // handle rollover, e.g. case 0.99 with prec 1 is 1.0 | |||
| // if (frac >= pow10[prec]) { | |||
| // frac = 0; | |||
| // ++whole; | |||
| // } | |||
| // } | |||
| // else if (diff < 0.5) { | |||
| // } | |||
| // else if ((frac == 0U) || (frac & 1U)) { | |||
| // // if halfway, round up if odd OR if last digit is 0 | |||
| // ++frac; | |||
| // } | |||
| // | |||
| // if (prec == 0U) { | |||
| // diff = value - (double)whole; | |||
| // if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { | |||
| // // exactly 0.5 and ODD, then round up | |||
| // // 1.5 -> 2, but 2.5 -> 2 | |||
| // ++whole; | |||
| // } | |||
| // } | |||
| // else { | |||
| // unsigned int count = prec; | |||
| // // now do fractional part, as an unsigned number | |||
| // while (len < PRINTF_FTOA_BUFFER_SIZE) { | |||
| // --count; | |||
| // buf[len++] = (char)(48U + (frac % 10U)); | |||
| // if (!(frac /= 10U)) { | |||
| // break; | |||
| // } | |||
| // } | |||
| // // add extra 0s | |||
| // while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { | |||
| // buf[len++] = '0'; | |||
| // } | |||
| // if (len < PRINTF_FTOA_BUFFER_SIZE) { | |||
| // // add decimal | |||
| // buf[len++] = '.'; | |||
| // } | |||
| // } | |||
| // | |||
| // // do whole part, number is reversed | |||
| // while (len < PRINTF_FTOA_BUFFER_SIZE) { | |||
| // buf[len++] = (char)(48 + (whole % 10)); | |||
| // if (!(whole /= 10)) { | |||
| // break; | |||
| // } | |||
| // } | |||
| // | |||
| // // pad leading zeros | |||
| // if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { | |||
| // if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { | |||
| // width--; | |||
| // } | |||
| // while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { | |||
| // buf[len++] = '0'; | |||
| // } | |||
| // } | |||
| // | |||
| // if (len < PRINTF_FTOA_BUFFER_SIZE) { | |||
| // if (negative) { | |||
| // buf[len++] = '-'; | |||
| // } | |||
| // else if (flags & FLAGS_PLUS) { | |||
| // buf[len++] = '+'; // ignore the space if the '+' exists | |||
| // } | |||
| // else if (flags & FLAGS_SPACE) { | |||
| // buf[len++] = ' '; | |||
| // } | |||
| // } | |||
| // | |||
| // return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); | |||
| // } | |||
| // | |||
| // | |||
| // #if defined(PRINTF_SUPPORT_EXPONENTIAL) | |||
| // // internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com> | |||
| // static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) | |||
| // { | |||
| // // check for NaN and special values | |||
| // if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { | |||
| // return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); | |||
| // } | |||
| // | |||
| // // determine the sign | |||
| // const bool negative = value < 0; | |||
| // if (negative) { | |||
| // value = -value; | |||
| // } | |||
| // | |||
| // // default precision | |||
| // if (!(flags & FLAGS_PRECISION)) { | |||
| // prec = PRINTF_DEFAULT_FLOAT_PRECISION; | |||
| // } | |||
| // | |||
| // // determine the decimal exponent | |||
| // // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) | |||
| // union { | |||
| // uint64_t U; | |||
| // double F; | |||
| // } conv; | |||
| // | |||
| // conv.F = value; | |||
| // int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 | |||
| // conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) | |||
| // // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 | |||
| // int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); | |||
| // // now we want to compute 10^expval but we want to be sure it won't overflow | |||
| // exp2 = (int)(expval * 3.321928094887362 + 0.5); | |||
| // const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; | |||
| // const double z2 = z * z; | |||
| // conv.U = (uint64_t)(exp2 + 1023) << 52U; | |||
| // // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex | |||
| // conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); | |||
| // // correct for rounding errors | |||
| // if (value < conv.F) { | |||
| // expval--; | |||
| // conv.F /= 10; | |||
| // } | |||
| // | |||
| // // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters | |||
| // unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; | |||
| // | |||
| // // in "%g" mode, "prec" is the number of *significant figures* not decimals | |||
| // if (flags & FLAGS_ADAPT_EXP) { | |||
| // // do we want to fall-back to "%f" mode? | |||
| // if ((value >= 1e-4) && (value < 1e6)) { | |||
| // if ((int)prec > expval) { | |||
| // prec = (unsigned)((int)prec - expval - 1); | |||
| // } | |||
| // else { | |||
| // prec = 0; | |||
| // } | |||
| // flags |= FLAGS_PRECISION; // make sure _ftoa respects precision | |||
| // // no characters in exponent | |||
| // minwidth = 0U; | |||
| // expval = 0; | |||
| // } | |||
| // else { | |||
| // // we use one sigfig for the whole part | |||
| // if ((prec > 0) && (flags & FLAGS_PRECISION)) { | |||
| // --prec; | |||
| // } | |||
| // } | |||
| // } | |||
| // | |||
| // // will everything fit? | |||
| // unsigned int fwidth = width; | |||
| // if (width > minwidth) { | |||
| // // we didn't fall-back so subtract the characters required for the exponent | |||
| // fwidth -= minwidth; | |||
| // } else { | |||
| // // not enough characters, so go back to default sizing | |||
| // fwidth = 0U; | |||
| // } | |||
| // if ((flags & FLAGS_LEFT) && minwidth) { | |||
| // // if we're padding on the right, DON'T pad the floating part | |||
| // fwidth = 0U; | |||
| // } | |||
| // | |||
| // // rescale the float value | |||
| // if (expval) { | |||
| // value /= conv.F; | |||
| // } | |||
| // | |||
| // // output the floating part | |||
| // const size_t start_idx = idx; | |||
| // idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); | |||
| // | |||
| // // output the exponent part | |||
| // if (minwidth) { | |||
| // // output the exponential symbol | |||
| // out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); | |||
| // // output the exponent value | |||
| // idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); | |||
| // // might need to right-pad spaces | |||
| // if (flags & FLAGS_LEFT) { | |||
| // while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); | |||
| // } | |||
| // } | |||
| // return idx; | |||
| // } | |||
| // #endif // PRINTF_SUPPORT_EXPONENTIAL | |||
| // #endif // PRINTF_SUPPORT_FLOAT | |||
| // internal vsnprintf | |||
| static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) | |||
| { | |||
| unsigned int flags, width, precision, n; | |||
| size_t idx = 0U; | |||
| if (!buffer) { | |||
| // use null output function | |||
| out = _out_null; | |||
| } | |||
| while (*format) | |||
| { | |||
| // format specifier? %[flags][width][.precision][length] | |||
| if (*format != '%') { | |||
| // no | |||
| out(*format, buffer, idx++, maxlen); | |||
| format++; | |||
| continue; | |||
| } | |||
| else { | |||
| // yes, evaluate it | |||
| format++; | |||
| } | |||
| // evaluate flags | |||
| flags = 0U; | |||
| do { | |||
| switch (*format) { | |||
| case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; | |||
| case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; | |||
| case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; | |||
| case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; | |||
| case '#': flags |= FLAGS_HASH; format++; n = 1U; break; | |||
| default : n = 0U; break; | |||
| } | |||
| } while (n); | |||
| // evaluate width field | |||
| width = 0U; | |||
| if (_is_digit(*format)) { | |||
| width = _atoi(&format); | |||
| } | |||
| else if (*format == '*') { | |||
| const int w = va_arg(va, int); | |||
| if (w < 0) { | |||
| flags |= FLAGS_LEFT; // reverse padding | |||
| width = (unsigned int)-w; | |||
| } | |||
| else { | |||
| width = (unsigned int)w; | |||
| } | |||
| format++; | |||
| } | |||
| // evaluate precision field | |||
| precision = 0U; | |||
| if (*format == '.') { | |||
| flags |= FLAGS_PRECISION; | |||
| format++; | |||
| if (_is_digit(*format)) { | |||
| precision = _atoi(&format); | |||
| } | |||
| else if (*format == '*') { | |||
| const int prec = (int)va_arg(va, int); | |||
| precision = prec > 0 ? (unsigned int)prec : 0U; | |||
| format++; | |||
| } | |||
| } | |||
| // evaluate length field | |||
| switch (*format) { | |||
| case 'l' : | |||
| flags |= FLAGS_LONG; | |||
| format++; | |||
| if (*format == 'l') { | |||
| flags |= FLAGS_LONG_LONG; | |||
| format++; | |||
| } | |||
| break; | |||
| case 'h' : | |||
| flags |= FLAGS_SHORT; | |||
| format++; | |||
| if (*format == 'h') { | |||
| flags |= FLAGS_CHAR; | |||
| format++; | |||
| } | |||
| break; | |||
| // #if defined(PRINTF_SUPPORT_PTRDIFF_T) | |||
| // case 't' : | |||
| // flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); | |||
| // format++; | |||
| // break; | |||
| // #endif | |||
| case 'j' : | |||
| flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); | |||
| format++; | |||
| break; | |||
| case 'z' : | |||
| flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); | |||
| format++; | |||
| break; | |||
| default : | |||
| break; | |||
| } | |||
| // evaluate specifier | |||
| switch (*format) { | |||
| case 'd' : | |||
| case 'i' : | |||
| case 'u' : | |||
| case 'x' : | |||
| case 'X' : | |||
| case 'o' : | |||
| case 'b' : { | |||
| // set the base | |||
| unsigned int base; | |||
| if (*format == 'x' || *format == 'X') { | |||
| base = 16U; | |||
| } | |||
| else if (*format == 'o') { | |||
| base = 8U; | |||
| } | |||
| else if (*format == 'b') { | |||
| base = 2U; | |||
| } | |||
| else { | |||
| base = 10U; | |||
| flags &= ~FLAGS_HASH; // no hash for dec format | |||
| } | |||
| // uppercase | |||
| if (*format == 'X') { | |||
| flags |= FLAGS_UPPERCASE; | |||
| } | |||
| // no plus or space flag for u, x, X, o, b | |||
| if ((*format != 'i') && (*format != 'd')) { | |||
| flags &= ~(FLAGS_PLUS | FLAGS_SPACE); | |||
| } | |||
| // ignore '0' flag when precision is given | |||
| if (flags & FLAGS_PRECISION) { | |||
| flags &= ~FLAGS_ZEROPAD; | |||
| } | |||
| // convert the integer | |||
| if ((*format == 'i') || (*format == 'd')) { | |||
| // signed | |||
| if (flags & FLAGS_LONG_LONG) { | |||
| #if defined(PRINTF_SUPPORT_LONG_LONG) | |||
| const long long value = va_arg(va, long long); | |||
| idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); | |||
| #endif | |||
| } | |||
| else if (flags & FLAGS_LONG) { | |||
| const long value = va_arg(va, long); | |||
| idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); | |||
| } | |||
| else { | |||
| const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); | |||
| idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); | |||
| } | |||
| } | |||
| else { | |||
| // unsigned | |||
| if (flags & FLAGS_LONG_LONG) { | |||
| #if defined(PRINTF_SUPPORT_LONG_LONG) | |||
| idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); | |||
| #endif | |||
| } | |||
| else if (flags & FLAGS_LONG) { | |||
| idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); | |||
| } | |||
| else { | |||
| const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); | |||
| idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); | |||
| } | |||
| } | |||
| format++; | |||
| break; | |||
| } | |||
| // #if defined(PRINTF_SUPPORT_FLOAT) | |||
| // case 'f' : | |||
| // case 'F' : | |||
| // if (*format == 'F') flags |= FLAGS_UPPERCASE; | |||
| // idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); | |||
| // format++; | |||
| // break; | |||
| // #if defined(PRINTF_SUPPORT_EXPONENTIAL) | |||
| // case 'e': | |||
| // case 'E': | |||
| // case 'g': | |||
| // case 'G': | |||
| // if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; | |||
| // if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; | |||
| // idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); | |||
| // format++; | |||
| // break; | |||
| // #endif // PRINTF_SUPPORT_EXPONENTIAL | |||
| // #endif // PRINTF_SUPPORT_FLOAT | |||
| case 'c' : { | |||
| unsigned int l = 1U; | |||
| // pre padding | |||
| if (!(flags & FLAGS_LEFT)) { | |||
| while (l++ < width) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| // char output | |||
| out((char)va_arg(va, int), buffer, idx++, maxlen); | |||
| // post padding | |||
| if (flags & FLAGS_LEFT) { | |||
| while (l++ < width) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| format++; | |||
| break; | |||
| } | |||
| case 's' : { | |||
| const char* p = va_arg(va, char*); | |||
| unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); | |||
| // pre padding | |||
| if (flags & FLAGS_PRECISION) { | |||
| l = (l < precision ? l : precision); | |||
| } | |||
| if (!(flags & FLAGS_LEFT)) { | |||
| while (l++ < width) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| // string output | |||
| while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { | |||
| out(*(p++), buffer, idx++, maxlen); | |||
| } | |||
| // post padding | |||
| if (flags & FLAGS_LEFT) { | |||
| while (l++ < width) { | |||
| out(' ', buffer, idx++, maxlen); | |||
| } | |||
| } | |||
| format++; | |||
| break; | |||
| } | |||
| case 'p' : { | |||
| width = sizeof(void*) * 2U; | |||
| flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; | |||
| #if defined(PRINTF_SUPPORT_LONG_LONG) | |||
| const bool is_ll = sizeof(uintptr_t) == sizeof(long long); | |||
| if (is_ll) { | |||
| idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); | |||
| } | |||
| else { | |||
| #endif | |||
| idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); | |||
| #if defined(PRINTF_SUPPORT_LONG_LONG) | |||
| } | |||
| #endif | |||
| format++; | |||
| break; | |||
| } | |||
| case '%' : | |||
| out('%', buffer, idx++, maxlen); | |||
| format++; | |||
| break; | |||
| default : | |||
| out(*format, buffer, idx++, maxlen); | |||
| format++; | |||
| break; | |||
| } | |||
| } | |||
| // termination | |||
| out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); | |||
| // return written chars without terminating \0 | |||
| return (int)idx; | |||
| } | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| int printf_(const char* format, ...) | |||
| { | |||
| va_list va; | |||
| va_start(va, format); | |||
| char buffer[1]; | |||
| const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); | |||
| va_end(va); | |||
| return ret; | |||
| } | |||
| int sprintf_(char* buffer, const char* format, ...) | |||
| { | |||
| va_list va; | |||
| va_start(va, format); | |||
| const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); | |||
| va_end(va); | |||
| return ret; | |||
| } | |||
| int snprintf_(char* buffer, size_t count, const char* format, ...) | |||
| { | |||
| va_list va; | |||
| va_start(va, format); | |||
| const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); | |||
| va_end(va); | |||
| return ret; | |||
| } | |||
| int vprintf_(const char* format, va_list va) | |||
| { | |||
| char buffer[1]; | |||
| return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); | |||
| } | |||
| int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) | |||
| { | |||
| return _vsnprintf(_out_buffer, buffer, count, format, va); | |||
| } | |||
| int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) | |||
| { | |||
| va_list va; | |||
| va_start(va, format); | |||
| const out_fct_wrap_type out_fct_wrap = { out, arg }; | |||
| const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); | |||
| va_end(va); | |||
| return ret; | |||
| } | |||
| @ -1,121 +0,0 @@ | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| // \author (c) Marco Paland (info@paland.com) | |||
| // 2014-2019, PALANDesign Hannover, Germany | |||
| // | |||
| // \license The MIT License (MIT) | |||
| // | |||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| // of this software and associated documentation files (the "Software"), to deal | |||
| // in the Software without restriction, including without limitation the rights | |||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| // copies of the Software, and to permit persons to whom the Software is | |||
| // furnished to do so, subject to the following conditions: | |||
| // | |||
| // The above copyright notice and this permission notice shall be included in | |||
| // all copies or substantial portions of the Software. | |||
| // | |||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| // THE SOFTWARE. | |||
| // | |||
| // \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on | |||
| // embedded systems with a very limited resources. | |||
| // Use this instead of bloated standard/newlib printf. | |||
| // These routines are thread safe and reentrant. | |||
| // | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| #ifndef _PRINTF_H_ | |||
| #define _PRINTF_H_ | |||
| #include <stdarg.h> | |||
| #include <stddef.h> | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #define PRINTF_DISABLE_SUPPORT_FLOAT | |||
| #define PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |||
| // #define PRINTF_DISABLE_SUPPORT_LONG_LONG | |||
| #define PRINTF_DISABLE_SUPPORT_PTRDIFF_T | |||
| /** | |||
| * Output a character to a custom device like UART, used by the printf() function | |||
| * This function is declared here only. You have to write your custom implementation somewhere | |||
| * \param character Character to output | |||
| */ | |||
| void _putchar(char character); | |||
| /** | |||
| * Tiny printf implementation | |||
| * You have to implement _putchar if you use printf() | |||
| * To avoid conflicts with the regular printf() API it is overridden by macro defines | |||
| * and internal underscore-appended functions like printf_() are used | |||
| * \param format A string that specifies the format of the output | |||
| * \return The number of characters that are written into the array, not counting the terminating null character | |||
| */ | |||
| #define printf printf_ | |||
| int printf_(const char* format, ...); | |||
| /** | |||
| * Tiny sprintf implementation | |||
| * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! | |||
| * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! | |||
| * \param format A string that specifies the format of the output | |||
| * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character | |||
| */ | |||
| #define sprintf sprintf_ | |||
| int sprintf_(char* buffer, const char* format, ...); | |||
| /** | |||
| * Tiny snprintf/vsnprintf implementation | |||
| * \param buffer A pointer to the buffer where to store the formatted string | |||
| * \param count The maximum number of characters to store in the buffer, including a terminating null character | |||
| * \param format A string that specifies the format of the output | |||
| * \param va A value identifying a variable arguments list | |||
| * \return The number of characters that COULD have been written into the buffer, not counting the terminating | |||
| * null character. A value equal or larger than count indicates truncation. Only when the returned value | |||
| * is non-negative and less than count, the string has been completely written. | |||
| */ | |||
| #define snprintf snprintf_ | |||
| #define vsnprintf vsnprintf_ | |||
| int snprintf_(char* buffer, size_t count, const char* format, ...); | |||
| int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); | |||
| /** | |||
| * Tiny vprintf implementation | |||
| * \param format A string that specifies the format of the output | |||
| * \param va A value identifying a variable arguments list | |||
| * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character | |||
| */ | |||
| #define vprintf vprintf_ | |||
| int vprintf_(const char* format, va_list va); | |||
| /** | |||
| * printf with output function | |||
| * You may use this as dynamic alternative to printf() with its fixed _putchar() output | |||
| * \param out An output function which takes one character and an argument pointer | |||
| * \param arg An argument pointer for user data passed to output function | |||
| * \param format A string that specifies the format of the output | |||
| * \return The number of characters that are sent to the output function, not counting the terminating null character | |||
| */ | |||
| int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // _PRINTF_H_ | |||
| @ -1,137 +0,0 @@ | |||
| /* SECTIONS for volatile chip configuration, i.e. chips without flash */ | |||
| SECTIONS | |||
| { | |||
| .init : | |||
| { | |||
| KEEP (*(SORT_NONE(.init))) | |||
| } >rom | |||
| .text : | |||
| { | |||
| *(.text.unlikely .text.unlikely.*) | |||
| *(.text.startup .text.startup.*) | |||
| *(.text .text.*) | |||
| *(.gnu.linkonce.t.*) | |||
| } >rom | |||
| .fini : | |||
| { | |||
| KEEP (*(SORT_NONE(.fini))) | |||
| } >rom | |||
| PROVIDE (__etext = .); | |||
| PROVIDE (_etext = .); | |||
| PROVIDE (etext = .); | |||
| . = ALIGN(4); | |||
| .preinit_array : | |||
| { | |||
| PROVIDE_HIDDEN (__preinit_array_start = .); | |||
| KEEP (*(.preinit_array)) | |||
| PROVIDE_HIDDEN (__preinit_array_end = .); | |||
| } >rom | |||
| .init_array : | |||
| { | |||
| PROVIDE_HIDDEN (__init_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) | |||
| KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) | |||
| PROVIDE_HIDDEN (__init_array_end = .); | |||
| } >rom | |||
| .fini_array : | |||
| { | |||
| PROVIDE_HIDDEN (__fini_array_start = .); | |||
| KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) | |||
| KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) | |||
| PROVIDE_HIDDEN (__fini_array_end = .); | |||
| } >rom | |||
| .ctors : | |||
| { | |||
| /* gcc uses crtbegin.o to find the start of | |||
| the constructors, so we make sure it is | |||
| first. Because this is a wildcard, it | |||
| doesn't matter if the user does not | |||
| actually link against crtbegin.o; the | |||
| linker won't look for a file to match a | |||
| wildcard. The wildcard also means that it | |||
| doesn't matter which directory crtbegin.o | |||
| is in. */ | |||
| KEEP (*crtbegin.o(.ctors)) | |||
| KEEP (*crtbegin?.o(.ctors)) | |||
| /* We don't want to include the .ctor section from | |||
| the crtend.o file until after the sorted ctors. | |||
| The .ctor section from the crtend file contains the | |||
| end of ctors marker and it must be last */ | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | |||
| KEEP (*(SORT(.ctors.*))) | |||
| KEEP (*(.ctors)) | |||
| } >rom | |||
| .dtors : | |||
| { | |||
| KEEP (*crtbegin.o(.dtors)) | |||
| KEEP (*crtbegin?.o(.dtors)) | |||
| KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | |||
| KEEP (*(SORT(.dtors.*))) | |||
| KEEP (*(.dtors)) | |||
| } >rom | |||
| .dalign : | |||
| { | |||
| . = ALIGN(4); | |||
| PROVIDE( _data = . ); | |||
| } >rom | |||
| /* RODATA is usally in ROM, however in volatile configurations this doesn't | |||
| make a lot of sense. */ | |||
| .rodata : | |||
| { | |||
| *(.rdata) | |||
| *(.rodata .rodata.*) | |||
| *(.gnu.linkonce.r.*) | |||
| } >ram | |||
| .data : | |||
| { | |||
| *(.data .data.*) | |||
| *(.gnu.linkonce.d.*) | |||
| . = ALIGN(8); | |||
| PROVIDE( __global_pointer$ = . + 0x800 ); | |||
| *(.sdata .sdata.*) | |||
| *(.gnu.linkonce.s.*) | |||
| . = ALIGN(8); | |||
| *(.srodata.cst16) | |||
| *(.srodata.cst8) | |||
| *(.srodata.cst4) | |||
| *(.srodata.cst2) | |||
| *(.srodata .srodata.*) | |||
| } >ram | |||
| . = ALIGN(4); | |||
| PROVIDE( _edata = . ); | |||
| PROVIDE( edata = . ); | |||
| PROVIDE( _fbss = . ); | |||
| PROVIDE( __bss_start = . ); | |||
| .bss : | |||
| { | |||
| *(.sbss*) | |||
| *(.gnu.linkonce.sb.*) | |||
| *(.bss .bss.*) | |||
| *(.gnu.linkonce.b.*) | |||
| *(COMMON) | |||
| . = ALIGN(4); | |||
| } >ram | |||
| . = ALIGN(8); | |||
| PROVIDE( _end = . ); | |||
| PROVIDE( end = . ); | |||
| } | |||
| PROVIDE(_sp = ORIGIN(ram) + LENGTH(ram)); | |||
| PROVIDE(_heap_end = ORIGIN(ram) + LENGTH(ram)); | |||
| @ -0,0 +1,32 @@ | |||
| TOPMOD := PQVexRiscvUlx3s | |||
| CHIP := 85k | |||
| PACKAGE := CABGA381 | |||
| CONSTRAINTS := ulx3s_v20_constraints | |||
| VLOGFIL := $(TOPMOD).v | |||
| PROGPATH := ~/bin/ujprog/ujprog | |||
| .PHONY: all | |||
| all: $(TOPMOD).bit | |||
| .PHONY: clean | |||
| clean: | |||
| rm -rf $(TOPMOD).json $(TOPMOD).config $(TOPMOD).bit | |||
| $(TOPMOD).bit: $(TOPMOD).config | |||
| ecppack $(TOPMOD).config $(TOPMOD).bit | |||
| $(TOPMOD).config: $(TOPMOD).json | |||
| nextpnr-ecp5 \ | |||
| --$(CHIP) \ | |||
| --package $(PACKAGE) \ | |||
| --json $(TOPMOD).json \ | |||
| --lpf-allow-unconstrained \ | |||
| --lpf $(CONSTRAINTS).lpf \ | |||
| --textcfg $(TOPMOD).config | |||
| $(TOPMOD).json: $(TOPMOD).v | |||
| yosys -q -l $(TOPMOD)_yosys.log -p "synth_ecp5 -top $(TOPMOD) -json $(TOPMOD).json" $(TOPMOD).v | |||
| prog: $(TOPMOD).bit | |||
| sudo $(PROGPATH) $(TOPMOD).bit | |||
| @ -0,0 +1,2 @@ | |||
| read_verilog PQVexRiscvUlx3s.v | |||
| synth_ecp5 -json PQVexRiscvUlx3s.json | |||
| @ -0,0 +1,452 @@ | |||
| BLOCK RESETPATHS; | |||
| BLOCK ASYNCPATHS; | |||
| ## ULX3S v2.x.x and v3.0.x | |||
| # The clock "usb" and "gpdi" sheet | |||
| LOCATE COMP "io_mainClock" SITE "G2"; | |||
| IOBUF PORT "io_mainClock" PULLMODE=NONE IO_TYPE=LVCMOS33; | |||
| FREQUENCY PORT "io_mainClock" 25 MHZ; | |||
| # JTAG and SPI FLASH voltage 3.3V and options to boot from SPI flash | |||
| # write to FLASH possible any time from JTAG: | |||
| # SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=ENABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE; | |||
| # write to FLASH possible from user bitstream: | |||
| # SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=DISABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE; | |||
| ## USBSERIAL FTDI-FPGA serial port "usb" sheet | |||
| LOCATE COMP "io_uart_txd" SITE "L4"; # FPGA transmits to ftdi | |||
| LOCATE COMP "io_uart_rxd" SITE "M1"; # FPGA receives from ftdi | |||
| LOCATE COMP "ftdi_nrts" SITE "M3"; # FPGA receives | |||
| LOCATE COMP "ftdi_ndtr" SITE "N1"; # FPGA receives | |||
| LOCATE COMP "ftdi_txden" SITE "L3"; # FPGA receives | |||
| IOBUF PORT "io_uart_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "io_uart_rxd" PULLMODE=UP IO_TYPE=LVCMOS33; | |||
| IOBUF PORT "ftdi_nrts" PULLMODE=UP IO_TYPE=LVCMOS33; | |||
| IOBUF PORT "ftdi_ndtr" PULLMODE=UP IO_TYPE=LVCMOS33; | |||
| IOBUF PORT "ftdi_txden" PULLMODE=UP IO_TYPE=LVCMOS33; | |||
| ## LED indicators "blinkey" and "gpio" sheet | |||
| LOCATE COMP "led[7]" SITE "H3"; | |||
| LOCATE COMP "led[6]" SITE "E1"; | |||
| LOCATE COMP "led[5]" SITE "E2"; | |||
| LOCATE COMP "led[4]" SITE "D1"; | |||
| LOCATE COMP "led[3]" SITE "D2"; | |||
| LOCATE COMP "led[2]" SITE "C1"; | |||
| LOCATE COMP "led[1]" SITE "C2"; | |||
| LOCATE COMP "led[0]" SITE "B2"; | |||
| IOBUF PORT "led[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "led[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## Pushbuttons "blinkey", "flash", "power", "gpdi" sheet | |||
| LOCATE COMP "btn[0]" SITE "D6"; # BTN_PWRn (inverted logic) | |||
| LOCATE COMP "io_asyncReset" SITE "R1"; # FIRE1 | |||
| LOCATE COMP "btn[2]" SITE "T1"; # FIRE2 | |||
| LOCATE COMP "btn[3]" SITE "R18"; # UP W1->R18 | |||
| LOCATE COMP "btn[4]" SITE "V1"; # DOWN | |||
| LOCATE COMP "btn[5]" SITE "U1"; # LEFT | |||
| LOCATE COMP "btn[6]" SITE "H16"; # RIGHT Y2->H16 | |||
| IOBUF PORT "btn[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "io_asyncReset" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "btn[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "btn[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "btn[4]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "btn[5]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "btn[6]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## DIP switch "blinkey", "gpio" sheet | |||
| LOCATE COMP "sw[0]" SITE "E8"; # SW1 | |||
| LOCATE COMP "sw[1]" SITE "D8"; # SW2 | |||
| LOCATE COMP "sw[2]" SITE "D7"; # SW3 | |||
| LOCATE COMP "sw[3]" SITE "E7"; # SW4 | |||
| IOBUF PORT "sw[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sw[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sw[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sw[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## SPI OLED DISPLAY SSD1331 (Color) or SSD1306 (B/W) "blinkey", "usb" sheet | |||
| LOCATE COMP "oled_clk" SITE "P4"; | |||
| LOCATE COMP "oled_mosi" SITE "P3"; | |||
| LOCATE COMP "oled_dc" SITE "P1"; | |||
| LOCATE COMP "oled_resn" SITE "P2"; | |||
| LOCATE COMP "oled_csn" SITE "N2"; | |||
| IOBUF PORT "oled_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "oled_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "oled_dc" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "oled_resn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "oled_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## SPI Flash chip "flash" sheet | |||
| LOCATE COMP "flash_csn" SITE "R2"; | |||
| LOCATE COMP "flash_clk" SITE "U3"; | |||
| LOCATE COMP "flash_mosi" SITE "W2"; | |||
| LOCATE COMP "flash_miso" SITE "V2"; | |||
| LOCATE COMP "flash_holdn" SITE "W1"; | |||
| LOCATE COMP "flash_wpn" SITE "Y2"; | |||
| #LOCATE COMP "flash_csspin" SITE "AJ3"; | |||
| #LOCATE COMP "flash_initn" SITE "AG4"; | |||
| #LOCATE COMP "flash_done" SITE "AJ4"; | |||
| #LOCATE COMP "flash_programn" SITE "AH4"; | |||
| #LOCATE COMP "flash_cfg_select[0]" SITE "AM4"; | |||
| #LOCATE COMP "flash_cfg_select[1]" SITE "AL4"; | |||
| #LOCATE COMP "flash_cfg_select[2]" SITE "AK4"; | |||
| IOBUF PORT "flash_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "flash_clk" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "flash_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "flash_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "flash_holdn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "flash_wpn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_csspin" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_initn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_cfg_select[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_cfg_select[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "flash_cfg_select[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## SD card "sdcard", "usb" sheet | |||
| LOCATE COMP "sd_clk" SITE "H2"; # sd_clk WiFi_GPIO14 | |||
| LOCATE COMP "sd_cmd" SITE "J1"; # sd_cmd_di (MOSI) WiFi GPIO15 | |||
| LOCATE COMP "sd_d[0]" SITE "J3"; # sd_dat0_do (MISO) WiFi GPIO2 | |||
| LOCATE COMP "sd_d[1]" SITE "H1"; # sd_dat1_irq WiFi GPIO4 | |||
| LOCATE COMP "sd_d[2]" SITE "K1"; # sd_dat2 WiFi_GPIO12 | |||
| LOCATE COMP "sd_d[3]" SITE "K2"; # sd_dat3_csn WiFi_GPIO13 | |||
| LOCATE COMP "sd_wp" SITE "P5"; # not connected | |||
| LOCATE COMP "sd_cdn" SITE "N5"; # not connected | |||
| IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_d[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_d[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; # WiFi GPIO12 pulldown bootstrapping requirement | |||
| IOBUF PORT "sd_d[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_wp" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sd_cdn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## ADC SPI (MAX11123) "analog", "ram" sheet | |||
| LOCATE COMP "adc_csn" SITE "R17"; | |||
| LOCATE COMP "adc_mosi" SITE "R16"; | |||
| LOCATE COMP "adc_miso" SITE "U16"; | |||
| LOCATE COMP "adc_sclk" SITE "P17"; | |||
| IOBUF PORT "adc_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "adc_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "adc_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "adc_sclk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## Audio 4-bit DAC "analog", "gpio" sheet | |||
| # Output impedance 75 ohm. | |||
| # Strong enough to drive 16 ohm earphones. | |||
| LOCATE COMP "audio_l[3]" SITE "B3"; # JACK TIP (left audio) | |||
| LOCATE COMP "audio_l[2]" SITE "C3"; | |||
| LOCATE COMP "audio_l[1]" SITE "D3"; | |||
| LOCATE COMP "audio_l[0]" SITE "E4"; | |||
| LOCATE COMP "audio_r[3]" SITE "C5"; # JACK RING1 (right audio) | |||
| LOCATE COMP "audio_r[2]" SITE "D5"; | |||
| LOCATE COMP "audio_r[1]" SITE "B5"; | |||
| LOCATE COMP "audio_r[0]" SITE "A3"; | |||
| LOCATE COMP "audio_v[3]" SITE "E5"; # JACK RING2 (video or digital audio) | |||
| LOCATE COMP "audio_v[2]" SITE "F5"; | |||
| LOCATE COMP "audio_v[1]" SITE "F2"; | |||
| LOCATE COMP "audio_v[0]" SITE "H5"; | |||
| IOBUF PORT "audio_l[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_l[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_l[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_l[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_r[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_r[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_r[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_r[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_v[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_v[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_v[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "audio_v[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| ## WiFi ESP-32 "wifi", "usb", "flash" sheet | |||
| # other pins are shared with GP/GN, SD card and JTAG | |||
| LOCATE COMP "wifi_en" SITE "F1"; # enable/reset WiFi | |||
| LOCATE COMP "wifi_rxd" SITE "K3"; # FPGA transmits to WiFi | |||
| LOCATE COMP "wifi_txd" SITE "K4"; # FPGA receives from WiFi | |||
| LOCATE COMP "wifi_gpio0" SITE "L2"; | |||
| LOCATE COMP "wifi_gpio5" SITE "N4"; # WIFI LED | |||
| LOCATE COMP "wifi_gpio16" SITE "L1"; # Serial1 RX | |||
| LOCATE COMP "wifi_gpio17" SITE "N3"; # Serial1 TX | |||
| # LOCATE COMP "prog_done" SITE "Y3"; # not GPIO, always active | |||
| IOBUF PORT "wifi_en" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "wifi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "wifi_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "wifi_gpio0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "wifi_gpio16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "wifi_gpio17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| # IOBUF PORT "prog_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## PCB antenna 433 MHz (may be also used for FM) "usb" sheet | |||
| LOCATE COMP "ant_433mhz" SITE "G1"; | |||
| IOBUF PORT "ant_433mhz" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## Second USB port "US2" going directly into FPGA "usb", "ram" sheet | |||
| LOCATE COMP "usb_fpga_dp" SITE "E16"; # single ended or differential input only | |||
| LOCATE COMP "usb_fpga_dn" SITE "F16"; | |||
| IOBUF PORT "usb_fpga_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "usb_fpga_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| LOCATE COMP "usb_fpga_bd_dp" SITE "D15"; # differential bidirectional | |||
| LOCATE COMP "usb_fpga_bd_dn" SITE "E15"; | |||
| IOBUF PORT "usb_fpga_bd_dp" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "usb_fpga_bd_dn" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=4; | |||
| LOCATE COMP "usb_fpga_pu_dp" SITE "B12"; # pull up/down control | |||
| LOCATE COMP "usb_fpga_pu_dn" SITE "C12"; | |||
| IOBUF PORT "usb_fpga_pu_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| IOBUF PORT "usb_fpga_pu_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; | |||
| ## JTAG ESP-32 "usb" sheet | |||
| # connected to FT231X and ESP-32 | |||
| # commented out because those are dedicated pins, not directly useable as GPIO | |||
| # but could be used by some vendor-specific JTAG bridging (boundary scan) module | |||
| #LOCATE COMP "jtag_tdi" SITE "R5"; # FTDI_nRI FPGA receives | |||
| #LOCATE COMP "jtag_tdo" SITE "V4"; # FTDI_nCTS FPGA transmits | |||
| #LOCATE COMP "jtag_tck" SITE "T5"; # FTDI_nDSR FPGA receives | |||
| #LOCATE COMP "jtag_tms" SITE "U5"; # FTDI_nDCD FPGA receives | |||
| #IOBUF PORT "jtag_tdi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "jtag_tdo" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "jtag_tck" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| #IOBUF PORT "jtag_tms" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## SDRAM "ram" sheet | |||
| LOCATE COMP "sdram_clk" SITE "F19"; | |||
| LOCATE COMP "sdram_cke" SITE "F20"; | |||
| LOCATE COMP "sdram_csn" SITE "P20"; | |||
| LOCATE COMP "sdram_wen" SITE "T20"; | |||
| LOCATE COMP "sdram_rasn" SITE "R20"; | |||
| LOCATE COMP "sdram_casn" SITE "T19"; | |||
| LOCATE COMP "sdram_a[0]" SITE "M20"; | |||
| LOCATE COMP "sdram_a[1]" SITE "M19"; | |||
| LOCATE COMP "sdram_a[2]" SITE "L20"; | |||
| LOCATE COMP "sdram_a[3]" SITE "L19"; | |||
| LOCATE COMP "sdram_a[4]" SITE "K20"; | |||
| LOCATE COMP "sdram_a[5]" SITE "K19"; | |||
| LOCATE COMP "sdram_a[6]" SITE "K18"; | |||
| LOCATE COMP "sdram_a[7]" SITE "J20"; | |||
| LOCATE COMP "sdram_a[8]" SITE "J19"; | |||
| LOCATE COMP "sdram_a[9]" SITE "H20"; | |||
| LOCATE COMP "sdram_a[10]" SITE "N19"; | |||
| LOCATE COMP "sdram_a[11]" SITE "G20"; | |||
| LOCATE COMP "sdram_a[12]" SITE "G19"; | |||
| LOCATE COMP "sdram_ba[0]" SITE "P19"; | |||
| LOCATE COMP "sdram_ba[1]" SITE "N20"; | |||
| LOCATE COMP "sdram_dqm[0]" SITE "U19"; | |||
| LOCATE COMP "sdram_dqm[1]" SITE "E20"; | |||
| LOCATE COMP "sdram_d[0]" SITE "J16"; | |||
| LOCATE COMP "sdram_d[1]" SITE "L18"; | |||
| LOCATE COMP "sdram_d[2]" SITE "M18"; | |||
| LOCATE COMP "sdram_d[3]" SITE "N18"; | |||
| LOCATE COMP "sdram_d[4]" SITE "P18"; | |||
| LOCATE COMP "sdram_d[5]" SITE "T18"; | |||
| LOCATE COMP "sdram_d[6]" SITE "T17"; | |||
| LOCATE COMP "sdram_d[7]" SITE "U20"; | |||
| LOCATE COMP "sdram_d[8]" SITE "E19"; | |||
| LOCATE COMP "sdram_d[9]" SITE "D20"; | |||
| LOCATE COMP "sdram_d[10]" SITE "D19"; | |||
| LOCATE COMP "sdram_d[11]" SITE "C20"; | |||
| LOCATE COMP "sdram_d[12]" SITE "E18"; | |||
| LOCATE COMP "sdram_d[13]" SITE "F18"; | |||
| LOCATE COMP "sdram_d[14]" SITE "J18"; | |||
| LOCATE COMP "sdram_d[15]" SITE "J17"; | |||
| IOBUF PORT "sdram_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_cke" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_wen" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_rasn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_casn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_a[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_ba[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_ba[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "sdram_d[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; | |||
| # GPDI differential interface (Video) "gpdi" sheet | |||
| LOCATE COMP "gpdi_dp[0]" SITE "A16"; # Blue + | |||
| LOCATE COMP "gpdi_dn[0]" SITE "B16"; # Blue - | |||
| LOCATE COMP "gpdi_dp[1]" SITE "A14"; # Green + | |||
| LOCATE COMP "gpdi_dn[1]" SITE "C14"; # Green - | |||
| LOCATE COMP "gpdi_dp[2]" SITE "A12"; # Red + | |||
| LOCATE COMP "gpdi_dn[2]" SITE "A13"; # Red - | |||
| LOCATE COMP "gpdi_dp[3]" SITE "A17"; # Clock + | |||
| LOCATE COMP "gpdi_dn[3]" SITE "B18"; # Clock - | |||
| LOCATE COMP "gpdi_ethp" SITE "A19"; # Ethernet + | |||
| LOCATE COMP "gpdi_ethn" SITE "B20"; # Ethernet - | |||
| LOCATE COMP "gpdi_cec" SITE "A18"; | |||
| LOCATE COMP "gpdi_sda" SITE "B19"; # I2C shared with RTC | |||
| LOCATE COMP "gpdi_scl" SITE "E12"; # I2C shared with RTC C12->E12 | |||
| IOBUF PORT "gpdi_dp[0]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dn[0]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dp[1]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dn[1]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dp[2]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dn[2]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dp[3]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_dn[3]" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_ethp" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_ethn" IO_TYPE=LVCMOS33D DRIVE=4; | |||
| IOBUF PORT "gpdi_cec" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gpdi_sda" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gpdi_scl" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| # GPIO (default single-ended) "gpio", "ram", "gpdi" sheet | |||
| # Pins enumerated gp[0-27], gn[0-27]. | |||
| # With differential mode enabled on Lattice, | |||
| # gp[] (+) are used, gn[] (-) are ignored from design | |||
| # as they handle inverted signal by default. | |||
| # To enable differential, rename LVCMOS33->LVCMOS33D | |||
| LOCATE COMP "gp[0]" SITE "B11"; # J1_5+ GP0 | |||
| LOCATE COMP "gn[0]" SITE "C11"; # J1_5- GN0 | |||
| LOCATE COMP "gp[1]" SITE "A10"; # J1_7+ GP1 | |||
| LOCATE COMP "gn[1]" SITE "A11"; # J1_7- GN1 | |||
| LOCATE COMP "gp[2]" SITE "A9"; # J1_9+ GP2 | |||
| LOCATE COMP "gn[2]" SITE "B10"; # J1_9- GN2 | |||
| LOCATE COMP "gp[3]" SITE "B9"; # J1_11+ GP3 | |||
| LOCATE COMP "gn[3]" SITE "C10"; # J1_11- GN3 | |||
| LOCATE COMP "gp[4]" SITE "A7"; # J1_13+ GP4 | |||
| LOCATE COMP "gn[4]" SITE "A8"; # J1_13- GN4 | |||
| LOCATE COMP "gp[5]" SITE "C8"; # J1_15+ GP5 | |||
| LOCATE COMP "gn[5]" SITE "B8"; # J1_15- GN5 | |||
| LOCATE COMP "gp[6]" SITE "C6"; # J1_17+ GP6 | |||
| LOCATE COMP "gn[6]" SITE "C7"; # J1_17- GN6 | |||
| IOBUF PORT "gp[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| LOCATE COMP "gp[7]" SITE "A6"; # J1_23+ GP7 | |||
| LOCATE COMP "gn[7]" SITE "B6"; # J1_23- GN7 | |||
| LOCATE COMP "gp[8]" SITE "A4"; # J1_25+ GP8 | |||
| LOCATE COMP "gn[8]" SITE "A5"; # J1_25- GN8 | |||
| LOCATE COMP "gp[9]" SITE "A2"; # J1_27+ GP9 | |||
| LOCATE COMP "gn[9]" SITE "B1"; # J1_27- GN9 | |||
| LOCATE COMP "gp[10]" SITE "C4"; # J1_29+ GP10 WIFI_GPIO27 | |||
| LOCATE COMP "gn[10]" SITE "B4"; # J1_29- GN10 | |||
| LOCATE COMP "gp[11]" SITE "F4"; # J1_31+ GP11 WIFI_GPIO25 | |||
| LOCATE COMP "gn[11]" SITE "E3"; # J1_31- GN11 WIFI_GPIO26 | |||
| LOCATE COMP "gp[12]" SITE "G3"; # J1_33+ GP12 WIFI_GPIO32 | |||
| LOCATE COMP "gn[12]" SITE "F3"; # J1_33- GN12 WIFI_GPIO33 | |||
| LOCATE COMP "gp[13]" SITE "H4"; # J1_35+ GP13 WIFI_GPIO34 | |||
| LOCATE COMP "gn[13]" SITE "G5"; # J1_35- GN13 WIFI_GPIO35 | |||
| IOBUF PORT "gp[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| LOCATE COMP "gp[14]" SITE "U18"; # J2_5+ GP14 | |||
| LOCATE COMP "gn[14]" SITE "U17"; # J2_5- GN14 | |||
| LOCATE COMP "gp[15]" SITE "N17"; # J2_7+ GP15 | |||
| LOCATE COMP "gn[15]" SITE "P16"; # J2_7- GN15 | |||
| LOCATE COMP "gp[16]" SITE "N16"; # J2_9+ GP16 | |||
| LOCATE COMP "gn[16]" SITE "M17"; # J2_9- GN16 | |||
| LOCATE COMP "gp[17]" SITE "L16"; # J2_11+ GP17 | |||
| LOCATE COMP "gn[17]" SITE "L17"; # J2_11- GN17 | |||
| LOCATE COMP "gp[18]" SITE "H18"; # J2_13+ GP18 | |||
| LOCATE COMP "gn[18]" SITE "H17"; # J2_13- GN18 | |||
| LOCATE COMP "gp[19]" SITE "F17"; # J2_15+ GP19 | |||
| LOCATE COMP "gn[19]" SITE "G18"; # J2_15- GN19 | |||
| LOCATE COMP "gp[20]" SITE "D18"; # J2_17+ GP20 | |||
| LOCATE COMP "gn[20]" SITE "E17"; # J2_17- GN20 | |||
| IOBUF PORT "gp[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| LOCATE COMP "io_jtag_tms" SITE "C18"; # J2_23+ GP21 | |||
| LOCATE COMP "gn[21]" SITE "D17"; # J2_23- GN21 | |||
| LOCATE COMP "io_jtag_tdi" SITE "B15"; # J2_25+ GP22 D15->B15 | |||
| LOCATE COMP "gn[22]" SITE "C15"; # J2_25- GN22 E15->C15 | |||
| LOCATE COMP "io_jtag_tdo" SITE "B17"; # J2_27+ GP23 | |||
| LOCATE COMP "gn[23]" SITE "C17"; # J2_27- GN23 | |||
| LOCATE COMP "io_jtag_tck" SITE "C16"; # J2_29+ GP24 | |||
| LOCATE COMP "gn[24]" SITE "D16"; # J2_29- GN24 | |||
| LOCATE COMP "gp[25]" SITE "D14"; # J2_31+ GP25 B15->D14 | |||
| LOCATE COMP "gn[25]" SITE "E14"; # J2_31- GN25 C15->E14 | |||
| LOCATE COMP "gp[26]" SITE "B13"; # J2_33+ GP26 | |||
| LOCATE COMP "gn[26]" SITE "C13"; # J2_33- GN26 | |||
| LOCATE COMP "gp[27]" SITE "D13"; # J2_35+ GP27 | |||
| LOCATE COMP "gn[27]" SITE "E13"; # J2_35- GN27 | |||
| IOBUF PORT "io_jtag_tms" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "io_jtag_tdi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "io_jtag_tdo" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "io_jtag_tck" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gp[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| IOBUF PORT "gn[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## PROGRAMN (reload bitstream from FLASH, exit from bootloader) | |||
| # PCB v2.0.5 and higher | |||
| LOCATE COMP "user_programn" SITE "M4"; | |||
| IOBUF PORT "user_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; | |||
| ## SHUTDOWN "power", "ram" sheet (connected from PCB v1.7.5) | |||
| # on PCB v1.7 shutdown is not connected to FPGA | |||
| LOCATE COMP "shutdown" SITE "G16"; # FPGA receives | |||
| IOBUF PORT "shutdown" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; | |||
| @ -1,4 +1,4 @@ | |||
| package mupq | |||
| package quantumrisc | |||
| import vexriscv._ | |||
| import vexriscv.plugin._ | |||
| @ -1,4 +1,4 @@ | |||
| package mupq | |||
| package quantumrisc | |||
| import spinal.core._ | |||
| import spinal.lib._ | |||
| @ -1,4 +1,4 @@ | |||
| package mupq | |||
| package quantumrisc | |||
| import scala.collection.mutable.ArrayBuffer | |||
| @ -0,0 +1,98 @@ | |||
| package quantumrisc | |||
| import java.io.{File, FileInputStream, FileOutputStream, IOException, OutputStream} | |||
| import scopt.OptionParser | |||
| import spinal.sim._ | |||
| import spinal.core._ | |||
| import spinal.lib._ | |||
| import spinal.core.sim._ | |||
| import spinal.lib.bus.simple._ | |||
| import spinal.lib.bus.misc.SizeMapping | |||
| import spinal.lib.io.{TriStateArray, InOutWrapper} | |||
| import spinal.lib.com.jtag.Jtag | |||
| import spinal.lib.com.uart.Uart | |||
| import spinal.lib.com.jtag.sim.JtagTcp | |||
| import vexriscv.VexRiscv | |||
| import vexriscv.plugin.Plugin | |||
| case class PipelinedMemoryBusRamUlx3s(size : BigInt, initialContent : File = null) extends Component{ | |||
| require(size % 4 == 0, "Size must be multiple of 4 bytes") | |||
| require(size > 0, "Size must be greater than zero") | |||
| val busConfig = PipelinedMemoryBusConfig(log2Up(size), 32) | |||
| val io = new Bundle{ | |||
| val bus = slave(PipelinedMemoryBus(busConfig)) | |||
| } | |||
| val ram = Mem(Bits(32 bits), size / 4) | |||
| io.bus.rsp.valid := RegNext(io.bus.cmd.fire && !io.bus.cmd.write) init(False) | |||
| io.bus.rsp.data := ram.readWriteSync( | |||
| address = io.bus.cmd.address >> 2, | |||
| data = io.bus.cmd.data, | |||
| enable = io.bus.cmd.valid, | |||
| write = io.bus.cmd.write, | |||
| mask = io.bus.cmd.mask | |||
| ) | |||
| io.bus.cmd.ready := True | |||
| if (initialContent != null) { | |||
| val input = new FileInputStream(initialContent) | |||
| val initContent = Array.fill[BigInt](ram.wordCount)(0) | |||
| val fileContent = Array.ofDim[Byte](Seq(input.available, initContent.length * 4).min) | |||
| input.read(fileContent) | |||
| for ((byte, addr) <- fileContent.zipWithIndex) { | |||
| val l = java.lang.Byte.toUnsignedLong(byte) << ((addr & 3) * 8) | |||
| initContent(addr >> 2) |= BigInt(l) | |||
| } | |||
| ram.initBigInt(initContent) | |||
| } | |||
| } | |||
| class PQVexRiscvUlx3s( | |||
| val ramBlockSizes : Seq[BigInt] = Seq[BigInt](64 KiB, 64 KiB), | |||
| val initialContent : File = null, | |||
| val coreFrequency : HertzNumber = 25 MHz, | |||
| cpuPlugins : () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() | |||
| ) extends PQVexRiscv( | |||
| cpuPlugins = cpuPlugins, | |||
| ibusRange = SizeMapping(0x80000000l, ramBlockSizes.reduce(_ + _)), | |||
| genTimer = true | |||
| ) { | |||
| val io = new Bundle { | |||
| val asyncReset = in Bool | |||
| val mainClock = in Bool | |||
| val uart = master(Uart()) | |||
| val jtag = slave(Jtag()) | |||
| } | |||
| asyncReset := io.asyncReset | |||
| mainClock := io.mainClock | |||
| uart <> io.uart | |||
| jtag <> io.jtag | |||
| val memory = new ClockingArea(systemClockDomain) { | |||
| val ramBlocks = ramBlockSizes.zipWithIndex.map(t => PipelinedMemoryBusRamUlx3s(t._1, if (t._2 == 0) initialContent else null)) | |||
| var curAddr : BigInt = 0x80000000l | |||
| for (block <- ramBlocks) { | |||
| busSlaves += block.io.bus -> SizeMapping(curAddr, block.size) | |||
| curAddr += block.size | |||
| } | |||
| } | |||
| } | |||
| object PQVexRiscvUlx3s { | |||
| def main(args: Array[String]) : Unit = { | |||
| SpinalConfig( | |||
| mode = Verilog | |||
| // targetDirectory = "rtl" | |||
| ).generate(new PQVexRiscvUlx3s).printPruned() | |||
| } | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| # ---- FT232H Adapter ----- | |||
| interface ftdi | |||
| # source [find interface/ftdi/um232h.cfg] | |||
| # ftdi_serial "TN34GV0F" | |||
| ftdi_vid_pid 0x0403 0x6014 | |||
| ftdi_layout_init 0x0008 0x400b | |||
| adapter_khz 20000 | |||
| transport select jtag | |||
| # Adapt this to your favourite FTDI-based debugger | |||
| # source [find interface/ftdi/um232h.cfg] | |||
| # ftdi_serial "TN34GV0F" | |||
| # The Murax target needs a YAML file, even if it is empty | |||
| set MURAX_CPU0_YAML cpu0.yaml | |||
| # The Murax target should work for all PQVexRiscv based chips | |||
| source [find target/murax.cfg] | |||