OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_rte.c] - Blame information for rev 74

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_rte.c - NEORV32 Runtime Environment >>                                    #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 70 zero_gravi
// # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
7 2 zero_gravi
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file neorv32_rte.c
38
 * @brief NEORV32 Runtime Environment.
39
 **************************************************************************/
40
 
41
#include "neorv32.h"
42
#include "neorv32_rte.h"
43
 
44 14 zero_gravi
/**********************************************************************//**
45
 * The >private< trap vector look-up table of the NEORV32 RTE.
46
 **************************************************************************/
47 58 zero_gravi
static uint32_t __neorv32_rte_vector_lut[NEORV32_RTE_NUM_TRAPS] __attribute__((unused)); // trap handler vector table
48 14 zero_gravi
 
49
// private functions
50 68 zero_gravi
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(4)));
51 64 zero_gravi
static void __neorv32_rte_debug_exc_handler(void);
52
static void __neorv32_rte_print_true_false(int state);
53 65 zero_gravi
static void __neorv32_rte_print_checkbox(int state);
54 33 zero_gravi
static void __neorv32_rte_print_hex_word(uint32_t num);
55 2 zero_gravi
 
56
 
57
/**********************************************************************//**
58 14 zero_gravi
 * Setup NEORV32 runtime environment.
59 2 zero_gravi
 *
60
 * @note This function installs a debug handler for ALL exception and interrupt sources, which
61 14 zero_gravi
 * gives detailed information about the exception/interrupt. Actual handler can be installed afterwards
62
 * via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
63 2 zero_gravi
 **************************************************************************/
64 14 zero_gravi
void neorv32_rte_setup(void) {
65 2 zero_gravi
 
66 14 zero_gravi
  // configure trap handler base address
67 68 zero_gravi
  neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)(&__neorv32_rte_core));
68 2 zero_gravi
 
69 74 zero_gravi
  // disable all IRQ channels
70
  neorv32_cpu_csr_write(CSR_MIE, 0);
71
 
72
  // clear all pending IRQs
73
  neorv32_cpu_csr_write(CSR_MIP, 0);
74
 
75
  // clear BUSKEEPER error flags
76
  NEORV32_BUSKEEPER.CTRL = 0;
77
 
78 2 zero_gravi
  // install debug handler for all sources
79 14 zero_gravi
  uint8_t id;
80
  for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
81
    neorv32_rte_exception_uninstall(id); // this will configure the debug handler
82 2 zero_gravi
  }
83
}
84
 
85
 
86
/**********************************************************************//**
87
 * Install exception handler function to NEORV32 runtime environment.
88
 *
89 17 zero_gravi
 * @note Interrupt sources have to be explicitly enabled by the user via the CSR.mie bits via neorv32_cpu_irq_enable(uint8_t irq_sel)
90
 * and the global interrupt enable bit mstatus.mie via neorv32_cpu_eint(void).
91 2 zero_gravi
 *
92 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
93
 * @param[in] handler The actual handler function for the specified exception (function MUST be of type "void function(void);").
94 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
95 2 zero_gravi
 **************************************************************************/
96 14 zero_gravi
int neorv32_rte_exception_install(uint8_t id, void (*handler)(void)) {
97 2 zero_gravi
 
98
  // id valid?
99 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
100 24 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
101 2 zero_gravi
    return 0;
102
  }
103
  return 1;
104
}
105
 
106
 
107
/**********************************************************************//**
108
 * Uninstall exception handler function from NEORV32 runtime environment, which was
109 14 zero_gravi
 * previously installed via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
110 2 zero_gravi
 *
111 17 zero_gravi
 * @note Interrupt sources have to be explicitly disabled by the user via the CSR.mie bits via neorv32_cpu_irq_disable(uint8_t irq_sel)
112
 * and/or the global interrupt enable bit mstatus.mie via neorv32_cpu_dint(void).
113 2 zero_gravi
 *
114 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
115 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
116 2 zero_gravi
 **************************************************************************/
117 14 zero_gravi
int neorv32_rte_exception_uninstall(uint8_t id) {
118 2 zero_gravi
 
119
  // id valid?
120 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
121 68 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidentally triggered
122 2 zero_gravi
    return 0;
123
  }
124
  return 1;
125
}
126
 
127
 
