From 82d4de34d0ab8daa29f886ea9793ac38922a6f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Tue, 11 Jun 2024 03:55:05 +0200 Subject: [PATCH 1/2] software: constrain the alignment of memory-mapped registers. Otherwise, GCC/Clang will serialize 32-bit accesses as four 8-bit instructions. Clang will schedule them in descending order, which violates the SoC memory model (Amaranth SoC CSRs must be accessed in ascending order of addresses). --- chipflow_lib/software/drivers/gpio.h | 2 +- chipflow_lib/software/drivers/plat_timer.h | 2 +- chipflow_lib/software/drivers/soc_id.h | 2 +- chipflow_lib/software/drivers/spiflash.h | 2 +- chipflow_lib/software/drivers/uart.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chipflow_lib/software/drivers/gpio.h b/chipflow_lib/software/drivers/gpio.h index 4b7bb3dc..711864d3 100644 --- a/chipflow_lib/software/drivers/gpio.h +++ b/chipflow_lib/software/drivers/gpio.h @@ -4,7 +4,7 @@ #include -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed, aligned(4))) { uint32_t out; uint32_t oe; uint32_t in; diff --git a/chipflow_lib/software/drivers/plat_timer.h b/chipflow_lib/software/drivers/plat_timer.h index 626f8ee3..0c4eb332 100644 --- a/chipflow_lib/software/drivers/plat_timer.h +++ b/chipflow_lib/software/drivers/plat_timer.h @@ -4,7 +4,7 @@ #include -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed, aligned(4))) { uint32_t cnt_lo; uint32_t cnt_hi; uint32_t cmp_lo; diff --git a/chipflow_lib/software/drivers/soc_id.h b/chipflow_lib/software/drivers/soc_id.h index 946ac19c..c0936b61 100644 --- a/chipflow_lib/software/drivers/soc_id.h +++ b/chipflow_lib/software/drivers/soc_id.h @@ -4,7 +4,7 @@ #include -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed, aligned(4))) { uint32_t type; uint32_t version; } soc_id_regs_t; diff --git a/chipflow_lib/software/drivers/spiflash.h b/chipflow_lib/software/drivers/spiflash.h index 661310f6..1dda92e2 100644 --- a/chipflow_lib/software/drivers/spiflash.h +++ b/chipflow_lib/software/drivers/spiflash.h @@ -7,7 +7,7 @@ #define WINBOND_ID 0x40 #define ISSI_ID 0x60 -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed, aligned(4))) { uint32_t ctrl; } spiflash_regs_t; diff --git a/chipflow_lib/software/drivers/uart.h b/chipflow_lib/software/drivers/uart.h index 1f237965..451335e3 100644 --- a/chipflow_lib/software/drivers/uart.h +++ b/chipflow_lib/software/drivers/uart.h @@ -4,7 +4,7 @@ #include -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed, aligned(4))) { uint32_t tx_data; uint32_t rx_data; uint32_t tx_ready; From a61b83f746f4ff546165146f03c91f46f15a98c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Tue, 11 Jun 2024 04:13:16 +0200 Subject: [PATCH 2/2] Use Amaranth SoC GPIO peripheral. --- chipflow_lib/providers/board_ulx3s.py | 20 ++++++------- chipflow_lib/providers/silicon.py | 27 +++++++++-------- chipflow_lib/providers/sim.py | 18 ++++++----- chipflow_lib/software/drivers/gpio.h | 43 ++++++++++++++++++++++++--- chipflow_lib/software/soft_gen.py | 5 ---- 5 files changed, 73 insertions(+), 40 deletions(-) diff --git a/chipflow_lib/providers/board_ulx3s.py b/chipflow_lib/providers/board_ulx3s.py index cb05d0fa..7c38c008 100644 --- a/chipflow_lib/providers/board_ulx3s.py +++ b/chipflow_lib/providers/board_ulx3s.py @@ -3,10 +3,12 @@ from amaranth import * from amaranth_boards.ulx3s import * from amaranth.lib.cdc import ResetSynchronizer -from amaranth.lib import io +from amaranth.lib import io, wiring +from amaranth.lib.wiring import In + +from amaranth_soc import gpio from amaranth_orchard.memory.spimemio import QSPIPins -from amaranth_orchard.base.gpio import GPIOPins from amaranth_orchard.io.uart import UARTPins from amaranth_orchard.memory.hyperram import HyperRAMPins @@ -47,29 +49,27 @@ def elaborate(self, platform): return m -class LEDGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=8) +class LEDGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(8) def elaborate(self, platform): m = Module() for i in range(8): led = io.Buffer("o", platform.request("led", i, dir="-")) m.submodules[f"led_{i}"] = led - m.d.comb += led.o.eq(self.pins.o[i]) + m.d.comb += led.o.eq(self.pins[i].o) return m -class ButtonGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=2) +class ButtonGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(2) def elaborate(self, platform): m = Module() for i in range(2): btn = io.Buffer("i", platform.request("button_fire", i, dir="-")) m.submodules[f"btn_{i}"] = btn - m.d.comb += self.pins.i[i].eq(btn.i) + m.d.comb += self.pins[i].i.eq(btn.i) return m diff --git a/chipflow_lib/providers/silicon.py b/chipflow_lib/providers/silicon.py index a1498690..71e04293 100644 --- a/chipflow_lib/providers/silicon.py +++ b/chipflow_lib/providers/silicon.py @@ -2,9 +2,12 @@ from amaranth import * from amaranth.lib.cdc import FFSynchronizer +from amaranth.lib import wiring +from amaranth.lib.wiring import In + +from amaranth_soc import gpio from amaranth_orchard.memory.spimemio import QSPIPins -from amaranth_orchard.base.gpio import GPIOPins from amaranth_orchard.io.uart import UARTPins from amaranth_orchard.memory.hyperram import HyperRAMPins @@ -29,34 +32,32 @@ def elaborate(self, platform): return m -class LEDGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=8) +class LEDGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(8) def elaborate(self, platform): m = Module() for index in range(8): pin = platform.request(f"gpio_{index}") m.d.comb += [ - self.pins.i[index].eq(pin.i), - pin.o.eq(self.pins.o[index]), - pin.oe.eq(self.pins.oe[index]) + self.pins[index].i.eq(pin.i), + pin.o.eq(self.pins[index].o), + pin.oe.eq(self.pins[index].oe), ] return m -class ButtonGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=2) +class ButtonGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(2) def elaborate(self, platform): m = Module() for index in range(2): pin = platform.request(f"btn_{index}") m.d.comb += [ - self.pins.i[index].eq(pin.i), - pin.o.eq(self.pins.o[index]), - pin.oe.eq(self.pins.oe[index]) + self.pins[index].i.eq(pin.i), + pin.o.eq(self.pins[index].o), + pin.oe.eq(self.pins[index].oe), ] return m diff --git a/chipflow_lib/providers/sim.py b/chipflow_lib/providers/sim.py index 38e22516..bdf9bef2 100644 --- a/chipflow_lib/providers/sim.py +++ b/chipflow_lib/providers/sim.py @@ -1,9 +1,12 @@ # SPDX-License-Identifier: BSD-2-Clause from amaranth import * +from amaranth.lib import wiring +from amaranth.lib.wiring import In + +from amaranth_soc import gpio from amaranth_orchard.memory.spimemio import QSPIPins -from amaranth_orchard.base.gpio import GPIOPins from amaranth_orchard.io.uart import UARTPins from amaranth_orchard.memory.hyperram import HyperRAMPins @@ -16,21 +19,20 @@ def elaborate(self, platform): return platform.add_model("spiflash_model", self.pins, edge_det=['clk_o', 'csn_o']) -class LEDGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=8) +class LEDGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(8) def elaborate(self, platform): return Module() -class ButtonGPIOProvider(Elaboratable): - def __init__(self): - self.pins = GPIOPins(width=2) +class ButtonGPIOProvider(wiring.Component): + pins: In(gpio.PinSignature()).array(2) def elaborate(self, platform): m = Module() - m.d.comb += self.pins.i.eq(platform.buttons) + for i in range(2): + m.d.comb += self.pins[i].i.eq(platform.buttons[i]) return m diff --git a/chipflow_lib/software/drivers/gpio.h b/chipflow_lib/software/drivers/gpio.h index 711864d3..5ba953eb 100644 --- a/chipflow_lib/software/drivers/gpio.h +++ b/chipflow_lib/software/drivers/gpio.h @@ -4,10 +4,45 @@ #include -typedef struct __attribute__((packed, aligned(4))) { - uint32_t out; - uint32_t oe; - uint32_t in; +typedef struct __attribute__((packed, aligned(2))) { + uint16_t mode; + uint8_t input; + uint8_t output; + uint16_t setclr; } gpio_regs_t; +typedef enum { +#define _GPIO_PIN(n) \ + GPIO_PIN ## n ## _INPUT_ONLY = (0 << 2 * (n)), \ + GPIO_PIN ## n ## _PUSH_PULL = (1 << 2 * (n)), \ + GPIO_PIN ## n ## _OPEN_DRAIN = (2 << 2 * (n)), \ + GPIO_PIN ## n ## _ALTERNATE = (3 << 2 * (n)) + + _GPIO_PIN(0), + _GPIO_PIN(1), + _GPIO_PIN(2), + _GPIO_PIN(3), + _GPIO_PIN(4), + _GPIO_PIN(5), + _GPIO_PIN(6), + _GPIO_PIN(7), +#undef _GPIO_PIN +} gpio_mode_t; + +typedef enum { +#define _GPIO_PIN(n) \ + GPIO_PIN ## n ## _SET = (1 << 2 * (n)), \ + GPIO_PIN ## n ## _CLEAR = (2 << 2 * (n)) + + _GPIO_PIN(0), + _GPIO_PIN(1), + _GPIO_PIN(2), + _GPIO_PIN(3), + _GPIO_PIN(4), + _GPIO_PIN(5), + _GPIO_PIN(6), + _GPIO_PIN(7), +#undef _GPIO_PIN +} gpio_setclr_t; + #endif diff --git a/chipflow_lib/software/soft_gen.py b/chipflow_lib/software/soft_gen.py index 65fd51cd..217c8ae4 100644 --- a/chipflow_lib/software/soft_gen.py +++ b/chipflow_lib/software/soft_gen.py @@ -126,11 +126,6 @@ def start(self): blt a0, a1, loop_init_bss end_init_bss: -# Update LEDs -li a0, 0xb1000000 -li a1, 2 -sw a1, 0(a0) - # call main call main loop: