hazard3.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_HAZARD3_
8#define _HARDWARE_HAZARD3_
9
10#include "pico.h"
11#include "hardware/riscv.h"
12#include "hardware/regs/rvcsr.h"
13
21// Feature detection macros for Hazard3 custom extensions
22#if PICO_RP2350
23#define __hazard3_extension_xh3power
24#define __hazard3_extension_xh3bextm
25#define __hazard3_extension_xh3irq
26#define __hazard3_extension_xh3pmpm
27#endif
28
29#ifdef __ASSEMBLER__
30
31// Assembly language instruction macros for Hazard3 custom instructions
32
33// h3.bextm: Extract up to 8 consecutive bits from register rs1, with the
34// first bit indexed by rs2, and bit count configured by an immediate value.
35// R-format instruction. Pseudocode:
36//
37// rd = (rs1 >> rs2[4:0]) & ~(-1 << nbits)
38
39.macro h3.bextm rd rs1 rs2 nbits
40.if (\nbits < 1) || (\nbits > 8)
41.err
42.endif
43#ifdef __hazard3_extension_xh3bextm
44 .insn r 0x0b, 0x4, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
45#else
46 srl \rd, \rs1, \rs2
47 andi \rd, \rd, ((1 << \nbits) - 1)
48#endif
49.endm
50
51// h3.bextmi: Extract up to 8 consecutive bits from register rs1, with the
52// first bit index and the number of bits both configured by immediate
53// values. I-format instruction. Pseudocode:
54//
55// rd = (rs1 >> shamt) & ~(-1 << nbits)
56
57.macro h3.bextmi rd rs1 shamt nbits
58.if (\nbits < 1) || (\nbits > 8)
59.err
60.endif
61.if (\shamt < 0) || (\shamt > 31)
62.err
63.endif
64#ifdef __hazard3_extension_xh3bextm
65 .insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
66#else
67 srli \rd, \rs1, \shamt
68 andi \rd, \rd, ((1 << \nbits) - 1)
69#endif
70.endm
71
72// h3.block: enter an idle state until another processor in the same
73// multiprocessor complex executes an h3.unblock instruction, or the
74// processor is interrupted. Fall through immediately if an h3.unblock has
75// been received since the last execution of an h3.block on this processor.
76// On RP2350, processors also have their own h3.unblock signals reflected
77// back to them.
78
79.macro h3.block
80#ifdef __hazard3_extension_xh3power
81 slt x0, x0, x0
82#else
83 nop
84#endif
85.endm
86
87// h3.unblock: signal other processors in the same multiprocessor complex to
88// exit the idle state entered by an h3.block instruction. On RP2350, this
89// signal is also reflected back to the processor that executed the
90// h3.unblock, which will cause that processor's next h3.block to fall
91// through immediately.
92
93.macro h3.unblock
94#ifdef __hazard3_extension_xh3power
95 slt x0, x0, x1
96#else
97 nop
98#endif
99.endm
100
101#else // !__ASSEMBLER__
102
103#ifdef __cplusplus
104extern "C" {
105#endif
106
107#ifdef __hazard3_extension_xh3irq
108#define hazard3_irqarray_read(csr, index) (riscv_read_set_csr(csr, (index)) >> 16)
109#else
110#define hazard3_irqarray_read(csr, index) static_assert(false, "Not supported: Xh3irq extension")
111#endif
112
113#ifdef __hazard3_extension_xh3irq
114#define hazard3_irqarray_write(csr, index, data) (riscv_write_csr(csr, (index) | ((uint32_t)(data) << 16)))
115#else
116#define hazard3_irqarray_write(csr, index, data) static_assert(false, "Not supported: Xh3irq extension")
117#endif
118
119#ifdef __hazard3_extension_xh3irq
120#define hazard3_irqarray_set(csr, index, data) (riscv_set_csr(csr, (index) | ((uint32_t)(data) << 16)))
121#else
122#define hazard3_irqarray_set(csr, index, data) static_assert(false, "Not supported: Xh3irq extension")
123#endif
124
125#ifdef __hazard3_extension_xh3irq
126#define hazard3_irqarray_clear(csr, index, data) (riscv_clear_csr(csr, (index) | ((uint32_t)(data) << 16)))
127#else
128#define hazard3_irqarray_clear(csr, index, data) static_assert(false, "Not supported: Xh3irq extension")
129#endif
130
131
132// nbits must be a constant expression
133#ifdef __hazard3_extension_xh3bextm
134#define __hazard3_bextm(nbits, rs1, rs2) ({\
135 uint32_t __h3_bextm_rd; \
136 asm (".insn r 0x0b, 0, %3, %0, %1, %2"\
137 : "=r" (__h3_bextm_rd) \
138 : "r" (rs1), "r" (rs2), "i" ((((nbits) - 1) & 0x7) << 1)\
139 ); \
140 __h3_bextm_rd; \
141})
142#else
143#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((rs2) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
144#endif
145
146// nbits and shamt must be constant expressions
147#ifdef __hazard3_extension_xh3bextm
148#define __hazard3_bextmi(nbits, rs1, shamt) ({\
149 uint32_t __h3_bextmi_rd; \
150 asm (".insn i 0x0b, 0x4, %0, %1, %2"\
151 : "=r" (__h3_bextmi_rd) \
152 : "r" (rs1), "i" ((((nbits) - 1) & 0x7) << 6 | ((shamt) & 0x1f)) \
153 ); \
154 __h3_bextmi_rd; \
155})
156#else
157#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((shamt) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
158#endif
159
160#ifdef __hazard3_extension_xh3power
161#define __hazard3_block() asm volatile ("slt x0, x0, x0" : : : "memory")
162#else
163#define __hazard3_block() do {} while (0)
164#endif
165
166#ifdef __hazard3_extension_xh3power
167#define __hazard3_unblock() asm volatile ("slt x0, x0, x1" : : : "memory")
168#else
169#define __hazard3_unblock() do {} while (0)
170#endif
171
172#ifdef __cplusplus
173}
174#endif
175
176#endif // !__ASSEMBLER__
177
178#endif