From c40a2f5c6fa4e1773baef3e400a4a79cdc6ca1a6 Mon Sep 17 00:00:00 2001 From: Brad Nelson Date: Sun, 3 Dec 2023 19:57:14 -0800 Subject: [PATCH] Adding initial pico-ice support. --- .gitmodules | 6 +++ Makefile | 63 ++++++++++++++++++++++- esp32/allocation.fs | 1 - pico-ice/CMakeLists.txt | 43 ++++++++++++++++ pico-ice/allocation.fs | 18 +++++++ pico-ice/autoboot.fs | 16 ++++++ pico-ice/builtins.h | 91 ++++++++++++++++++++++++++++++++++ pico-ice/main.c | 62 +++++++++++++++++++++++ pico-ice/pico-ice-sdk | 1 + pico-ice/pico-sdk | 1 + pico-ice/pico_sdk_import.cmake | 73 +++++++++++++++++++++++++++ pico-ice/platform.fs | 50 +++++++++++++++++++ 12 files changed, 422 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 100644 pico-ice/CMakeLists.txt create mode 100644 pico-ice/allocation.fs create mode 100644 pico-ice/autoboot.fs create mode 100644 pico-ice/builtins.h create mode 100644 pico-ice/main.c create mode 160000 pico-ice/pico-ice-sdk create mode 160000 pico-ice/pico-sdk create mode 100644 pico-ice/pico_sdk_import.cmake create mode 100644 pico-ice/platform.fs diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0c300cd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "pico-ice/pico-sdk"] + path = pico-ice/pico-sdk + url = https://github.com/raspberrypi/pico-sdk +[submodule "pico-ice/pico-ice-sdk"] + path = pico-ice/pico-ice-sdk + url = https://github.com/tinyvision-ai-inc/pico-ice-sdk diff --git a/Makefile b/Makefile index a48699c..f8495b3 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,8 @@ POSIX = $(OUT)/posix WINDOWS = $(OUT)/windows ESP32 = $(OUT)/esp32 ESP32_SIM = $(OUT)/esp32-sim +PICO_ICE = $(OUT)/pico-ice +PICO_ICE_SIM = $(OUT)/pico-ice-sim DEPLOY = $(OUT)/deploy OS = $(shell uname -s) @@ -238,9 +240,9 @@ COMMON_PHASE1 = common/comments.fs \ common/structures.fs COMMON_PHASE1e = common/comments.fs \ - common/tier2a_forth.fs \ + common/tier2a_forth.fs \ common/boot.fs \ - common/tier2b_forth.fs \ + common/tier2b_forth.fs \ common/io.fs \ common/conditionals.fs \ common/vocabulary.fs \ @@ -287,6 +289,16 @@ WINDOWS_BOOT = $(COMMON_PHASE1) \ $(GEN)/windows_boot.h: tools/source_to_string.js $(WINDOWS_BOOT) | $(GEN) $< -win boot $(VERSION) $(REVISION) $(WINDOWS_BOOT) >$@ +PICO_ICE_BOOT = $(COMMON_PHASE1) \ + pico-ice/allocation.fs \ + $(COMMON_PHASE2) \ + common/tasks.fs common/streams.fs \ + pico-ice/platform.fs \ + pico-ice/autoboot.fs \ + common/fini.fs +$(GEN)/pico_ice_boot.h: tools/source_to_string.js $(PICO_ICE_BOOT) | $(GEN) + $< boot $(VERSION) $(REVISION) $(PICO_ICE_BOOT) >$@ + ESP32_BOOT = $(COMMON_PHASE1) \ esp32/allocation.fs esp32/bindings.fs \ $(COMMON_PHASE2) $(COMMON_FILETOOLS) \ @@ -793,6 +805,53 @@ CHIP_esp32cam=esp32 %-build: $(ESP32)/%_build/ESP32forth.ino.bin echo "done" +# ---- PICO-ICE ---- + +pico-ice: $(PICO_ICE)/ueforth_pico_ice.uf2 + +$(PICO_ICE)/ueforth_pico_ice.uf2: \ + $(PICO_ICE)/Makefile \ + pico-ice/main.c \ + pico-ice/builtins.h \ + common/tier0_opcodes.h \ + common/tier1_opcodes.h \ + common/tier2_opcodes.h \ + common/floats.h \ + common/calls.h \ + common/calling.h \ + common/floats.h \ + common/bits.h \ + common/core.h \ + common/interp.h \ + $(GEN)/pico_ice_boot.h + make -C $(PICO_ICE) VERBOSE=1 + +$(PICO_ICE)/Makefile: + cmake $(PICO_ICE) -S pico-ice -B $(PICO_ICE) + +# ---- PICO-ICE-SIM ---- + +pico-ice-sim: $(PICO_ICE_SIM)/ueforth_pico_ice_sim + +$(PICO_ICE_SIM): + mkdir -p $@ + +$(PICO_ICE_SIM)/ueforth_pico_ice_sim: \ + pico-ice/main.c \ + pico-ice/builtins.h \ + common/tier0_opcodes.h \ + common/tier1_opcodes.h \ + common/tier2_opcodes.h \ + common/floats.h \ + common/calls.h \ + common/calling.h \ + common/floats.h \ + common/bits.h \ + common/core.h \ + common/interp.h \ + $(GEN)/pico_ice_boot.h | $(PICO_ICE_SIM) + $(CXX) $(CFLAGS) -DUEFORTH_SIM=1 $< -o $@ + # ---- PACKAGE ---- $(ESP32)/ESP32forth.zip: \ diff --git a/esp32/allocation.fs b/esp32/allocation.fs index 882b64e..449f541 100644 --- a/esp32/allocation.fs +++ b/esp32/allocation.fs @@ -16,4 +16,3 @@ : allocate ( n -- a ior ) malloc dup 0= ; : free ( a -- ior ) sysfree 0 ; : resize ( a n -- a ior ) realloc dup 0= ; - diff --git a/pico-ice/CMakeLists.txt b/pico-ice/CMakeLists.txt new file mode 100644 index 0000000..e072ce4 --- /dev/null +++ b/pico-ice/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright 2024 Bradley D. Nelson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.13) + +# import the pico-sdk +set(PICO_SDK_PATH ${CMAKE_CURRENT_SOURCE_DIR}/pico-sdk/) +include(pico_sdk_import.cmake) + +# configure the pico-sdk project +project(ueforth_pico_ice C CXX ASM) +pico_sdk_init() + +# add the pico-ice-sdk +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/pico-ice-sdk) + +add_executable(${CMAKE_PROJECT_NAME} main.c) +target_link_libraries(${CMAKE_PROJECT_NAME} + pico_ice_sdk + pico_stdio_usb +) +target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../out/ +) +target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) +pico_add_extra_outputs(${CMAKE_PROJECT_NAME}) +pico_enable_stdio_usb(${CMAKE_PROJECT_NAME} 0) +pico_enable_stdio_uart(${CMAKE_PROJECT_NAME} 0) diff --git a/pico-ice/allocation.fs b/pico-ice/allocation.fs new file mode 100644 index 0000000..455c698 --- /dev/null +++ b/pico-ice/allocation.fs @@ -0,0 +1,18 @@ +\ Copyright 2023 Bradley D. Nelson +\ +\ Licensed under the Apache License, Version 2.0 (the "License"); +\ you may not use this file except in compliance with the License. +\ You may obtain a copy of the License at +\ +\ http://www.apache.org/licenses/LICENSE-2.0 +\ +\ Unless required by applicable law or agreed to in writing, software +\ distributed under the License is distributed on an "AS IS" BASIS, +\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +\ See the License for the specific language governing permissions and +\ limitations under the License. + +( Words with OS assist ) +: allocate ( n -- a ior ) malloc dup 0= ; +: free ( a -- ior ) sysfree 0 ; +: resize ( a n -- a ior ) realloc dup 0= ; diff --git a/pico-ice/autoboot.fs b/pico-ice/autoboot.fs new file mode 100644 index 0000000..7e758cf --- /dev/null +++ b/pico-ice/autoboot.fs @@ -0,0 +1,16 @@ +\ Copyright 2023 Bradley D. Nelson +\ +\ Licensed under the Apache License, Version 2.0 (the "License"); +\ you may not use this file except in compliance with the License. +\ You may obtain a copy of the License at +\ +\ http://www.apache.org/licenses/LICENSE-2.0 +\ +\ Unless required by applicable law or agreed to in writing, software +\ distributed under the License is distributed on an "AS IS" BASIS, +\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +\ See the License for the specific language governing permissions and +\ limitations under the License. + +( TODO: Add autoboot support. ) +' ok diff --git a/pico-ice/builtins.h b/pico-ice/builtins.h new file mode 100644 index 0000000..1386100 --- /dev/null +++ b/pico-ice/builtins.h @@ -0,0 +1,91 @@ +// Copyright 2023 Bradley D. Nelson +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include + +#ifndef UEFORTH_SIM +# include "pico/time.h" +#endif + +// TODO: Implement RESIZE-FILE. +// TODO: Implement FLUSH-FILE. + +#define PLATFORM_OPCODE_LIST \ + REQUIRED_MEMORY_SUPPORT \ + REQUIRED_SYSTEM_SUPPORT \ + REQUIRED_FILES_SUPPORT \ + CALLING_OPCODE_LIST \ + FLOATING_POINT_LIST + +#define REQUIRED_MEMORY_SUPPORT \ + YV(internals, MALLOC, SET malloc(n0)) \ + YV(internals, SYSFREE, free(a0); DROP) \ + YV(internals, REALLOC, SET realloc(a1, n0); NIP) + +#ifndef UEFORTH_SIM +# define REQUIRED_SYSTEM_SUPPORT \ + X("MS-TICKS", MS_TICKS, PUSH us_to_ms(get_absolute_time())) \ + XV(internals, "RAW-YIELD", RAW_YIELD, tud_task()) \ + XV(internals, "RAW-TERMINATE", RAW_TERMINATE, exit(n0); DROP) \ + YV(internals, getchar_timeout_us, n0 = getchar_timeout_us(n0)) +#else +# define REQUIRED_SYSTEM_SUPPORT \ + X("MS-TICKS", MS_TICKS, PUSH (time(0) * 1000)) \ + XV(internals, "RAW-YIELD", RAW_YIELD, sleep(0)) \ + XV(internals, "RAW-TERMINATE", RAW_TERMINATE, exit(n0); DROP) \ + YV(internals, getchar_timeout_us, DROP; PUSH fgetc(stdin)) +#endif + +#define REQUIRED_FILES_SUPPORT \ + X("R/O", R_O, PUSH O_RDONLY) \ + X("W/O", W_O, PUSH O_WRONLY) \ + X("R/W", R_W, PUSH O_RDWR) \ + Y(BIN, ) \ + X("CLOSE-FILE", CLOSE_FILE, tos = close(tos); tos = tos ? errno : 0) \ + X("OPEN-FILE", OPEN_FILE, cell_t mode = n0; DROP; cell_t len = n0; DROP; \ + memcpy(filename, a0, len); filename[len] = 0; \ + n0 = open(filename, mode, 0777); PUSH n0 < 0 ? errno : 0) \ + X("CREATE-FILE", CREATE_FILE, cell_t mode = n0; DROP; cell_t len = n0; DROP; \ + memcpy(filename, a0, len); filename[len] = 0; \ + n0 = open(filename, mode | O_CREAT | O_TRUNC); PUSH n0 < 0 ? errno : 0) \ + X("DELETE-FILE", DELETE_FILE, cell_t len = n0; DROP; \ + memcpy(filename, a0, len); filename[len] = 0; \ + n0 = unlink(filename); n0 = n0 ? errno : 0) \ + X("RENAME-FILE", RENAME_FILE, \ + cell_t len = n0; DROP; memcpy(filename, a0, len); filename[len] = 0; DROP; \ + cell_t len2 = n0; DROP; memcpy(filename2, a0, len2); filename2[len2] = 0; \ + n0 = rename(filename2, filename); n0 = n0 ? errno : 0) \ + X("WRITE-FILE", WRITE_FILE, cell_t fd = n0; DROP; cell_t len = n0; DROP; \ + n0 = write(fd, a0, len); n0 = n0 != len ? errno : 0) \ + X("READ-FILE", READ_FILE, cell_t fd = n0; DROP; cell_t len = n0; DROP; \ + n0 = read(fd, a0, len); PUSH n0 < 0 ? errno : 0) \ + X("FILE-POSITION", FILE_POSITION, \ + n0 = (cell_t) lseek(n0, 0, SEEK_CUR); PUSH n0 < 0 ? errno : 0) \ + X("REPOSITION-FILE", REPOSITION_FILE, cell_t fd = n0; DROP; \ + n0 = (cell_t) lseek(fd, tos, SEEK_SET); n0 = n0 < 0 ? errno : 0) \ + X("FILE-SIZE", FILE_SIZE, struct stat st; w = fstat(n0, &st); \ + n0 = (cell_t) st.st_size; PUSH w < 0 ? errno : 0) \ + X("NON-BLOCK", NON_BLOCK, n0 = fcntl(n0, F_SETFL, O_NONBLOCK); \ + n0 = n0 < 0 ? errno : 0) + +#define VOCABULARY_LIST V(forth) V(internals) + +#define PATH_MAX 256 +static char filename[PATH_MAX]; +static char filename2[PATH_MAX]; diff --git a/pico-ice/main.c b/pico-ice/main.c new file mode 100644 index 0000000..203ebea --- /dev/null +++ b/pico-ice/main.c @@ -0,0 +1,62 @@ +// Copyright 2023 Bradley D. Nelson +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#ifndef UEFORTH_SIM +# include "pico/stdlib.h" +# include "boards/pico_ice.h" +# include "tusb.h" +#else +# include +#endif + +#include "common/tier0_opcodes.h" +#include "common/tier1_opcodes.h" +#include "common/tier2_opcodes.h" +#include "common/floats.h" +#include "common/calls.h" + +#ifndef UEFORTH_SIM +# define HEAP_SIZE (100 * 1024) +#else +# define HEAP_SIZE (200 * 1024) +#endif +#define STACK_CELLS (4 * 1024) + +#include "pico-ice/builtins.h" + +// TODO: Implement faults. +#define FAULT_ENTRY +static void forth_faults_setup(void) { +} + +#include "common/bits.h" +#include "common/core.h" +#include "common/calling.h" +#include "common/interp.h" +#include "gen/pico_ice_boot.h" + +int main(int argc, char *argv[]) { +#ifndef UEFORTH_SIM + tusb_init(); + stdio_init_all(); + tud_task(); +#endif + + void *heap = malloc(HEAP_SIZE); + forth_init(argc, argv, heap, HEAP_SIZE, boot, sizeof(boot)); + for (;;) { g_sys->rp = forth_run(g_sys->rp); } + return 1; +} diff --git a/pico-ice/pico-ice-sdk b/pico-ice/pico-ice-sdk new file mode 160000 index 0000000..dfc0efe --- /dev/null +++ b/pico-ice/pico-ice-sdk @@ -0,0 +1 @@ +Subproject commit dfc0efeb73a3a8bf8cfa9fac3f135b1f0ccf5bcb diff --git a/pico-ice/pico-sdk b/pico-ice/pico-sdk new file mode 160000 index 0000000..6a7db34 --- /dev/null +++ b/pico-ice/pico-sdk @@ -0,0 +1 @@ +Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374 diff --git a/pico-ice/pico_sdk_import.cmake b/pico-ice/pico_sdk_import.cmake new file mode 100644 index 0000000..65f8a6f --- /dev/null +++ b/pico-ice/pico_sdk_import.cmake @@ -0,0 +1,73 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + GIT_SUBMODULES_RECURSE FALSE + ) + else () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + endif () + + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/pico-ice/platform.fs b/pico-ice/platform.fs new file mode 100644 index 0000000..b1d74e9 --- /dev/null +++ b/pico-ice/platform.fs @@ -0,0 +1,50 @@ +\ Copyright 2023 Bradley D. Nelson +\ +\ Licensed under the Apache License, Version 2.0 (the "License"); +\ you may not use this file except in compliance with the License. +\ You may obtain a copy of the License at +\ +\ http://www.apache.org/licenses/LICENSE-2.0 +\ +\ Unless required by applicable law or agreed to in writing, software +\ distributed under the License is distributed on an "AS IS" BASIS, +\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +\ See the License for the specific language governing permissions and +\ limitations under the License. + +( Add a yielding task so pause yields ) +internals definitions +: yield-step raw-yield yield ; +' yield-step 100 100 task yield-task +yield-task start-task +forth definitions + +( Initial file handles ) +0 constant stdin +1 constant stdout +2 constant stderr + +( Set up Basic I/O ) +also internals definitions +: setup-saving-base ; ( TODO: implement. ) +variable last-key -1 last-key ! +forth definitions internals +: default-type ( a n -- ) stderr write-file throw ; +: default-key? ( -- f ) + last-key @ 0< if 1000 getchar_timeout_us last-key ! then + last-key @ 0< 0= +; +: default-key ( -- ch ) + begin default-key? 0= while pause repeat + last-key @ -1 last-key ! +; +previous + +' default-type is type +' default-key is key +' default-key? is key? +' raw-terminate is terminate +-1 echo ! + +( Setup entry ) +internals : ok ." uEforth" raw-ok ; forth