128
/**********************************************************************//**
129 14 zero_gravi
 * This is the core of the NEORV32 RTE.
130
 *
131
 * @note This function must no be explicitly used by the user.
132 33 zero_gravi
 * @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
133
 *
134 14 zero_gravi
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
135 2 zero_gravi
 **************************************************************************/
136 73 zero_gravi
static void __attribute__((__interrupt__)) __attribute__((aligned(4))) __neorv32_rte_core(void) {
137 2 zero_gravi
 
138 33 zero_gravi
  register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
139 74 zero_gravi
  neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // backup for later
140 14 zero_gravi
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
141
 
142
  // compute return address
143 68 zero_gravi
  if (((int32_t)rte_mcause) >= 0) { // modify pc only if not interrupt (MSB cleared)
144 14 zero_gravi
 
145
    // get low half word of faulting instruction
146 73 zero_gravi
    register uint32_t rte_trap_inst = neorv32_cpu_load_unsigned_half(rte_mepc);
147 14 zero_gravi
 
148 74 zero_gravi
    rte_mepc += 4; // default: faulting instruction is uncompressed
149
    if (neorv32_cpu_csr_read(CSR_MISA) & (1 << CSR_MISA_C)) { // C extension implemented?
150
      if ((rte_trap_inst & 3) != 3) { // faulting instruction is compressed instruction
151
        rte_mepc -= 2;
152
      }
153 14 zero_gravi
    }
154
 
155
    // store new return address
156
    neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
157
  }
158
 
159
  // find according trap handler
160 68 zero_gravi
  register uint32_t rte_handler;
161 14 zero_gravi
  switch (rte_mcause) {
162
    case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
163
    case TRAP_CODE_I_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
164
    case TRAP_CODE_I_ILLEGAL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
165
    case TRAP_CODE_BREAKPOINT:   rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
166
    case TRAP_CODE_L_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
167
    case TRAP_CODE_L_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
168
    case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break;
169
    case TRAP_CODE_S_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break;
170 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_UENV_CALL]; break;
171 14 zero_gravi
    case TRAP_CODE_MENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break;
172
    case TRAP_CODE_MSI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break;
173
    case TRAP_CODE_MTI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break;
174
    case TRAP_CODE_MEI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MEI]; break;
175
    case TRAP_CODE_FIRQ_0:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_0]; break;
176
    case TRAP_CODE_FIRQ_1:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
177
    case TRAP_CODE_FIRQ_2:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
178
    case TRAP_CODE_FIRQ_3:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
179 47 zero_gravi
    case TRAP_CODE_FIRQ_4:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_4]; break;
180
    case TRAP_CODE_FIRQ_5:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_5]; break;
181
    case TRAP_CODE_FIRQ_6:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_6]; break;
182
    case TRAP_CODE_FIRQ_7:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_7]; break;
183 48 zero_gravi
    case TRAP_CODE_FIRQ_8:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_8]; break;
184
    case TRAP_CODE_FIRQ_9:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_9]; break;
185
    case TRAP_CODE_FIRQ_10:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_10]; break;
186
    case TRAP_CODE_FIRQ_11:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_11]; break;
187
    case TRAP_CODE_FIRQ_12:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_12]; break;
188
    case TRAP_CODE_FIRQ_13:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_13]; break;
189
    case TRAP_CODE_FIRQ_14:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_14]; break;
190
    case TRAP_CODE_FIRQ_15:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_15]; break;
191 68 zero_gravi
    default:                     rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler); break;
192 14 zero_gravi
  }
193
 
194
  // execute handler
195
  void (*handler_pnt)(void);
196
  handler_pnt = (void*)rte_handler;
197
  (*handler_pnt)();
198 2 zero_gravi
}
199
 
200
 
201
/**********************************************************************//**
202
 * NEORV32 runtime environment: Debug exception handler, printing various exception/interrupt information via UART.
203 14 zero_gravi
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
204 2 zero_gravi
 **************************************************************************/
205
static void __neorv32_rte_debug_exc_handler(void) {
206
 
207 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
208
    return; // handler cannot output anything if UART0 is not implemented
209
  }
210
 
211 15 zero_gravi
  // intro
212 65 zero_gravi
  neorv32_uart0_print("<RTE> ");
213 2 zero_gravi
 
214 15 zero_gravi
  // cause
