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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [include/] [neorv32_cpu.h] - Blame information for rev 73

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_cpu.h - CPU Core Functions HW Driver >>                                   #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 73 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_cpu.h
38
 * @author Stephan Nolting
39
 * @brief CPU Core Functions HW driver header file.
40
 **************************************************************************/
41
 
42
#ifndef neorv32_cpu_h
43
#define neorv32_cpu_h
44
 
45
// prototypes
46
int neorv32_cpu_irq_enable(uint8_t irq_sel);
47
int neorv32_cpu_irq_disable(uint8_t irq_sel);
48 12 zero_gravi
uint64_t neorv32_cpu_get_cycle(void);
49
void neorv32_cpu_set_mcycle(uint64_t value);
50
uint64_t neorv32_cpu_get_instret(void);
51
void neorv32_cpu_set_minstret(uint64_t value);
52
uint64_t neorv32_cpu_get_systime(void);
53 64 zero_gravi
void neorv32_cpu_delay_ms(uint32_t time_ms);
54 42 zero_gravi
uint32_t neorv32_cpu_pmp_get_num_regions(void);
55 40 zero_gravi
uint32_t neorv32_cpu_pmp_get_granularity(void);
56 73 zero_gravi
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint8_t config);
57 42 zero_gravi
uint32_t neorv32_cpu_hpm_get_counters(void);
58 56 zero_gravi
uint32_t neorv32_cpu_hpm_get_size(void);
59 2 zero_gravi
 
60
 
61
/**********************************************************************//**
62 61 zero_gravi
 * Prototype for "after-main handler". This function is called if main() returns.
63
 *
64
 * @param[in] return_code Return value of main() function.
65
 **************************************************************************/
66 73 zero_gravi
extern void __attribute__ ((weak)) __neorv32_crt0_after_main(int32_t return_code);
67 61 zero_gravi
 
68
 
69
/**********************************************************************//**
70 65 zero_gravi
 * Store unsigned word to address space if atomic access reservation is still valid.
71 56 zero_gravi
 *
72
 * @note An unaligned access address will raise an alignment exception.
73
 *
74
 * @param[in] addr Address (32-bit).
75
 * @param[in] wdata Data word (32-bit) to store.
76 65 zero_gravi
 * @return Operation status (32-bit, zero if success).
77 56 zero_gravi
 **************************************************************************/
78 57 zero_gravi
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_store_conditional(uint32_t addr, uint32_t wdata) {
79
 
80
#if defined __riscv_atomic || defined __riscv_a
81
  register uint32_t reg_addr = addr;
82
  register uint32_t reg_data = wdata;
83
  register uint32_t reg_status;
84
 
85
  asm volatile ("sc.w %[status], %[da], (%[ad])" : [status] "=r" (reg_status) : [da] "r" (reg_data), [ad] "r" (reg_addr));
86
 
87
  return reg_status;
88
#else
89
  return 1; // always failing
90
#endif
91
}
92
 
93
 
94
/**********************************************************************//**
95 65 zero_gravi
 * Conditional store unsigned word to address space.
96 57 zero_gravi
 *
97
 * @note An unaligned access address will raise an alignment exception.
98
 *
99
 * @param[in] addr Address (32-bit).
100
 * @param[in] wdata Data word (32-bit) to store.
101
 **************************************************************************/
