mirror of
https://github.com/antonblanchard/chiselwatt.git
synced 2026-04-04 21:17:43 +00:00
Merge pull request #33 from carlosedp/add_samples
Add hello_world sample sources and Makefile targets
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -6,6 +6,7 @@ test_run_dir/
|
||||
*.anno.json
|
||||
*.fir
|
||||
*.vcd
|
||||
.metals
|
||||
insns.hex
|
||||
firrtl_black_box_resource_files.f
|
||||
chiselwatt_out.config
|
||||
@@ -18,4 +19,9 @@ Core.v
|
||||
Core.fir
|
||||
Core.anno.json
|
||||
LoadStoreInsns.hex
|
||||
MemoryBlackBoxInsns.hex
|
||||
MemoryBlackBoxInsns.hex
|
||||
samples/micropython
|
||||
samples/hello_world/hello_world.bin
|
||||
samples/hello_world/hello_world.elf
|
||||
samples/hello_world/hello_world.o
|
||||
samples/hello_world/head.o
|
||||
22
Makefile
22
Makefile
@@ -115,13 +115,33 @@ chiselwatt.svf: chiselwatt.bit
|
||||
prog: check-board-vars chiselwatt.svf
|
||||
$(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf chiselwatt.svf; exit"
|
||||
|
||||
apps_dir = ./samples
|
||||
|
||||
hello_world:
|
||||
docker run -it --rm -w /build -v $(PWD):/build carlosedp/crossbuild-ppc64le make -C $(apps_dir)/hello_world
|
||||
@scripts/bin2hex.py $(apps_dir)/hello_world/hello_world.bin > ./insns.hex
|
||||
|
||||
micropython:
|
||||
@if [ ! -d "$(apps_dir)/micropyton/ports/powerpc" ] ; then \
|
||||
rm -rf $(apps_dir)/micropyton; \
|
||||
echo "Cloning micropython repo into $(apps_dir)/micropyton"; \
|
||||
git clone https://github.com/micropython/micropython.git $(apps_dir)/micropyton; \
|
||||
else \
|
||||
echo "Micropython repo exists, updating..."; \
|
||||
cd "$(apps_dir)/micropyton"; \
|
||||
git pull; \
|
||||
fi
|
||||
@docker run -it --rm -v $(PWD):/build carlosedp/crossbuild-ppc64le make -C $(apps_dir)/micropyton/ports/powerpc
|
||||
@scripts/bin2hex.py $(apps_dir)/micropyton/ports/powerpc/build/firmware.bin > ./insns.hex
|
||||
|
||||
clean:
|
||||
@rm -f Core.fir firrtl_black_box_resource_files.f Core.v Core.anno.json MemoryBlackBox.v
|
||||
@rm -rf obj_dir test_run_dir target project
|
||||
@rm -f chiselwatt
|
||||
@rm -f *.bit *.json *.svf *.config
|
||||
@rm -f LoadStoreInsns.hex MemoryBlackBoxInsns.hex
|
||||
@make -C $(apps_dir)/hello_world clean
|
||||
|
||||
.PHONY: clean prog
|
||||
.PHONY: clean prog hello_world micropython
|
||||
.PRECIOUS: chiselwatt.json chiselwatt_out.config chiselwatt.bit
|
||||
|
||||
|
||||
108
README.md
108
README.md
@@ -15,11 +15,13 @@ cd chiselwatt
|
||||
make
|
||||
```
|
||||
|
||||
* A micropython image is included in the repo. To use it, link the memory image
|
||||
into chiselwatt:
|
||||
* The micropython and hello_world sample images are included in the repo. To use
|
||||
it, link the memory image into chiselwatt:
|
||||
|
||||
```sh
|
||||
ln -s micropython/firmware.hex insns.hex
|
||||
ln -s samples/binaries/micropython/firmware.hex insns.hex
|
||||
# or to use the hello_world sample, run
|
||||
ln -s samples/binaries/hello_world/hello_world.hex insns.hex
|
||||
```
|
||||
|
||||
* Now run chiselwatt:
|
||||
@@ -39,54 +41,26 @@ make dockerlator
|
||||
exit
|
||||
```
|
||||
|
||||
## Building micropython from scratch
|
||||
|
||||
* You can also build micropython from scratch. If you aren't building natively
|
||||
on a ppc64le box you will need a cross compiler. This may be available on your
|
||||
distro, otherwise grab the the powerpc64le-power8 toolchain from [bootlin](https://toolchains.bootlin.com).
|
||||
If you are cross compiling, point `CROSS_COMPILE` at the toolchain. In the
|
||||
example below I installed it in usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/
|
||||
and the tools begin with `powerpc64-linux-*`:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/micropython/micropython.git
|
||||
cd micropython
|
||||
cd ports/powerpc
|
||||
make CROSS_COMPILE=/usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/powerpc64le-linux- -j$(nproc)
|
||||
cd ../../../
|
||||
```
|
||||
|
||||
* Build chiselwatt, import the the micropython image and run it. We use
|
||||
bin2hex.py to convert a binary file into a series of 64 bit hex values
|
||||
expected by the tools:
|
||||
|
||||
```sh
|
||||
cd chiselwatt
|
||||
make
|
||||
scripts/bin2hex.py ../micropython/ports/powerpc/build/firmware.bin > insns.hex
|
||||
./chiselwatt
|
||||
```
|
||||
|
||||
## Synthesis using Open Source tools (yosys/nextpnr)
|
||||
## Synthesizing for FPGAs using Open Source tools (yosys/nextpnr)
|
||||
|
||||
Synthesis on FPGAs is supported with yosys/nextpnr. At the moment the tools support
|
||||
Lattice ECP5 FPGAs. The build process uses Docker images, so no software other than Docker needs
|
||||
to be installed. If you prefer podman you can use that too, just adjust it in
|
||||
`Makefile`, `DOCKER=podman`.
|
||||
Lattice ECP5 FPGAs. The build process uses Docker images, so no software other
|
||||
than Docker needs to be installed. If you prefer podman you can use that too,
|
||||
just adjust it in `Makefile`, `DOCKER=podman`.
|
||||
|
||||
### hello_world
|
||||
|
||||
The `hello_world` example should run everywhere, so start with it. Edit `src/main/scala/Core.scala`
|
||||
and set memory to 16 kB (`16*1024`):
|
||||
The `hello_world` example should run everywhere, so start with it.
|
||||
Edit `src/main/scala/Core.scala` and set memory to 16 kB (`16*1024`):
|
||||
|
||||
```
|
||||
```scala
|
||||
chisel3.Driver.execute(Array[String](), () => new Core(64, 16*1024, "insns.hex", 0x0))
|
||||
```
|
||||
|
||||
Then link in the hello_world image:
|
||||
|
||||
```sh
|
||||
ln -s hello_world/hello_world.hex insns.hex
|
||||
ln -s samples/binaries/hello_world/hello_world.hex insns.hex
|
||||
```
|
||||
|
||||
### Building and programming the FPGA
|
||||
@@ -101,7 +75,7 @@ The `Makefile` currently supports the following FPGA boards by defining the `ECP
|
||||
For example, to build for the Evaluation Board, run:
|
||||
|
||||
```sh
|
||||
make ECP5_BOARD=evn synth`
|
||||
make ECP5_BOARD=evn synth
|
||||
```
|
||||
|
||||
and to program the FPGA:
|
||||
@@ -131,16 +105,16 @@ This means we use twice as much block RAM as you would expect. This also means
|
||||
Micropython won't fit on an ECP5 85F, because the ~400kB of available BRAM is halved
|
||||
to ~200k. Micropython requires 384 kB.
|
||||
|
||||
Once this is fixed, edit `src/main/scala/Core.scala` and set memory to 384 kB (`384*1024`):
|
||||
**Once this is fixed**, edit `src/main/scala/Core.scala` and set memory to 384 kB (`384*1024`):
|
||||
|
||||
```
|
||||
```scala
|
||||
chisel3.Driver.execute(Array[String](), () => new Core(64, 384*1024, "insns.hex", 0x0))
|
||||
```
|
||||
|
||||
Then link in the micropython image:
|
||||
|
||||
```sh
|
||||
ln -s micropython/firmware.hex insns.hex
|
||||
ln -s samples/binaries/micropython/firmware.hex insns.hex
|
||||
```
|
||||
|
||||
For example, to build for the ULX3S, run:
|
||||
@@ -155,7 +129,9 @@ and to program the FPGA:
|
||||
make ECP5_BOARD=ulx3s prog
|
||||
```
|
||||
|
||||
## Simple Python script for reading USB serial port
|
||||
If you connect to the serial port of the FPGA at 115200 8n1, you should see "Hello World"
|
||||
and after that all input will be echoed to the output. On Linux, picocom can be used.
|
||||
Another option below is a simple python script.
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
@@ -178,6 +154,50 @@ while 1:
|
||||
print("%s" %(byte))
|
||||
```
|
||||
|
||||
## Building from scratch
|
||||
|
||||
### Hello World
|
||||
|
||||
The hello world sample simply prints "Hello from Chiselwatt, an OpenPower processor!"
|
||||
and echoes the input back to the terminal as a serial console.
|
||||
The source is in `./samples/hello_world` and it can be built by `make hello_world`.
|
||||
The Makefile generates the `insns.hex` file that will be used on the synthesized
|
||||
core to be run on Verilator or loaded into FPGA.
|
||||
|
||||
### Micropython
|
||||
|
||||
You can also build micropython from scratch. As a convenience, there is a Makefile
|
||||
target to cross-build on a Docker container and generate the firmware.
|
||||
Just run `make micropython` and it will generate the `insns.hex` file that will
|
||||
be used on the synthesized core to be run on Verilator or loaded into FPGA.
|
||||
|
||||
If running on a container is not an option, you need a ppc64le box or a cross compiler.
|
||||
This may be available on your distro, otherwise grab the the powerpc64le-power8
|
||||
toolchain from [bootlin](https://toolchains.bootlin.com).
|
||||
|
||||
If you are cross compiling, point `CROSS_COMPILE` at the toolchain. In the
|
||||
example below I installed it in `usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/`
|
||||
and the tools begin with `powerpc64-linux-*`:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/micropython/micropython.git
|
||||
cd micropython
|
||||
cd ports/powerpc
|
||||
make CROSS_COMPILE=/usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/powerpc64le-linux- -j$(nproc)
|
||||
cd ../../../
|
||||
```
|
||||
|
||||
* Build chiselwatt, import the the micropython image and run it. We use
|
||||
bin2hex.py to convert a binary file into a series of 64 bit hex values
|
||||
expected by the tools:
|
||||
|
||||
```sh
|
||||
cd chiselwatt
|
||||
make
|
||||
scripts/bin2hex.py ../micropython/ports/powerpc/build/firmware.bin > insns.hex
|
||||
./chiselwatt
|
||||
```
|
||||
|
||||
## Issues
|
||||
|
||||
Now that it is functional, we have a number of things to add:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
32
samples/Dockerfile.crossbuild-ppc64le
Normal file
32
samples/Dockerfile.crossbuild-ppc64le
Normal file
@@ -0,0 +1,32 @@
|
||||
# build with docker build -t REPO/crossbuild-ppc64le -f Dockerfile.crossbuild-ppc64le .
|
||||
FROM debian:buster
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
ENV TOOLCHAIN_URL https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64le-power8/tarballs/powerpc64le-power8--glibc--bleeding-edge-2020.02-2.tar.bz2
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
autoconf \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
python3 \
|
||||
python3-pip \
|
||||
bzip2 \
|
||||
ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
RUN wget $TOOLCHAIN_URL && \
|
||||
mkdir -p /opt/powerpc64le-toolchain && \
|
||||
tar vxf $(basename $TOOLCHAIN_URL) -C /opt/powerpc64le-toolchain --strip-components=1 && \
|
||||
rm -rf $(basename $TOOLCHAIN_URL)
|
||||
|
||||
ENV PATH /opt/powerpc64le-toolchain/bin:$PATH
|
||||
ENV CROSS_COMPILE powerpc64le-linux-
|
||||
|
||||
RUN powerpc64le-linux-gcc --version
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
Binary file not shown.
Binary file not shown.
@@ -40,7 +40,7 @@ a64b5a7d14004a39
|
||||
60211f0064210000
|
||||
618c00003d800000
|
||||
658c0000798c07c6
|
||||
7d8903a6618c113c
|
||||
7d8903a6618c1194
|
||||
480000004e800421
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
@@ -551,36 +551,63 @@ f80100107c7f1b78
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
7c0802a63842a000
|
||||
fbe1fff8fbc1fff0
|
||||
3be000007c7e1b78
|
||||
f821ffd1f8010010
|
||||
4bffffad7fc3f378
|
||||
419d000c7fa3f840
|
||||
4bfffe8c38210030
|
||||
3bff00017c7ef8ae
|
||||
4bffffdc4bffff15
|
||||
0100000000000000
|
||||
3c40000100000280
|
||||
7c0802a63842a000
|
||||
3fe2fffffbe1fff8
|
||||
f80100103bff7190
|
||||
4bfffec1f821ffd1
|
||||
4bffffad7fe3fb78
|
||||
7fe3fb787c641b78
|
||||
4bfffee94bffff59
|
||||
4bffff195463063e
|
||||
000000004bfffff4
|
||||
f80100103bff7240
|
||||
4bfffe69f821ffd1
|
||||
386372003c62ffff
|
||||
3c62ffff4bffff85
|
||||
4bffff7938637238
|
||||
5463063e4bfffe8d
|
||||
409e00102b83000d
|
||||
4bffff617fe3fb78
|
||||
4bfffea94bffffe8
|
||||
000000004bffffe0
|
||||
0000018001000000
|
||||
6f57206f6c6c6548
|
||||
0000000a0d646c72
|
||||
7266206f6c6c6548
|
||||
6573696843206d6f
|
||||
61202c747461776c
|
||||
6f506e65704f206e
|
||||
636f727020726577
|
||||
0a0d21726f737365
|
||||
0000000000000000
|
||||
000000000000203e
|
||||
00000000203e0a0d
|
||||
0000000000000010
|
||||
0141780400527a01
|
||||
0000001000010c1b
|
||||
fffffe5800000018
|
||||
fffffdb000000018
|
||||
0000000000000040
|
||||
0000002c00000010
|
||||
00000038fffffe84
|
||||
00000038fffffddc
|
||||
0000001000000000
|
||||
fffffea800000040
|
||||
fffffe0000000040
|
||||
0000000000000034
|
||||
0000005400000028
|
||||
00000050fffffec8
|
||||
00000050fffffe20
|
||||
9f029e0041094500
|
||||
437e4111300e4401
|
||||
4106dedf41000e0a
|
||||
000000100000000b
|
||||
fffffeec00000080
|
||||
fffffe4400000080
|
||||
000000000000002c
|
||||
000000940000001c
|
||||
00000054ffffff04
|
||||
44019f0041094400
|
||||
0000007e4111300e
|
||||
0000009400000028
|
||||
00000058fffffe5c
|
||||
9f029e0041094500
|
||||
457e4111300e4401
|
||||
4106dedf41000e0a
|
||||
0000001c0000000b
|
||||
fffffe88000000c0
|
||||
410944000000006c
|
||||
4111300e44019f00
|
||||
000000000000007e
|
||||
BIN
samples/binaries/micropython/firmware.bin
Normal file
BIN
samples/binaries/micropython/firmware.bin
Normal file
Binary file not shown.
BIN
samples/binaries/micropython/firmware.elf
Executable file
BIN
samples/binaries/micropython/firmware.elf
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
28
samples/hello_world/Makefile
Normal file
28
samples/hello_world/Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
ARCH = $(shell uname -m)
|
||||
ifneq ("$(ARCH)", "ppc64")
|
||||
ifneq ("$(ARCH)", "ppc64le")
|
||||
CROSS_COMPILE = powerpc64le-linux-
|
||||
endif
|
||||
endif
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
|
||||
CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections
|
||||
ASFLAGS = $(CFLAGS)
|
||||
LDFLAGS = -T powerpc.lds
|
||||
|
||||
all: hello_world.bin
|
||||
|
||||
hello_world.elf: hello_world.o head.o
|
||||
$(LD) $(LDFLAGS) -o hello_world.elf hello_world.o head.o
|
||||
|
||||
hello_world.bin: hello_world.elf
|
||||
$(OBJCOPY) -O binary hello_world.elf hello_world.bin
|
||||
|
||||
hello_world.hex: hello_world.bin
|
||||
../../scripts/bin2hex.py hello_world.bin > hello_world.hex
|
||||
|
||||
clean:
|
||||
@rm -f *.o hello_world.elf hello_world.bin hello_world.hex
|
||||
107
samples/hello_world/head.S
Normal file
107
samples/hello_world/head.S
Normal file
@@ -0,0 +1,107 @@
|
||||
/* Copyright 2013-2014 IBM Corp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define STACK_TOP 0x2000
|
||||
|
||||
#define FIXUP_ENDIAN \
|
||||
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
|
||||
b 191f; /* Skip trampoline if endian is good */ \
|
||||
.long 0xa600607d; /* mfmsr r11 */ \
|
||||
.long 0x01006b69; /* xori r11,r11,1 */ \
|
||||
.long 0x05009f42; /* bcl 20,31,$+4 */ \
|
||||
.long 0xa602487d; /* mflr r10 */ \
|
||||
.long 0x14004a39; /* addi r10,r10,20 */ \
|
||||
.long 0xa64b5a7d; /* mthsrr0 r10 */ \
|
||||
.long 0xa64b7b7d; /* mthsrr1 r11 */ \
|
||||
.long 0x2402004c; /* hrfid */ \
|
||||
191:
|
||||
|
||||
|
||||
/* Load an immediate 64-bit value into a register */
|
||||
#define LOAD_IMM64(r, e) \
|
||||
lis r,(e)@highest; \
|
||||
ori r,r,(e)@higher; \
|
||||
rldicr r,r, 32, 31; \
|
||||
oris r,r, (e)@h; \
|
||||
ori r,r, (e)@l;
|
||||
|
||||
.section ".head","ax"
|
||||
|
||||
/*
|
||||
* Microwatt currently enters in LE mode at 0x0, so we don't need to
|
||||
* do any endian fix ups>
|
||||
*/
|
||||
. = 0
|
||||
.global _start
|
||||
_start:
|
||||
b boot_entry
|
||||
|
||||
/* QEMU enters at 0x10 */
|
||||
. = 0x10
|
||||
FIXUP_ENDIAN
|
||||
b boot_entry
|
||||
|
||||
. = 0x100
|
||||
FIXUP_ENDIAN
|
||||
b boot_entry
|
||||
|
||||
.global boot_entry
|
||||
boot_entry:
|
||||
/* setup stack */
|
||||
LOAD_IMM64(%r1, STACK_TOP - 0x100)
|
||||
LOAD_IMM64(%r12, main)
|
||||
mtctr %r12,
|
||||
bctrl
|
||||
b .
|
||||
|
||||
#define EXCEPTION(nr) \
|
||||
.= nr; \
|
||||
b .
|
||||
|
||||
/* More exception stubs */
|
||||
EXCEPTION(0x300)
|
||||
EXCEPTION(0x380)
|
||||
EXCEPTION(0x400)
|
||||
EXCEPTION(0x480)
|
||||
EXCEPTION(0x500)
|
||||
EXCEPTION(0x600)
|
||||
EXCEPTION(0x700)
|
||||
EXCEPTION(0x800)
|
||||
EXCEPTION(0x900)
|
||||
EXCEPTION(0x980)
|
||||
EXCEPTION(0xa00)
|
||||
EXCEPTION(0xb00)
|
||||
EXCEPTION(0xc00)
|
||||
EXCEPTION(0xd00)
|
||||
EXCEPTION(0xe00)
|
||||
EXCEPTION(0xe20)
|
||||
EXCEPTION(0xe40)
|
||||
EXCEPTION(0xe60)
|
||||
EXCEPTION(0xe80)
|
||||
EXCEPTION(0xf00)
|
||||
EXCEPTION(0xf20)
|
||||
EXCEPTION(0xf40)
|
||||
EXCEPTION(0xf60)
|
||||
EXCEPTION(0xf80)
|
||||
#if 0
|
||||
EXCEPTION(0x1000)
|
||||
EXCEPTION(0x1100)
|
||||
EXCEPTION(0x1200)
|
||||
EXCEPTION(0x1300)
|
||||
EXCEPTION(0x1400)
|
||||
EXCEPTION(0x1500)
|
||||
EXCEPTION(0x1600)
|
||||
#endif
|
||||
164
samples/hello_world/hello_world.c
Normal file
164
samples/hello_world/hello_world.c
Normal file
@@ -0,0 +1,164 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Core UART functions to implement for a port
|
||||
*/
|
||||
|
||||
static uint64_t potato_uart_base;
|
||||
|
||||
#define PROC_FREQ 50000000
|
||||
#define UART_FREQ 115200
|
||||
#define UART_BASE 0xc0002000
|
||||
|
||||
#define POTATO_CONSOLE_TX 0x00
|
||||
#define POTATO_CONSOLE_RX 0x08
|
||||
#define POTATO_CONSOLE_STATUS 0x10
|
||||
#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
|
||||
#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
|
||||
#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
|
||||
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
|
||||
#define POTATO_CONSOLE_CLOCK_DIV 0x18
|
||||
#define POTATO_CONSOLE_IRQ_EN 0x20
|
||||
|
||||
static uint64_t potato_uart_reg_read(int offset)
|
||||
{
|
||||
uint64_t addr;
|
||||
uint64_t val;
|
||||
|
||||
addr = potato_uart_base + offset;
|
||||
|
||||
val = *(volatile uint64_t *)addr;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void potato_uart_reg_write(int offset, uint64_t val)
|
||||
{
|
||||
uint64_t addr;
|
||||
|
||||
addr = potato_uart_base + offset;
|
||||
|
||||
*(volatile uint64_t *)addr = val;
|
||||
}
|
||||
|
||||
static int potato_uart_rx_empty(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
|
||||
|
||||
if (val & POTATO_CONSOLE_STATUS_RX_EMPTY)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int potato_uart_tx_full(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
|
||||
|
||||
if (val & POTATO_CONSOLE_STATUS_TX_FULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char potato_uart_read(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_RX);
|
||||
|
||||
return (char)(val & 0x000000ff);
|
||||
}
|
||||
|
||||
static void potato_uart_write(char c)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = c;
|
||||
|
||||
potato_uart_reg_write(POTATO_CONSOLE_TX, val);
|
||||
}
|
||||
|
||||
static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq)
|
||||
{
|
||||
return proc_freq / (uart_freq * 16) - 1;
|
||||
}
|
||||
|
||||
void potato_uart_init(void)
|
||||
{
|
||||
potato_uart_base = UART_BASE;
|
||||
|
||||
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ));
|
||||
}
|
||||
|
||||
int getchar(void)
|
||||
{
|
||||
while (potato_uart_rx_empty())
|
||||
/* Do nothing */;
|
||||
|
||||
return potato_uart_read();
|
||||
}
|
||||
|
||||
void putchar(unsigned char c)
|
||||
{
|
||||
while (potato_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
|
||||
potato_uart_write(c);
|
||||
}
|
||||
|
||||
void putstr(const char *str, unsigned long len)
|
||||
{
|
||||
for (unsigned long i = 0; i < len; i++)
|
||||
{
|
||||
putchar(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void puts(const char *str)
|
||||
{
|
||||
for (unsigned long i = 0; i < strlen(str); i++)
|
||||
{
|
||||
putchar(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
while (*s++)
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#define HELLO_WORLD "Hello from Chiselwatt, an OpenPower processor!\r\n"
|
||||
#define CLEAR "\033[2K"
|
||||
int main(void)
|
||||
{
|
||||
potato_uart_init();
|
||||
|
||||
puts(HELLO_WORLD);
|
||||
puts("> ");
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned char c = getchar();
|
||||
if (c == '\r')
|
||||
{
|
||||
puts("\r\n> ");
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
samples/hello_world/powerpc.lds
Normal file
13
samples/hello_world/powerpc.lds
Normal file
@@ -0,0 +1,13 @@
|
||||
SECTIONS
|
||||
{
|
||||
_start = .;
|
||||
. = 0;
|
||||
.head : {
|
||||
KEEP(*(.head))
|
||||
}
|
||||
. = 0x1000;
|
||||
.text : { *(.text) }
|
||||
. = 0x2000;
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss) }
|
||||
}
|
||||
1
samples/micropyton
Submodule
1
samples/micropyton
Submodule
Submodule samples/micropyton added at 0bfd55afbe
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
@@ -12,7 +12,7 @@ tempdir = tempfile.TemporaryDirectory()
|
||||
cwd = os.getcwd()
|
||||
os.chdir(tempdir.name)
|
||||
|
||||
copyfile(os.path.join(cwd, 'micropython/firmware.hex'),
|
||||
copyfile(os.path.join(cwd, 'samples/binaries/micropython/firmware.hex'),
|
||||
os.path.join(tempdir.name, 'insns.hex'))
|
||||
|
||||
cmd = [ os.path.join(cwd, 'chiselwatt') ]
|
||||
|
||||
Reference in New Issue
Block a user