215 7 zero_gravi
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
216 66 zero_gravi
  register char tmp = (char)(trap_cause & 0xf);
217 48 zero_gravi
  if (tmp >= 10) {
218
    tmp = 'a' + (tmp - 10);
219
  }
220
  else {
221
    tmp = '0' + tmp;
222
  }
223 7 zero_gravi
  switch (trap_cause) {
224 65 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart0_print("Instruction address misaligned"); break;
225
    case TRAP_CODE_I_ACCESS:     neorv32_uart0_print("Instruction access fault"); break;
226
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart0_print("Illegal instruction"); break;
227
    case TRAP_CODE_BREAKPOINT:   neorv32_uart0_print("Breakpoint"); break;
228
    case TRAP_CODE_L_MISALIGNED: neorv32_uart0_print("Load address misaligned"); break;
229
    case TRAP_CODE_L_ACCESS:     neorv32_uart0_print("Load access fault"); break;
230
    case TRAP_CODE_S_MISALIGNED: neorv32_uart0_print("Store address misaligned"); break;
231
    case TRAP_CODE_S_ACCESS:     neorv32_uart0_print("Store access fault"); break;
232
    case TRAP_CODE_UENV_CALL:    neorv32_uart0_print("Environment call from U-mode"); break;
233
    case TRAP_CODE_MENV_CALL:    neorv32_uart0_print("Environment call from M-mode"); break;
234
    case TRAP_CODE_MSI:          neorv32_uart0_print("Machine software interrupt"); break;
235
    case TRAP_CODE_MTI:          neorv32_uart0_print("Machine timer interrupt"); break;
236
    case TRAP_CODE_MEI:          neorv32_uart0_print("Machine external interrupt"); break;
237 47 zero_gravi
    case TRAP_CODE_FIRQ_0:
238
    case TRAP_CODE_FIRQ_1:
239
    case TRAP_CODE_FIRQ_2:
240
    case TRAP_CODE_FIRQ_3:
241
    case TRAP_CODE_FIRQ_4:
242
    case TRAP_CODE_FIRQ_5:
243
    case TRAP_CODE_FIRQ_6:
244 48 zero_gravi
    case TRAP_CODE_FIRQ_7:
245
    case TRAP_CODE_FIRQ_8:
246
    case TRAP_CODE_FIRQ_9:
247
    case TRAP_CODE_FIRQ_10:
248
    case TRAP_CODE_FIRQ_11:
249
    case TRAP_CODE_FIRQ_12:
250
    case TRAP_CODE_FIRQ_13:
251
    case TRAP_CODE_FIRQ_14:
252 65 zero_gravi
    case TRAP_CODE_FIRQ_15:      neorv32_uart0_print("Fast interrupt "); neorv32_uart0_putc(tmp); break;
253
    default:                     neorv32_uart0_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
254 2 zero_gravi
  }
255
 
256 66 zero_gravi
  // check cause if bus access fault exception
257
  if ((trap_cause == TRAP_CODE_I_ACCESS) || (trap_cause == TRAP_CODE_L_ACCESS) || (trap_cause == TRAP_CODE_S_ACCESS)) {
258
    register uint32_t bus_err = NEORV32_BUSKEEPER.CTRL;
259
    if (bus_err & (1<<BUSKEEPER_ERR_FLAG)) { // exception caused by bus system?
260
      if (bus_err & (1<<BUSKEEPER_ERR_TYPE)) {
261
        neorv32_uart0_print(" [TIMEOUT_ERR]");
262
      }
263
      else {
264
        neorv32_uart0_print(" [DEVICE_ERR]");
265
      }
266
    }
267
    else { // exception was not caused by bus system -> has to be caused by PMP rule violation
268
      neorv32_uart0_print(" [PMP_ERR]");
269
    }
270
  }
271
 
272 33 zero_gravi
  // instruction address
273 65 zero_gravi
  neorv32_uart0_print(" @ PC=");
274 66 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores original mepc to mscratch
275 15 zero_gravi
 
276 33 zero_gravi
  // additional info
277 65 zero_gravi
  neorv32_uart0_print(", MTVAL=");
278 33 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
279 70 zero_gravi
  neorv32_uart0_print(" </RTE>\n");
280 6 zero_gravi
}
281
 
282
 
283
/**********************************************************************//**
284
 * NEORV32 runtime environment: Print hardware configuration information via UART
285
 **************************************************************************/