102 56 zero_gravi
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_word(uint32_t addr, uint32_t wdata) {
103
 
104
  register uint32_t reg_addr = addr;
105
  register uint32_t reg_data = wdata;
106
 
107
  asm volatile ("sw %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
108
}
109
 
110
 
111
/**********************************************************************//**
112
 * Store unsigned half-word to address space.
113
 *
114
 * @note An unaligned access address will raise an alignment exception.
115
 *
116
 * @param[in] addr Address (32-bit).
117
 * @param[in] wdata Data half-word (16-bit) to store.
118
 **************************************************************************/
119
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_half(uint32_t addr, uint16_t wdata) {
120
 
121
  register uint32_t reg_addr = addr;
122
  register uint32_t reg_data = (uint32_t)wdata;
123
 
124
  asm volatile ("sh %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
125
}
126
 
127
 
128
/**********************************************************************//**
129
 * Store unsigned byte to address space.
130
 *
131
 * @param[in] addr Address (32-bit).
132
 * @param[in] wdata Data byte (8-bit) to store.
133
 **************************************************************************/
134
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_byte(uint32_t addr, uint8_t wdata) {
135
 
136
  register uint32_t reg_addr = addr;
137
  register uint32_t reg_data = (uint32_t)wdata;
138
 
139
  asm volatile ("sb %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
140
}
141
 
142
 
143
/**********************************************************************//**
144 57 zero_gravi
 * Load unsigned word from address space and make reservation for atomic access.
145
 *
146
 * @note An unaligned access address will raise an alignment exception.
147
 *
148
 * @param[in] addr Address (32-bit).
149
 * @return Read data word (32-bit).
150
 **************************************************************************/
151
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_load_reservate_word(uint32_t addr) {
152
 
153
  register uint32_t reg_addr = addr;
154
  register uint32_t reg_data;
155
 
156
#if defined __riscv_atomic || defined __riscv_a
157
  asm volatile ("lr.w %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
158
#else
159
  asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
160
#endif
161
 
162 73 zero_gravi
  return reg_data;
163 57 zero_gravi
}
164
 
165
 
166
/**********************************************************************//**
167 56 zero_gravi
 * Load unsigned word from address space.
168
 *
169
 * @note An unaligned access address will raise an alignment exception.
170
 *
171
 * @param[in] addr Address (32-bit).
172
 * @return Read data word (32-bit).
173
 **************************************************************************/
174
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_word(uint32_t addr) {
175
 
176
  register uint32_t reg_addr = addr;
177
  register uint32_t reg_data;
178
 
179
  asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
180
 
181 73 zero_gravi
  return reg_data;
182 56 zero_gravi
}
183
 
184
 
185
/**********************************************************************//**
186
 * Load unsigned half-word from address space.
187
 *
188
 * @note An unaligned access address will raise an alignment exception.
189
 *
190
 * @param[in] addr Address (32-bit).
191
 * @return Read data half-word (16-bit).
192
 **************************************************************************/
193
inline uint16_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_half(uint32_t addr) {
194
 
195
  register uint32_t reg_addr = addr;
196 73 zero_gravi
  register uint16_t reg_data;
197 56 zero_gravi
 
198
  asm volatile ("lhu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
199
 
200 73 zero_gravi
  return reg_data;
201 56 zero_gravi
}
202
 
203
 
204
/**********************************************************************//**
205 73 zero_gravi
 * Load signed half-word from address space.
206
 *
207
 * @note An unaligned access address will raise an alignment exception.
208
 *
209
 * @param[in] addr Address (32-bit).
210
 * @return Read data half-word (16-bit).
211
 **************************************************************************/
212
inline int16_t __attribute__ ((always_inline)) neorv32_cpu_load_signed_half(uint32_t addr) {
213
 
214
  register uint32_t reg_addr = addr;
215
  register int16_t reg_data;
216
 
217
  asm volatile ("lh %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
218
 
219
  return reg_data;
220
}
221
 
222
 
223
/**********************************************************************//**
224 56 zero_gravi
 * Load unsigned byte from address space.
225
 *
226
 * @param[in] addr Address (32-bit).
227
 * @return Read data byte (8-bit).
228
 **************************************************************************/
229
inline uint8_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_byte(uint32_t addr) {
230
 
231
  register uint32_t reg_addr = addr;
232 73 zero_gravi
  register uint8_t reg_data;
233 56 zero_gravi
 
234
  asm volatile ("lbu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
235
 
236 73 zero_gravi
  return reg_data;
237 56 zero_gravi
}
238
 
239
 
240
/**********************************************************************//**
241 73 zero_gravi
 * Load signed byte from address space.
242
 *
243
 * @param[in] addr Address (32-bit).
244
 * @return Read data byte (8-bit).
245
 **************************************************************************/
246
inline int8_t __attribute__ ((always_inline)) neorv32_cpu_load_signed_byte(uint32_t addr) {
247
 
248
  register uint32_t reg_addr = addr;
249
  register int8_t reg_data;
250
 
251
  asm volatile ("lb %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
252
 
253
  return reg_data;
254
}
255
 
256
 
257
/**********************************************************************//**
258 2 zero_gravi
 * Read data from CPU configuration and status register (CSR).
259
 *
260 42 zero_gravi
 * @param[in] csr_id ID of CSR to read. See #NEORV32_CSR_enum.
261 2 zero_gravi
 * @return Read data (uint32_t).
262
 **************************************************************************/
263
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_csr_read(const int csr_id) {
264
 
265
  register uint32_t csr_data;
266
 
267 6 zero_gravi
  asm volatile ("csrr %[result], %[input_i]" : [result] "=r" (csr_data) : [input_i] "i" (csr_id));
268 2 zero_gravi
 
269
  return csr_data;
270
}
271
 
272
 
273
/**********************************************************************//**
274
 * Write data to CPU configuration and status register (CSR).
275
 *
276 42 zero_gravi
 * @param[in] csr_id ID of CSR to write. See #NEORV32_CSR_enum.
277 2 zero_gravi
 * @param[in] data Data to write (uint32_t).
278
 **************************************************************************/
279
inline void __attribute__ ((always_inline)) neorv32_cpu_csr_write(const int csr_id, uint32_t data) {
280
 
281
  register uint32_t csr_data = data;
282
 
283 6 zero_gravi
  asm volatile ("csrw %[input_i], %[input_j]" :  : [input_i] "i" (csr_id), [input_j] "r" (csr_data));
284 2 zero_gravi
}
285
 
286 9 zero_gravi
 
287
/**********************************************************************//**
288
 * Put CPU into "sleep" mode.
289
 *
290 65 zero_gravi
 * @note This function executes the WFI instruction.
291 9 zero_gravi
 * The WFI (wait for interrupt) instruction will make the CPU stall until
292 65 zero_gravi
 * an interrupt request is detected. Interrupts have to be globally enabled
293 56 zero_gravi
 * and at least one external source must be enabled (like the MTI machine
294
 * timer interrupt) to allow the CPU to wake up again. If 'Zicsr' CPU extension is disabled,
295 9 zero_gravi
 * this will permanently stall the CPU.
296
 **************************************************************************/
297
inline void __attribute__ ((always_inline)) neorv32_cpu_sleep(void) {
298
 
299
  asm volatile ("wfi");
300
}
301
 
302
 
303
/**********************************************************************//**
304
 * Enable global CPU interrupts (via MIE flag in mstatus CSR).
305
 **************************************************************************/
306
inline void __attribute__ ((always_inline)) neorv32_cpu_eint(void) {
307
 
308 42 zero_gravi
  asm volatile ("csrrsi zero, mstatus, %0" : : "i" (1 << CSR_MSTATUS_MIE));
309 9 zero_gravi
}
310
 
311
 
312
/**********************************************************************//**
313
 * Disable global CPU interrupts (via MIE flag in mstatus CSR).
314
 **************************************************************************/
315
inline void __attribute__ ((always_inline)) neorv32_cpu_dint(void) {
316
 
317 42 zero_gravi
  asm volatile ("csrrci zero, mstatus, %0" : : "i" (1 << CSR_MSTATUS_MIE));
318 9 zero_gravi
}
319
 
320
 
321
/**********************************************************************//**
322
 * Trigger breakpoint exception (via EBREAK instruction).
323
 **************************************************************************/
324
inline void __attribute__ ((always_inline)) neorv32_cpu_breakpoint(void) {
325
 
326
  asm volatile ("ebreak");
327
}
328
 
329
 
330
/**********************************************************************//**
331
 * Trigger "environment call" exception (via ECALL instruction).
332
 **************************************************************************/
333
inline void __attribute__ ((always_inline)) neorv32_cpu_env_call(void) {
334
 
335
  asm volatile ("ecall");
336
}
337
 
338
 
339 2 zero_gravi
#endif // neorv32_cpu_h

powered by: WebSVN 2.1.0

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