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

Subversion Repositories neorv32

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

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 42 zero_gravi
// # Copyright (c) 2021, 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 56 zero_gravi
void neorv32_cpu_delay_ms(int16_t time_ms);
54 15 zero_gravi
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void);
55 42 zero_gravi
uint32_t neorv32_cpu_pmp_get_num_regions(void);
56 40 zero_gravi
uint32_t neorv32_cpu_pmp_get_granularity(void);
57
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config);
58 42 zero_gravi
uint32_t neorv32_cpu_hpm_get_counters(void);
59 56 zero_gravi
uint32_t neorv32_cpu_hpm_get_size(void);
60 55 zero_gravi
int neorv32_check_zextension(uint32_t);
61 2 zero_gravi
 
62
 
63
/**********************************************************************//**
64 56 zero_gravi
 * Store unsigned word to address space.
65
 *
66
 * @note An unaligned access address will raise an alignment exception.
67
 *
68
 * @param[in] addr Address (32-bit).
69
 * @param[in] wdata Data word (32-bit) to store.
70 57 zero_gravi
 * @return Operation status (32-bit).
71 56 zero_gravi
 **************************************************************************/
72 57 zero_gravi
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_store_conditional(uint32_t addr, uint32_t wdata) {
73
 
74
#if defined __riscv_atomic || defined __riscv_a
75
  register uint32_t reg_addr = addr;
76
  register uint32_t reg_data = wdata;
77
  register uint32_t reg_status;
78
 
79
  asm volatile ("sc.w %[status], %[da], (%[ad])" : [status] "=r" (reg_status) : [da] "r" (reg_data), [ad] "r" (reg_addr));
80
 
81
  return reg_status;
82
#else
83
  return 1; // always failing
84
#endif
85
}
86
 
87
 
88
/**********************************************************************//**
89
 * Conditional store unsigned word to address space if atomic access reservation is valid.
90
 *
91
 * @note An unaligned access address will raise an alignment exception.
92
 *
93
 * @param[in] addr Address (32-bit).
94
 * @param[in] wdata Data word (32-bit) to store.
95
 **************************************************************************/