286
void neorv32_rte_print_hw_config(void) {
287
 
288 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
289
    return; // cannot output anything if UART0 is not implemented
290
  }
291
 
292 6 zero_gravi
  uint32_t tmp;
293
  int i;
294
  char c;
295
 
296 65 zero_gravi
  neorv32_uart0_printf("\n\n<<< Processor Configuration Overview >>>\n");
297 6 zero_gravi
 
298
  // CPU configuration
299 61 zero_gravi
  neorv32_uart0_printf("\n=== << CPU >> ===\n");
300 6 zero_gravi
 
301 65 zero_gravi
  // general
302
  neorv32_uart0_printf("Clock speed:       %u Hz\n", NEORV32_SYSINFO.CLK);
303
  neorv32_uart0_printf("Full HW reset:     "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
304
  neorv32_uart0_printf("On-chip debugger:  "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
305 23 zero_gravi
  // ID
306 61 zero_gravi
  neorv32_uart0_printf("Hart ID:           0x%x\n"
307
                       "Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
308 12 zero_gravi
 
309 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
310 61 zero_gravi
  neorv32_uart0_printf("Architecture ID:   0x%x", tmp);
311 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
312 61 zero_gravi
    neorv32_uart0_printf(" (NEORV32)");
313 32 zero_gravi
  }
314 23 zero_gravi
 
315 49 zero_gravi
  // hardware version
316 61 zero_gravi
  neorv32_uart0_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
317 12 zero_gravi
  neorv32_rte_print_hw_version();
318 61 zero_gravi
  neorv32_uart0_putc(')');
319 6 zero_gravi
 
320 60 zero_gravi
  // CPU architecture and endianness
321 61 zero_gravi
  neorv32_uart0_printf("\nArchitecture:      ");
322 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
323
  tmp = (tmp >> 30) & 0x03;
324
  if (tmp == 1) {
325 61 zero_gravi
    neorv32_uart0_printf("rv32-little");
326 6 zero_gravi
  }
327 40 zero_gravi
  else {
328 61 zero_gravi
    neorv32_uart0_printf("unknown");
329 40 zero_gravi
  }
330 71 zero_gravi
 
331 40 zero_gravi
  // CPU extensions
332 61 zero_gravi
  neorv32_uart0_printf("\nISA extensions:    ");
333 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
334
  for (i=0; i<26; i++) {
335
    if (tmp & (1 << i)) {
336
      c = (char)('A' + i);
337 61 zero_gravi
      neorv32_uart0_putc(c);
338
      neorv32_uart0_putc(' ');
339 6 zero_gravi
    }
340
  }
341 22 zero_gravi
 
342 63 zero_gravi
  // Z* CPU extensions
343 72 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MXISA);
344
  if (tmp & (1<<CSR_MXISA_ZICSR)) {
345 61 zero_gravi
    neorv32_uart0_printf("Zicsr ");
346 22 zero_gravi
  }
347 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZICNTR)) {
348 66 zero_gravi
    neorv32_uart0_printf("Zicntr ");
349
  }
350 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZIHPM)) {
351 66 zero_gravi
    neorv32_uart0_printf("Zihpm ");
352
  }
353 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZIFENCEI)) {
354 61 zero_gravi
    neorv32_uart0_printf("Zifencei ");
355 22 zero_gravi
  }
356 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZMMUL)) {
357 61 zero_gravi
    neorv32_uart0_printf("Zmmul ");
358
  }
359 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZFINX)) {
360 61 zero_gravi
    neorv32_uart0_printf("Zfinx ");
361 53 zero_gravi
  }
362 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZXCFU)) {
363
    neorv32_uart0_printf("Zxcfu ");
364
  }
365
  if (tmp & (1<<CSR_MXISA_ZXSCNT)) {
366 61 zero_gravi
    neorv32_uart0_printf("Zxscnt(!) ");
367 56 zero_gravi
  }
368 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_DEBUGMODE)) {
369
    neorv32_uart0_printf("DebugMode ");
370 59 zero_gravi
  }
371 71 zero_gravi
 
372
  // CPU extension options
373
  neorv32_uart0_printf("\nExtension options: ");
374 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_FASTMUL)) {
375 63 zero_gravi
    neorv32_uart0_printf("FAST_MUL ");
376
  }
