TT-System-Firmware APIs 19.17.99
Tenstorrent Firmware
Loading...
Searching...
No Matches
uart_tt_virt.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Tenstorrent AI ULC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
11
12#ifndef TENSTORRENT_UART_TT_VIRT_H_
13#define TENSTORRENT_UART_TT_VIRT_H_
14
15#include <assert.h>
16#include <stdatomic.h>
17#include <stdbool.h>
18#include <stddef.h>
19#include <stdint.h>
20
21#ifdef CONFIG_UART_TT_VIRT_TX_BLOCK
22#include <zephyr/kernel.h>
23#endif
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
33
50
85
93static inline size_t tt_vuart_inst(volatile const struct tt_vuart *vuart)
94{
95 return vuart->version >> 24;
96}
97
106{
107 return tail - head;
108}
109
119{
120 return cap - (tt_vuart_buf_size(head, tail));
121}
122
130static inline bool tt_vuart_buf_empty(uint32_t head, uint32_t tail)
131{
132 return tt_vuart_buf_size(head, tail) == 0;
133}
134
143static inline bool tt_vuart_buf_full(uint32_t head, uint32_t tail, uint32_t cap)
144{
145 return tt_vuart_buf_size(head, tail) == cap;
146}
147
159static inline int tt_vuart_poll_in(volatile struct tt_vuart *vuart, unsigned char *p_char,
160 enum tt_vuart_role role)
161{
162 uint32_t cap;
163 uint32_t offs;
164 uint32_t tail;
165 uint32_t head;
166 volatile atomic_uint *headp;
167
168 do {
169 if (role == TT_VUART_ROLE_DEVICE) {
170 headp = (volatile atomic_uint *)&vuart->rx_head;
171 head = vuart->rx_head;
172 tail = vuart->rx_tail;
173 cap = vuart->rx_cap;
174 offs = vuart->tx_cap;
175 } else if (role == TT_VUART_ROLE_HOST) {
176 headp = (volatile atomic_uint *)&vuart->tx_head;
177 head = vuart->tx_head;
178 tail = vuart->tx_tail;
179 cap = vuart->tx_cap;
180 offs = 0;
181 } else {
182 assert((role == TT_VUART_ROLE_DEVICE) || (role == TT_VUART_ROLE_HOST));
183 return -1;
184 }
185
186 if (tt_vuart_buf_empty(head, tail)) {
187 return -1;
188 }
189
190 /*
191 * Read before publishing the advanced head. Otherwise a producer can
192 * observe the freed slot and overwrite it before it is consumed.
193 */
194 atomic_thread_fence(memory_order_acquire);
195 unsigned char ch = vuart->buf[offs + (head % cap)];
196
197 if (atomic_compare_exchange_strong(headp, &head, head + 1)) {
198 *p_char = ch;
199 return *p_char;
200 }
201 } while (true);
202
203 assert(false);
204 return -1;
205}
206
225static inline void tt_vuart_poll_out(volatile struct tt_vuart *vuart, unsigned char out_char,
226 enum tt_vuart_role role)
227{
228 uint32_t head;
229 uint32_t cap;
230 uint32_t offs;
231 uint32_t tail;
232 volatile atomic_uint *tailp;
233
234#ifdef CONFIG_UART_TT_VIRT_TX_BLOCK
235 const uint32_t tx_block_deadline =
236 k_uptime_get_32() + CONFIG_UART_TT_VIRT_TX_BLOCK_TIMEOUT_MS;
237#endif
238
239 do {
240 if (role == TT_VUART_ROLE_DEVICE) {
241 tailp = (volatile atomic_uint *)&vuart->tx_tail;
242 tail = vuart->tx_tail;
243 head = vuart->tx_head;
244 cap = vuart->tx_cap;
245 offs = 0;
246 } else if (role == TT_VUART_ROLE_HOST) {
247 tailp = (volatile atomic_uint *)&vuart->rx_tail;
248 tail = vuart->rx_tail;
249 head = vuart->rx_head;
250 cap = vuart->rx_cap;
251 offs = vuart->tx_cap;
252 } else {
253 assert((role == TT_VUART_ROLE_DEVICE) || (role == TT_VUART_ROLE_HOST));
254 break;
255 }
256
257 if ((role == TT_VUART_ROLE_DEVICE) && tt_vuart_buf_full(head, tail, cap)) {
258#ifdef CONFIG_UART_TT_VIRT_TX_BLOCK
259 if ((int32_t)(k_uptime_get_32() - tx_block_deadline) >= 0) {
260 ++vuart->tx_oflow;
261 return;
262 }
263 continue;
264#else
265 ++vuart->tx_oflow;
266 return;
267#endif
268 }
269
270 /*
271 * Store the byte before publishing the new tail, so a consumer that
272 * observes the tail also observes the data.
273 */
274 vuart->buf[offs + (tail % cap)] = out_char;
275 atomic_store_explicit(tailp, tail + 1, memory_order_release);
276 return;
277 } while (true);
278}
279
280#ifdef __ZEPHYR__
281#include <zephyr/device.h>
282
289volatile struct tt_vuart *uart_tt_virt_get(const struct device *dev);
290
301volatile struct tt_vuart *uart_tt_virt_lookup_callback(size_t inst);
302
309void uart_tt_virt_init_callback(const struct device *dev, size_t inst);
310
311#endif
312
316
317#ifdef __cplusplus
318}
319#endif
320
321#endif /* TENSTORRENT_UART_TT_VIRT_H_ */
#define assert(test)
static uint32_t k_uptime_get_32(void)
tt_vuart_role
Role of the virtual UART in the context of the shared memory buffer.
Definition uart_tt_virt.h:46
static bool tt_vuart_buf_empty(uint32_t head, uint32_t tail)
Determine if the given buffer is empty.
Definition uart_tt_virt.h:130
static uint32_t tt_vuart_buf_size(uint32_t head, uint32_t tail)
Determine the size of the given buffer.
Definition uart_tt_virt.h:105
static bool tt_vuart_buf_full(uint32_t head, uint32_t tail, uint32_t cap)
Determine if the given buffer is full.
Definition uart_tt_virt.h:143
static uint32_t tt_vuart_buf_space(uint32_t head, uint32_t tail, uint32_t cap)
Determine the free space available in the given buffer.
Definition uart_tt_virt.h:118
static int tt_vuart_poll_in(volatile struct tt_vuart *vuart, unsigned char *p_char, enum tt_vuart_role role)
Poll the virtual UART buffer for incoming data.
Definition uart_tt_virt.h:159
static size_t tt_vuart_inst(volatile const struct tt_vuart *vuart)
Determine the instance number of a virtual UART buffer descriptor.
Definition uart_tt_virt.h:93
static void tt_vuart_poll_out(volatile struct tt_vuart *vuart, unsigned char out_char, enum tt_vuart_role role)
Poll the virtual UART buffer with outgoing data.
Definition uart_tt_virt.h:225
@ TT_VUART_ROLE_DEVICE
Definition uart_tt_virt.h:47
@ TT_VUART_ROLE_HOST
Definition uart_tt_virt.h:48
__UINT32_TYPE__ uint32_t
__INT32_TYPE__ int32_t
__UINT8_TYPE__ uint8_t
In-memory ring buffer descriptor for Tenstorrent virtual UART.
Definition uart_tt_virt.h:73
uint32_t tx_head
Definition uart_tt_virt.h:79
uint32_t magic
Definition uart_tt_virt.h:74
uint32_t rx_cap
Definition uart_tt_virt.h:75
uint32_t tx_oflow
Definition uart_tt_virt.h:80
uint32_t rx_tail
Definition uart_tt_virt.h:77
uint32_t version
Definition uart_tt_virt.h:82
uint32_t tx_tail
Definition uart_tt_virt.h:81
uint32_t tx_cap
Definition uart_tt_virt.h:78
uint32_t rx_head
Definition uart_tt_virt.h:76
uint8_t buf[]
Definition uart_tt_virt.h:83
__weak volatile struct tt_vuart * uart_tt_virt_lookup_callback(size_t inst)
Definition uart_tt_virt.c:367
__weak void uart_tt_virt_init_callback(const struct device *dev, size_t inst)
Definition uart_tt_virt.c:361
volatile struct tt_vuart * uart_tt_virt_get(const struct device *dev)
Definition uart_tt_virt.c:374