96 56 zero_gravi
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_word(uint32_t addr, uint32_t wdata) {
97
 
98
  register uint32_t reg_addr = addr;
99
  register uint32_t reg_data = wdata;
100
 
101
  asm volatile ("sw %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
102
}
103
 
104
 
105
/**********************************************************************//**
106
 * Store unsigned half-word to address space.
107
 *
108
 * @note An unaligned access address will raise an alignment exception.
109
 *
110
 * @param[in] addr Address (32-bit).
111
 * @param[in] wdata Data half-word (16-bit) to store.
112
 **************************************************************************/
113
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_half(uint32_t addr, uint16_t wdata) {
114
 
115
  register uint32_t reg_addr = addr;
116
  register uint32_t reg_data = (uint32_t)wdata;
117
 
118
  asm volatile ("sh %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
119
}
120
 
121
 
122
/**********************************************************************//**
123
 * Store unsigned byte to address space.
124
 *
125
 * @param[in] addr Address (32-bit).
126
 * @param[in] wdata Data byte (8-bit) to store.
127
 **************************************************************************/
128
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_byte(uint32_t addr, uint8_t wdata) {
129
 
130
  register uint32_t reg_addr = addr;
131
  register uint32_t reg_data = (uint32_t)wdata;
132
 
133
  asm volatile ("sb %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr));
134
}
135
 
136
 
137
/**********************************************************************//**
138 57 zero_gravi
 * Load unsigned word from address space and make reservation for atomic access.
139
 *
140
 * @note An unaligned access address will raise an alignment exception.
141
 *
142
 * @param[in] addr Address (32-bit).
143
 * @return Read data word (32-bit).
144
 **************************************************************************/
145
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_load_reservate_word(uint32_t addr) {
146
 
147
  register uint32_t reg_addr = addr;
148
  register uint32_t reg_data;
149
 
150
#if defined __riscv_atomic || defined __riscv_a
151
  asm volatile ("lr.w %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
152
#else
153
  asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
154
#endif
155
 
156
  return (uint32_t)reg_data;
157
}
158
 
159
 
160
 
161
/**********************************************************************//**
162 56 zero_gravi
 * Load unsigned word from address space.
163
 *
164
 * @note An unaligned access address will raise an alignment exception.
165
 *
166
 * @param[in] addr Address (32-bit).
167
 * @return Read data word (32-bit).
168
 **************************************************************************/
169
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_word(uint32_t addr) {
170
 
171
  register uint32_t reg_addr = addr;
172
  register uint32_t reg_data;
173
 
174
  asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
175
 
176
  return (uint32_t)reg_data;
177
}
178
 
179
 
180
/**********************************************************************//**
181
 * Load unsigned half-word from address space.
182
 *
183
 * @note An unaligned access address will raise an alignment exception.
184
 *
185
 * @param[in] addr Address (32-bit).
186
 * @return Read data half-word (16-bit).
187
 **************************************************************************/
188
inline uint16_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_half(uint32_t addr) {
189
 
190
  register uint32_t reg_addr = addr;
191
  register uint32_t reg_data;
192
 
193
  asm volatile ("lhu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
194
 
195
  return (uint16_t)reg_data;
196
}
197
 
198
 
199
/**********************************************************************//**
200
 * Load unsigned byte from address space.
201
 *
202
 * @param[in] addr Address (32-bit).
203
 * @return Read data byte (8-bit).
204
 **************************************************************************/
205
inline uint8_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_byte(uint32_t addr) {
206
 
207
  register uint32_t reg_addr = addr;
208
  register uint32_t reg_data;
209
 
210
  asm volatile ("lbu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
211
 
212
  return (uint8_t)reg_data;
213
}
214
 
215
 
216
/**********************************************************************//**
217 2 zero_gravi
 * Read data from CPU configuration and status register (CSR).
218
 *
219 42 zero_gravi
 * @param[in] csr_id ID of CSR to read. See #NEORV32_CSR_enum.
220 2 zero_gravi
 * @return Read data (uint32_t).
221
 **************************************************************************/
222
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_csr_read(const int csr_id) {
223
 
224
  register uint32_t csr_data;
225
 
226 6 zero_gravi
  asm volatile ("csrr %[result], %[input_i]" : [result] "=r" (csr_data) : [input_i] "i" (csr_id));
227 2 zero_gravi
 
228
  return csr_data;
229
}
230
 
231
 
232
/**********************************************************************//**
233
 * Write data to CPU configuration and status register (CSR).
234
 *
235 42 zero_gravi
 * @param[in] csr_id ID of CSR to write. See #NEORV32_CSR_enum.
236 2 zero_gravi
 * @param[in] data Data to write (uint32_t).
237
 **************************************************************************/
238
inline void __attribute__ ((always_inline)) neorv32_cpu_csr_write(const int csr_id, uint32_t data) {
239
 
240
  register uint32_t csr_data = data;
241
 
242 6 zero_gravi
  asm volatile ("csrw %[input_i], %[input_j]" :  : [input_i] "i" (csr_id), [input_j] "r" (csr_data));
243 2 zero_gravi
}
244
 
245 9 zero_gravi
 
246
/**********************************************************************//**
247
 * Put CPU into "sleep" mode.
248
 *
249
 * @note This function executes the WFI insstruction.
250
 * The WFI (wait for interrupt) instruction will make the CPU stall until
251
 * an interupt request is detected. Interrupts have to be globally enabled
252 56 zero_gravi
 * and at least one external source must be enabled (like the MTI machine
253
 * timer interrupt) to allow the CPU to wake up again. If 'Zicsr' CPU extension is disabled,
254 9 zero_gravi
 * this will permanently stall the CPU.
255
 **************************************************************************/
256
inline void __attribute__ ((always_inline)) neorv32_cpu_sleep(void) {
257
 
258
  asm volatile ("wfi");
259
}
260
 
261
 
262
/**********************************************************************//**
263
 * Enable global CPU interrupts (via MIE flag in mstatus CSR).
264
 **************************************************************************/
265
inline void __attribute__ ((always_inline)) neorv32_cpu_eint(void) {
266
 
267 42 zero_gravi
  asm volatile ("csrrsi zero, mstatus, %0" : : "i" (1 << CSR_MSTATUS_MIE));
268 40 zero_gravi
  asm volatile ("nop");
269
  asm volatile ("nop");
270 9 zero_gravi
}
271
 
272
 
273
/**********************************************************************//**
274
 * Disable global CPU interrupts (via MIE flag in mstatus CSR).
275
 **************************************************************************/
276
inline void __attribute__ ((always_inline)) neorv32_cpu_dint(void) {
277
 
278 42 zero_gravi
  asm volatile ("csrrci zero, mstatus, %0" : : "i" (1 << CSR_MSTATUS_MIE));
279 40 zero_gravi
  asm volatile ("nop");
280
  asm volatile ("nop");
281 9 zero_gravi
}
282
 
283
 
284
/**********************************************************************//**
285
 * Trigger breakpoint exception (via EBREAK instruction).
286
 **************************************************************************/
287
inline void __attribute__ ((always_inline)) neorv32_cpu_breakpoint(void) {
288
 
289
  asm volatile ("ebreak");
290
}
291
 
292
 
293
/**********************************************************************//**
294
 * Trigger "environment call" exception (via ECALL instruction).
295
 **************************************************************************/
296
inline void __attribute__ ((always_inline)) neorv32_cpu_env_call(void) {
297
 
298
  asm volatile ("ecall");
299
}
300
 
301
 
302 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.