377 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_FASTSHIFT)) {
378 63 zero_gravi
    neorv32_uart0_printf("FAST_SHIFT ");
379
  }
380
 
381 34 zero_gravi
  // check physical memory protection
382 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
383 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
384
  if (pmp_num_regions != 0)  {
385 73 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity, OFF/TOR modes only\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
386 34 zero_gravi
  }
387
  else {
388 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
389 34 zero_gravi
  }
390
 
391
 
392 6 zero_gravi
  // Memory configuration
393 65 zero_gravi
  neorv32_uart0_printf("\n=== << Memory System >> ===\n");
394 6 zero_gravi
 
395 73 zero_gravi
  neorv32_uart0_printf("Boot configuration:  Boot ");
396 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
397
    neorv32_uart0_printf("via Bootloader\n");
398
  }
399
  else {
400
    neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
401
  }
402
 
403 66 zero_gravi
  neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
404 56 zero_gravi
 
405
  // IMEM
406 66 zero_gravi
  neorv32_uart0_printf("Internal IMEM:       ");
407 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_IMEM)) {
408
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.IMEM_SIZE);
409 56 zero_gravi
  }
410
  else {
411 61 zero_gravi
    neorv32_uart0_printf("no\n");
412 56 zero_gravi
  }
413 6 zero_gravi
 
414 56 zero_gravi
  // DMEM
415 66 zero_gravi
  neorv32_uart0_printf("Data base address:   0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
416
  neorv32_uart0_printf("Internal DMEM:       ");
417 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
418
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
419
  }
420
  else {
421
    neorv32_uart0_printf("no\n");
422
  }
423 6 zero_gravi
 
424 56 zero_gravi
  // i-cache
425 66 zero_gravi
  neorv32_uart0_printf("Internal i-cache:    ");
426 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
427 65 zero_gravi
    neorv32_uart0_printf("yes, ");
428 41 zero_gravi
 
429 64 zero_gravi
    uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
430 41 zero_gravi
    if (ic_block_size) {
431
      ic_block_size = 1 << ic_block_size;
432
    }
433
    else {
434
      ic_block_size = 0;
435
    }
436
 
437 64 zero_gravi
    uint32_t ic_num_blocks = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
438 41 zero_gravi
    if (ic_num_blocks) {
439
      ic_num_blocks = 1 << ic_num_blocks;
440
    }
441
    else {
442
      ic_num_blocks = 0;
443
    }
444
 
445 64 zero_gravi
    uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
446 41 zero_gravi
    ic_associativity = 1 << ic_associativity;
447
 
448 65 zero_gravi
    neorv32_uart0_printf("%u bytes, %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
449 45 zero_gravi
    if (ic_associativity == 1) {
450 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
451 41 zero_gravi
    }
452 64 zero_gravi
    else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
453 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
454 41 zero_gravi
    }
455
    else {
456 61 zero_gravi
      neorv32_uart0_printf("\n");
457 41 zero_gravi
    }
458
  }
459 65 zero_gravi
  else {
460
    neorv32_uart0_printf("no\n");
461
  }
462 41 zero_gravi
 
463 66 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:  ");
464 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
465 73 zero_gravi
  neorv32_uart0_printf("Ext. bus endianness: ");
466 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
467 61 zero_gravi
    neorv32_uart0_printf("big\n");
468 40 zero_gravi
  }
469
  else {
470 61 zero_gravi
    neorv32_uart0_printf("little\n");
471 40 zero_gravi
  }
472 6 zero_gravi
 
473
  // peripherals
474 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
475 15 zero_gravi
 
476 64 zero_gravi
  tmp = NEORV32_SYSINFO.SOC;
477 65 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO));   neorv32_uart0_printf(" GPIO\n");
478
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME));  neorv32_uart0_printf(" MTIME\n");
479
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0));  neorv32_uart0_printf(" UART0\n");
480
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1));  neorv32_uart0_printf(" UART1\n");
481
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI));    neorv32_uart0_printf(" SPI\n");
482
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI));    neorv32_uart0_printf(" TWI\n");
483
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM));    neorv32_uart0_printf(" PWM\n");
484
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT));    neorv32_uart0_printf(" WDT\n");
485
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG));   neorv32_uart0_printf(" TRNG\n");
486
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS));    neorv32_uart0_printf(" CFS\n");
487
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK));  neorv32_uart0_printf(" SLINK\n");
488
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
489
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ));   neorv32_uart0_printf(" XIRQ\n");
490 67 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPTMR));  neorv32_uart0_printf(" GPTMR\n");
491 70 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIP));    neorv32_uart0_printf(" XIP\n");
492 6 zero_gravi
}
493
 
