aboutsummaryrefslogtreecommitdiff
path: root/examples/example3a_spi_wasm
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-12-29 19:56:04 +0100
committerWojciech Kosior <kwojtus@protonmail.com>2020-12-29 19:56:04 +0100
commit68c80359ba0983bc21a18c0270025be9b441c0bb (patch)
treea06a04eb8756f96d05c55768bd356917847cdc95 /examples/example3a_spi_wasm
parent5b6a3f3b216939a11ed1978d7da4dd6bbe4edc2a (diff)
downloadAGH-engineering-thesis-68c80359ba0983bc21a18c0270025be9b441c0bb.tar.gz
AGH-engineering-thesis-68c80359ba0983bc21a18c0270025be9b441c0bb.zip
add the ability to include additional data at the end of bitstream image and prepare an example, that reads thic data through SPI and displays it
Diffstat (limited to 'examples/example3a_spi_wasm')
-rw-r--r--examples/example3a_spi_wasm/Makefile4
-rw-r--r--examples/example3a_spi_wasm/data.txt40
-rw-r--r--examples/example3a_spi_wasm/instructions.wat115
3 files changed, 159 insertions, 0 deletions
diff --git a/examples/example3a_spi_wasm/Makefile b/examples/example3a_spi_wasm/Makefile
new file mode 100644
index 0000000..0eff969
--- /dev/null
+++ b/examples/example3a_spi_wasm/Makefile
@@ -0,0 +1,4 @@
+SIMFLAGS += -DFINISH_ON_LED1=1 -DFINISH_ON_LED2=1 -DFINISH_ON_IMAGE_WRITES=1
+FLASH_DATA = data.txt
+
+include ../../Makefile.example
diff --git a/examples/example3a_spi_wasm/data.txt b/examples/example3a_spi_wasm/data.txt
new file mode 100644
index 0000000..2200f6b
--- /dev/null
+++ b/examples/example3a_spi_wasm/data.txt
@@ -0,0 +1,40 @@
+WebAssembly or Wasm standard developed by W3C Community Group defines a bytecode
+format for executable programs, as well as its text representation. The goal of the bytecode is to
+enable efficient interpretation and keep the size of the binary small. Although it has been created
+mainly for use on web pages, it is suited for other environments as well, including embedded
+targets. Programming languages, even those with manual memory management and pointer
+arithmetics, can be compiled to Wasm bytecode. Hence, a standard-conforming WebAssembly
+interpreter is capable of running code written in any of the languages, for which a compiler
+exists. This currently includes C, C++, C#, Rust and others. Wasm bytecode runs on a virtual
+stack machine. Most existing environments either interpret it directly or use JIT compilation.
+The goal of this thesis is to create a laboratory station for execution of WebAssembly on a
+programmable logic device. The client is a person responsible for the equipment of a laboratory.
+Project’s codename is WMC - WebAssembly Machine in Circuitry.
+
+
+WebAsm interpretation could possibly be made faster with hardware designed specifically for
+this task 1. Such hardware would also benefit from already existing tools for generating and
+working with the bytecode. The entire range of languages, that can be compiled to the bytecode,
+would be immediately available for use on such platform.
+Although a WebAssembly processor would be unique in some sense, it could still be used in a
+fashion similar to other soft processors for programmable logic, enabling sequential execution.
+The processor could be integrated with hardware modules. Such a combination would allow for
+implementing peripheral devices operated by Wasm software. If such WebAssembly processor
+proves speed-efficient, it can be implemented in application-specific integrated circuit.
+
+
+In terms of this thesis a laboratory station for execution of WebAssembly in a programmable
+logic device is going to be created. It will consist of a selected FPGA board with a dedicated
+programmer. Means of communication with the device, for example a VGA display or wired
+connection to a computer, are also going to be ensured.
+Wasm machine is going to be implemented in a hardware description language. Included will
+be: the code, tools to generate bitstream and load it to the board, a test program in WebAssembly binary format, means of transfering it to the device and documentation for the product.
+The client will be a person responsible for equipment of a research laboratory. Aside from
+allowing researchers to evaluate Wasm bytecode execution on the FPGA board, the resulting
+product should allow modification of the logic design, for example to add a peripheral module
+or a custom instruction to the processor and perform experiments with it.
+The designed Wasm machine is going to be a stack machine. Its distinguishable parts will be
+control unit, arithmetic logic unit and peripheral interfaces. An in-circuit stack (as opposed to
+stack fully contained in RAM) and floating-point unit might also be added. The machine shall
+make use of memory module residing on the development board. It shall communicate with
+devices external to FPGA chip through peripherals (e.g. VGA module, serial interface module).
diff --git a/examples/example3a_spi_wasm/instructions.wat b/examples/example3a_spi_wasm/instructions.wat
new file mode 100644
index 0000000..f09e080
--- /dev/null
+++ b/examples/example3a_spi_wasm/instructions.wat
@@ -0,0 +1,115 @@
+;; See instructions.wat of soc_print_number test. A lot has been taken from
+;; there.
+;; Relevant addresses are VGA text memory (0xFFC00), VGA regs (0x100600),
+;; lower half of timer reg (0x1BFC08), SPI memory (0x13FC00),
+;; SPI bytes_to_output reg (0x13FE00), SPI bytes_to_receive reg (0x13FE02)
+;; and SPI operating reg (0x13FE04).
+
+(module
+ (memory 0 2)
+ (func $main
+ (local $transfers i32)
+ (local $offset i32)
+ (local $address i32)
+ (local $index i32)
+
+ ;; power up flash chip
+ ;; set bytes_to_output to 1
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE00) (i32.const 1))
+ ;; set bytes_to_receive to 0
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE02) (i32.const 0))
+ ;; release power-down SPI command
+ (i32.store8 offset=0 align=1
+ (i32.const 0x13FC00) (i32.const 0xAB))
+ ;; start SPI operation
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE04) (i32.const 0x1))
+
+ ;; wait for at least 3000 ns after command gets sent
+ ;; reset the timer
+ (i32.store16 offset=0x0 align=2
+ (i32.const 0x1BFC08) (i32.const 0x0))
+
+ ;; loop until 45 ticks pass; 45 ticks is 3600 ns; additional 600ns
+ ;; is enough for power-up command to be sent
+ (loop $again
+ (br_if $again (i32.lt_u
+ (i32.load16_u offset=0x0 align=2
+ (i32.const 0x1BFC08))
+ (i32.const 45))))
+
+ ;; we'll transfer 2400 bytes by making 5 transfers of 480 bytes;
+ ;; our SPI peripheral can transfer at most 511 bytes in one SPI command
+ (set_local $transfers (i32.const 0))
+
+ (loop $outer
+ ;; set bytes_to_output to 5
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE00) (i32.const 5))
+ ;; set bytes_to_receive to 480
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE02) (i32.const 480))
+ ;; fast read SPI command
+ (i32.store8 offset=0 align=1
+ (i32.const 0x13FC00) (i32.const 0x0B))
+ ;; prepare address - first, compute current offset
+ (set_local $offset (i32.mul (get_local $transfers)
+ (i32.const 480)))
+ ;; then, add computed offset to base address of 135100
+ (set_local $address (i32.add (get_local $offset)
+ (i32.const 135100)))
+ ;; store the address in big endian
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FC02)
+ (i32.div_u (get_local $address)
+ (i32.const 256)))
+ (i32.store8 offset=0 align=1
+ (i32.const 0x13FC03) (get_local $address))
+ (i32.store8 offset=0 align=1
+ (i32.const 0x13FC01)
+ (i32.div_u (get_local $address)
+ (i32.const 65536)))
+ ;; start SPI operation
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE04) (i32.const 0x1))
+ ;; force wait for operation completion
+ (i32.store16 offset=0 align=2
+ (i32.const 0x13FE00) (i32.const 0))
+
+ ;; assume transferred data to be ascii text and print it to screen
+ ;; initialize index to 0
+ (set_local $index (i32.const 0))
+ ;; copy characters in a loop
+ (loop $inner
+ ;; copy 4 characters to VGA memory
+ (i32.store offset=0xFFC00 align=4
+ (i32.add (get_local $index)
+ (get_local $offset))
+ (i32.load offset=0x13FC00 align=4
+ (get_local $index)))
+ ;; increase index
+ (set_local $index (i32.add (get_local $index)
+ (i32.const 4)))
+ ;; loop condition
+ (br_if $inner (i32.lt_u
+ (get_local $index)
+ (i32.const 480))))
+
+ ;; increase transfers count
+ (set_local $transfers (i32.add (get_local $transfers)
+ (i32.const 1)))
+
+ ;; switch LED2
+ (i32.store16 offset=0x0 align=2
+ (i32.const 0x1BFC06)
+ (i32.rem_u (get_local $transfers) (i32.const 2)))
+
+ ;; if less than 5 transfers were done, continue with another one
+ (br_if $outer (i32.lt_u (get_local $transfers) (i32.const 5))))
+
+ ;; write a non-zero value to the VGA power-on reg at 0x100600 (0x100A00)
+ (i32.store16 offset=0x0 align=2
+ (i32.const 0x100600) (i32.const 0x1)))
+ (export "main" (func $main)))