494
 
495
/**********************************************************************//**
496 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
497 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
498
 *
499 65 zero_gravi
 * @param[in] state Print 'yes' when !=0, print 'no' when 0
500 6 zero_gravi
 **************************************************************************/
501
static void __neorv32_rte_print_true_false(int state) {
502
 
503
  if (state) {
504 61 zero_gravi
    neorv32_uart0_print("yes\n");
505 6 zero_gravi
  }
506 2 zero_gravi
  else {
507 61 zero_gravi
    neorv32_uart0_print("no\n");
508 2 zero_gravi
  }
509 6 zero_gravi
}
510 2 zero_gravi
 
511
 
512 6 zero_gravi
/**********************************************************************//**
513 65 zero_gravi
 * NEORV32 runtime environment: Private function to print [x] or [ ].
514
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
515
 *
516
 * @param[in] state Print '[x]' when !=0, print '[ ]' when 0
517
 **************************************************************************/
518
static void __neorv32_rte_print_checkbox(int state) {
519
 
520
  neorv32_uart0_putc('[');
521
  if (state) {
522
    neorv32_uart0_putc('x');
523
  }
524
  else {
525
    neorv32_uart0_putc(' ');
526
  }
527
  neorv32_uart0_putc(']');
528
}
529
 
530
 
531
/**********************************************************************//**
532 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
533
 * as 8-digit hexadecimal value (with "0x" suffix).
534
 *
535
 * @param[in] num Number to print as hexadecimal.
536
 **************************************************************************/
537
void __neorv32_rte_print_hex_word(uint32_t num) {
538
 
539
  static const char hex_symbols[16] = "0123456789ABCDEF";
540
 
541 61 zero_gravi
  neorv32_uart0_print("0x");
542 33 zero_gravi
 
543
  int i;
544
  for (i=0; i<8; i++) {
545
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
546 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
547 33 zero_gravi
  }
548
}
549
 
550
 
551 47 zero_gravi
/**********************************************************************//**
552 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
553 6 zero_gravi
 **************************************************************************/
554 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
555 6 zero_gravi
 
556
  uint32_t i;
557
  char tmp, cnt;
558
 
559 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
560
    return; // cannot output anything if UART0 is not implemented
561
  }
562
 
563 6 zero_gravi
  for (i=0; i<4; i++) {
564
 
565 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
566 6 zero_gravi
 
567
    // serial division
568
    cnt = 0;
569 35 zero_gravi
    while (tmp >= 16) {
570
      tmp = tmp - 16;
571 6 zero_gravi
      cnt++;
572
    }
573
 
574
    if (cnt) {
575 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
576 6 zero_gravi
    }
577 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
578 6 zero_gravi
    if (i < 3) {
579 61 zero_gravi
      neorv32_uart0_putc('.');
580 6 zero_gravi
    }
581
  }
582 2 zero_gravi
}
583 11 zero_gravi
 
584
 
585
/**********************************************************************//**
586
 * NEORV32 runtime environment: Print project credits
587
 **************************************************************************/
588
void neorv32_rte_print_credits(void) {
589
 
590 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
591
    return; // cannot output anything if UART0 is not implemented
592
  }
593
 
594 71 zero_gravi
  neorv32_uart0_print("The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32\n"
595
                      "(c) 2022 by Stephan Nolting, BSD 3-Clause License\n\n");
596 11 zero_gravi
}
597
 
598 22 zero_gravi
 
599
/**********************************************************************//**
600 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
601 37 zero_gravi
 **************************************************************************/
602
void neorv32_rte_print_logo(void) {
603
 
604 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
605
  {
606
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
607
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
608
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
609
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
610
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
611
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
612
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
613
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
614
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
615
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
616
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
617
  };
618
 
619
  int u,v,w;
620
  uint32_t tmp;
621
 
622 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
623
    return; // cannot output anything if UART0 is not implemented
624
  }
625
 
626 40 zero_gravi
  for (u=0; u<11; u++) {
627 61 zero_gravi
    neorv32_uart0_print("\n");
628 40 zero_gravi
    for (v=0; v<4; v++) {
629
      tmp = logo_data_c[u][v];
630
      for (w=0; w<32; w++){
631 61 zero_gravi
        if (((int32_t)tmp) < 0) { // check MSB
632
          neorv32_uart0_putc('#');
633 40 zero_gravi
        }
634
        else {
635 61 zero_gravi
          neorv32_uart0_putc(' ');
636 40 zero_gravi
        }
637 47 zero_gravi
        tmp <<= 1;
638 40 zero_gravi
      }
639
    }
640
  }
641 61 zero_gravi
  neorv32_uart0_print("\n");
642 37 zero_gravi
}
643
 
644
 
645
/**********************************************************************//**
646 22 zero_gravi
 * NEORV32 runtime environment: Print project license
647
 **************************************************************************/
648
void neorv32_rte_print_license(void) {
649
 
650 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
651
    return; // cannot output anything if UART0 is not implemented
652
  }
653
 
654 65 zero_gravi
  neorv32_uart0_print(
655 22 zero_gravi
  "\n"
656
  "BSD 3-Clause License\n"
657
  "\n"
658 71 zero_gravi
  "Copyright (c) 2022, Stephan Nolting. All rights reserved.\n"
659 22 zero_gravi
  "\n"
660
  "Redistribution and use in source and binary forms, with or without modification, are\n"
661
  "permitted provided that the following conditions are met:\n"
662
  "\n"
663
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
664
  "   conditions and the following disclaimer.\n"
665
  "\n"
666
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
667
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
668
  "   provided with the distribution.\n"
669
  "\n"
670
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
671
  "   endorse or promote products derived from this software without specific prior written\n"
672
  "   permission.\n"
673
  "\n"
674
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
675
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
676
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
677
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
678
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
679
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
680
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
681
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
682
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
683
  "\n"
684
  "\n"
685
  );
686
}
687
 
688 44 zero_gravi
 
689
/**********************************************************************//**
690
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
691
 *
692
 * @return MISA content according to compiler configuration.
693
 **************************************************************************/
694
uint32_t neorv32_rte_get_compiler_isa(void) {
695
 
696
  uint32_t misa_cc = 0;
697
 
698 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
699 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_A;
700 44 zero_gravi
#endif
701
 
702 53 zero_gravi
#ifdef __riscv_b
703 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_B;
704 53 zero_gravi
#endif
705
 
706
#if defined __riscv_compressed || defined __riscv_c
707 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_C;
708 44 zero_gravi
#endif
709
 
710 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
711 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_D;
712 52 zero_gravi
#endif
713
 
714 44 zero_gravi
#ifdef __riscv_32e
715 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_E;
716 44 zero_gravi
#else
717 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_I;
718 44 zero_gravi
#endif
719
 
720 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
721 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_F;
722 52 zero_gravi
#endif
723
 
724 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
725 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_M;
726 44 zero_gravi
#endif
727
 
728
#if (__riscv_xlen == 32)
729 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_MXL_LO;
730 44 zero_gravi
#elif (__riscv_xlen == 64)
731 61 zero_gravi
  misa_cc |= 2 << CSR_MISA_MXL_LO;
732 44 zero_gravi
#else
733 61 zero_gravi
  misa_cc |= 3 << CSR_MISA_MXL_LO;
734 44 zero_gravi
#endif
735
 
736
  return misa_cc;
737
}
738
 
739
 
740
/**********************************************************************//**
741
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
742
 *
743 68 zero_gravi
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when = 0.
744 44 zero_gravi
 * @return MISA content according to compiler configuration.
745
 **************************************************************************/
746
int neorv32_rte_check_isa(int silent) {
747
 
748
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
749
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
750
 
751
  // mask hardware features that are not used by software
752
  uint32_t check = misa_hw & misa_sw;
753
 
754
  if (check == misa_sw) {
755
    return 0;
756
  }
757
  else {
758 68 zero_gravi
    if ((silent == 0) && (neorv32_uart0_available() != 0)) {
759 65 zero_gravi
      neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
760 44 zero_gravi
                          "SW_ISA = 0x%x (compiler flags)\n"
761
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
762
    }
763
    return 1;
764
  }
765
}
766
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.