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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_cpu.c] - Blame information for rev 46

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

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_cpu.c - 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.c
38
 * @author Stephan Nolting
39
 * @brief CPU Core Functions HW driver source file.
40
 **************************************************************************/
41
 
42
#include "neorv32.h"
43
#include "neorv32_cpu.h"
44
 
45
 
46 45 zero_gravi
 
47 2 zero_gravi
/**********************************************************************//**
48 45 zero_gravi
 * >Private< helper functions.
49
 **************************************************************************/
50
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index);
51
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data);
52
 
53
 
54
/**********************************************************************//**
55 2 zero_gravi
 * Enable specific CPU interrupt.
56
 *
57
 * @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too.
58
 *
59 42 zero_gravi
 * @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum.
60 12 zero_gravi
 * @return 0 if success, 1 if error (invalid irq_sel).
61 2 zero_gravi
 **************************************************************************/
62
int neorv32_cpu_irq_enable(uint8_t irq_sel) {
63
 
64 42 zero_gravi
  if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
65
      (irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
66 2 zero_gravi
    return 1;
67
  }
68
 
69
  register uint32_t mask = (uint32_t)(1 << irq_sel);
70
  asm volatile ("csrrs zero, mie, %0" : : "r" (mask));
71
  return 0;
72
}
73
 
74
 
75
/**********************************************************************//**
76
 * Disable specific CPU interrupt.
77
 *
78 42 zero_gravi
 * @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum.
79 12 zero_gravi
 * @return 0 if success, 1 if error (invalid irq_sel).
80 2 zero_gravi
 **************************************************************************/
81
int neorv32_cpu_irq_disable(uint8_t irq_sel) {
82
 
83 42 zero_gravi
  if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
84
      (irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
85 2 zero_gravi
    return 1;
86
  }
87
 
88
  register uint32_t mask = (uint32_t)(1 << irq_sel);
89
  asm volatile ("csrrc zero, mie, %0" : : "r" (mask));
90
  return 0;
91
}
92
 
93
 
94
/**********************************************************************//**
95 12 zero_gravi
 * Get cycle count from cycle[h].
96
 *
97
 * @note The cycle[h] CSR is shadowed copy of the mcycle[h] CSR.
98
 *
99
 * @return Current cycle counter (64 bit).
100
 **************************************************************************/
101
uint64_t neorv32_cpu_get_cycle(void) {
102
 
103
  union {
104
    uint64_t uint64;
105
    uint32_t uint32[sizeof(uint64_t)/2];
106
  } cycles;
107
 
108
  uint32_t tmp1, tmp2, tmp3;
109
  while(1) {
110
    tmp1 = neorv32_cpu_csr_read(CSR_CYCLEH);
111
    tmp2 = neorv32_cpu_csr_read(CSR_CYCLE);
112
    tmp3 = neorv32_cpu_csr_read(CSR_CYCLEH);
113
    if (tmp1 == tmp3) {
114
      break;
115
    }
116
  }
117
 
118
  cycles.uint32[0] = tmp2;
119
  cycles.uint32[1] = tmp3;
120
 
121
  return cycles.uint64;
122
}
123
 
124
 
125
/**********************************************************************//**
126
 * Set mcycle[h] counter.
127
 *
128
 * @param[in] value New value for mcycle[h] CSR (64-bit).
129
 **************************************************************************/
130
void neorv32_cpu_set_mcycle(uint64_t value) {
131
 
132
  union {
133
    uint64_t uint64;
134
    uint32_t uint32[sizeof(uint64_t)/2];
135
  } cycles;
136
 
137
  cycles.uint64 = value;
138
 
139
  neorv32_cpu_csr_write(CSR_MCYCLE,  0);
140
  neorv32_cpu_csr_write(CSR_MCYCLEH, cycles.uint32[1]);
141
  neorv32_cpu_csr_write(CSR_MCYCLE,  cycles.uint32[0]);
142
}
143
 
144
 
145
/**********************************************************************//**
146
 * Get retired instructions counter from instret[h].
147
 *
148
 * @note The instret[h] CSR is shadowed copy of the instret[h] CSR.
149
 *
150
 * @return Current instructions counter (64 bit).
151
 **************************************************************************/
152
uint64_t neorv32_cpu_get_instret(void) {
153
 
154
  union {
155
    uint64_t uint64;
156
    uint32_t uint32[sizeof(uint64_t)/2];
157
  } cycles;
158
 
159
  uint32_t tmp1, tmp2, tmp3;
160
  while(1) {
161
    tmp1 = neorv32_cpu_csr_read(CSR_INSTRETH);
162
    tmp2 = neorv32_cpu_csr_read(CSR_INSTRET);
163
    tmp3 = neorv32_cpu_csr_read(CSR_INSTRETH);
164
    if (tmp1 == tmp3) {
165
      break;
166
    }
167
  }
168
 
169
  cycles.uint32[0] = tmp2;
170
  cycles.uint32[1] = tmp3;
171
 
172
  return cycles.uint64;
173
}
174
 
175
 
176
/**********************************************************************//**
177
 * Set retired instructions counter minstret[h].
178
 *
179
 * @param[in] value New value for mcycle[h] CSR (64-bit).
180
 **************************************************************************/
181
void neorv32_cpu_set_minstret(uint64_t value) {
182
 
183
  union {
184
    uint64_t uint64;
185
    uint32_t uint32[sizeof(uint64_t)/2];
186
  } cycles;
187
 
188
  cycles.uint64 = value;
189
 
190
  neorv32_cpu_csr_write(CSR_MINSTRET,  0);
191
  neorv32_cpu_csr_write(CSR_MINSTRETH, cycles.uint32[1]);
192
  neorv32_cpu_csr_write(CSR_MINSTRET,  cycles.uint32[0]);
193
}
194
 
195
 
196
/**********************************************************************//**
197
 * Get current system time from time[h] CSR.
198
 *
199
 * @note This function requires the MTIME system timer to be implemented.
200
 *
201
 * @return Current system time (64 bit).
202
 **************************************************************************/
203
uint64_t neorv32_cpu_get_systime(void) {
204
 
205
  union {
206
    uint64_t uint64;
207
    uint32_t uint32[sizeof(uint64_t)/2];
208
  } cycles;
209
 
210
  uint32_t tmp1, tmp2, tmp3;
211
  while(1) {
212
    tmp1 = neorv32_cpu_csr_read(CSR_TIMEH);
213
    tmp2 = neorv32_cpu_csr_read(CSR_TIME);
214
    tmp3 = neorv32_cpu_csr_read(CSR_TIMEH);
215
    if (tmp1 == tmp3) {
216
      break;
217
    }
218
  }
219
 
220
  cycles.uint32[0] = tmp2;
221
  cycles.uint32[1] = tmp3;
222
 
223
  return cycles.uint64;
224
}
225
 
226
 
227
/**********************************************************************//**
228 39 zero_gravi
 * Simple delay function using busy wait.
229 2 zero_gravi
 *
230 39 zero_gravi
 * @warning This function requires the cycle CSR(s). Hence, the Zicsr extension is mandatory.
231
 *
232 2 zero_gravi
 * @param[in] time_ms Time in ms to wait.
233
 **************************************************************************/
234
void neorv32_cpu_delay_ms(uint32_t time_ms) {
235
 
236 39 zero_gravi
  uint64_t time_resume = neorv32_cpu_get_cycle();
237 2 zero_gravi
 
238 39 zero_gravi
  uint32_t clock = SYSINFO_CLK; // clock ticks per second
239
  clock = clock / 1000; // clock ticks per ms
240
 
241
  uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms);
242
  time_resume += wait_cycles;
243
 
244
  while(1) {
245
    if (neorv32_cpu_get_cycle() >= time_resume) {
246
      break;
247
    }
248 2 zero_gravi
  }
249
}
250
 
251 15 zero_gravi
 
252
/**********************************************************************//**
253
 * Switch from privilege mode MACHINE to privilege mode USER.
254
 *
255 39 zero_gravi
 * @warning This function requires the U extension to be implemented.
256 15 zero_gravi
 **************************************************************************/
257
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
258
 
259 35 zero_gravi
  // make sure to use NO registers in here! -> naked
260 15 zero_gravi
 
261 39 zero_gravi
  asm volatile ("csrw mepc, ra           \n\t" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here
262 35 zero_gravi
                "li ra, %[input_imm]     \n\t" // bit mask to clear the two MPP bits
263
                "csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode
264
                "mret                    \n\t" // return and switch to user mode
265 42 zero_gravi
                :  : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
266 15 zero_gravi
}
267 39 zero_gravi
 
268
 
269
/**********************************************************************//**
270
 * Atomic compare-and-swap operation (for implemeneting semaphores and mutexes).
271
 *
272
 * @warning This function requires the A (atomic) CPU extension.
273
 *
274
 * @param[in] addr Address of memory location.
275
 * @param[in] expected Expected value (for comparison).
276
 * @param[in] desired Desired value (new value).
277
 * @return Returns 0 on success, 1 on failure.
278
 **************************************************************************/
279
int __attribute__ ((noinline)) neorv32_cpu_atomic_cas(uint32_t addr, uint32_t expected, uint32_t desired) {
280
#ifdef __riscv_atomic
281
 
282
  register uint32_t addr_reg = addr;
283
  register uint32_t des_reg = desired;
284
  register uint32_t tmp_reg;
285
 
286
  // load original value + reservation (lock)
287
  asm volatile ("lr.w %[result], (%[input])" : [result] "=r" (tmp_reg) : [input] "r" (addr_reg));
288
 
289
  if (tmp_reg != expected) {
290
    asm volatile ("lw x0, 0(%[input])" : : [input] "r" (addr_reg)); // clear reservation lock
291
    return 1;
292
  }
293
 
294
  // store-conditional
295
  asm volatile ("sc.w %[result], %[input_i], (%[input_j])" : [result] "=r" (tmp_reg) : [input_i] "r" (des_reg), [input_j] "r" (addr_reg));
296
 
297
  if (tmp_reg) {
298
    return 1;
299
  }
300
 
301
  return 0;
302
#else
303 45 zero_gravi
  return 1; // A extension not implemented - function always fails
304 39 zero_gravi
#endif
305
}
306 40 zero_gravi
 
307
 
308
/**********************************************************************//**
309 42 zero_gravi
 * Physical memory protection (PMP): Get number of available regions.
310
 *
311
 * @warning This function overrides all available PMPCFG* CSRs.
312
 * @warning This function requires the PMP CPU extension.
313
 *
314
 * @return Returns number of available PMP regions.
315
 **************************************************************************/
316
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
317
 
318 45 zero_gravi
  uint32_t i = 0;
319
 
320 42 zero_gravi
  // try setting R bit in all PMPCFG CSRs
321 45 zero_gravi
  const uint32_t tmp = 0x01010101;
322
  for (i=0; i<16; i++) {
323
    __neorv32_cpu_pmp_cfg_write(i, tmp);
324
  }
325 42 zero_gravi
 
326
  // sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
327
  union {
328
    uint32_t uint32;
329
    uint8_t  uint8[sizeof(uint32_t)/sizeof(uint8_t)];
330
  } cnt;
331
 
332
  cnt.uint32 = 0;
333 45 zero_gravi
  for (i=0; i<16; i++) {
334
    cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i);
335
  }
336 42 zero_gravi
 
337
  // sum up bytes
338
  uint32_t num_regions = 0;
339
  num_regions += (uint32_t)cnt.uint8[0];
340
  num_regions += (uint32_t)cnt.uint8[1];
341
  num_regions += (uint32_t)cnt.uint8[2];
342
  num_regions += (uint32_t)cnt.uint8[3];
343
 
344
  return num_regions;
345
}
346
 
347
 
348
/**********************************************************************//**
349 40 zero_gravi
 * Physical memory protection (PMP): Get minimal region size (granularity).
350
 *
351
 * @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs.
352
 * @warning This function requires the PMP CPU extension.
353
 *
354 42 zero_gravi
 * @return Returns minimal region size in bytes.
355 40 zero_gravi
 **************************************************************************/
356
uint32_t neorv32_cpu_pmp_get_granularity(void) {
357
 
358
  // check min granulartiy
359
  uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);
360
  tmp &= 0xffffff00; // disable entry 0
361
  neorv32_cpu_csr_write(CSR_PMPCFG0, tmp);
362
  neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff);
363
  uint32_t tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0);
364
 
365
  uint32_t i;
366
 
367
  // find least-significat set bit
368
  for (i=31; i!=0; i--) {
369
    if (((tmp_a >> i) & 1) == 0) {
370
      break;
371
    }
372
  }
373
 
374
  return (uint32_t)(1 << (i+1+2));
375
}
376
 
377
 
378
/**********************************************************************//**
379
 * Physical memory protection (PMP): Configure region.
380
 *
381
 * @note Using NAPOT mode - page base address has to be naturally aligned.
382
 *
383
 * @warning This function requires the PMP CPU extension.
384 42 zero_gravi
 * @warning Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
385 40 zero_gravi
 *
386 42 zero_gravi
 * @param[in] index Region number (index, 0..PMP_NUM_REGIONS-1).
387 40 zero_gravi
 * @param[in] base Region base address (has to be naturally aligned!).
388
 * @param[in] size Region size, has to be a power of 2 (min 8 bytes or according to HW's PMP.granularity configuration).
389
 * @param[in] config Region configuration (attributes) byte (for PMPCFGx).
390
 * @return Returns 0 on success, 1 on failure.
391
 **************************************************************************/
392
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config) {
393
 
394
  if (size < 8) {
395
    return 1; // minimal region size is 8 bytes
396
  }
397
 
398
  if ((size & (size - 1)) != 0) {
399
    return 1; // region size is not a power of two
400
  }
401
 
402 45 zero_gravi
  // pmpcfg register index
403
  uint32_t pmpcfg_index = index >> 4; // 4 entries per pmpcfg csr
404
 
405 40 zero_gravi
  // setup configuration
406
  uint32_t tmp;
407
  uint32_t config_int  = ((uint32_t)config) << ((index%4)*8);
408
  uint32_t config_mask = ((uint32_t)0xFF)   << ((index%4)*8);
409
  config_mask = ~config_mask;
410
 
411
  // clear old configuration
412 45 zero_gravi
  __neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) & config_mask);
413 40 zero_gravi
 
414 45 zero_gravi
 
415 40 zero_gravi
  // set base address and region size
416
  uint32_t addr_mask = ~((size - 1) >> 2);
417
  uint32_t size_mask = (size - 1) >> 3;
418
 
419
  tmp = base & addr_mask;
420
  tmp = tmp | size_mask;
421
 
422 42 zero_gravi
  switch(index & 63) {
423
    case 0:  neorv32_cpu_csr_write(CSR_PMPADDR0,  tmp); break;
424
    case 1:  neorv32_cpu_csr_write(CSR_PMPADDR1,  tmp); break;
425
    case 2:  neorv32_cpu_csr_write(CSR_PMPADDR2,  tmp); break;
426
    case 3:  neorv32_cpu_csr_write(CSR_PMPADDR3,  tmp); break;
427
    case 4:  neorv32_cpu_csr_write(CSR_PMPADDR4,  tmp); break;
428
    case 5:  neorv32_cpu_csr_write(CSR_PMPADDR5,  tmp); break;
429
    case 6:  neorv32_cpu_csr_write(CSR_PMPADDR6,  tmp); break;
430
    case 7:  neorv32_cpu_csr_write(CSR_PMPADDR7,  tmp); break;
431
    case 8:  neorv32_cpu_csr_write(CSR_PMPADDR8,  tmp); break;
432
    case 9:  neorv32_cpu_csr_write(CSR_PMPADDR9,  tmp); break;
433
    case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, tmp); break;
434
    case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, tmp); break;
435
    case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, tmp); break;
436
    case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, tmp); break;
437
    case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, tmp); break;
438
    case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, tmp); break;
439
    case 16: neorv32_cpu_csr_write(CSR_PMPADDR16, tmp); break;
440
    case 17: neorv32_cpu_csr_write(CSR_PMPADDR17, tmp); break;
441
    case 18: neorv32_cpu_csr_write(CSR_PMPADDR18, tmp); break;
442
    case 19: neorv32_cpu_csr_write(CSR_PMPADDR19, tmp); break;
443
    case 20: neorv32_cpu_csr_write(CSR_PMPADDR20, tmp); break;
444
    case 21: neorv32_cpu_csr_write(CSR_PMPADDR21, tmp); break;
445
    case 22: neorv32_cpu_csr_write(CSR_PMPADDR22, tmp); break;
446
    case 23: neorv32_cpu_csr_write(CSR_PMPADDR23, tmp); break;
447
    case 24: neorv32_cpu_csr_write(CSR_PMPADDR24, tmp); break;
448
    case 25: neorv32_cpu_csr_write(CSR_PMPADDR25, tmp); break;
449
    case 26: neorv32_cpu_csr_write(CSR_PMPADDR26, tmp); break;
450
    case 27: neorv32_cpu_csr_write(CSR_PMPADDR27, tmp); break;
451
    case 28: neorv32_cpu_csr_write(CSR_PMPADDR28, tmp); break;
452
    case 29: neorv32_cpu_csr_write(CSR_PMPADDR29, tmp); break;
453
    case 30: neorv32_cpu_csr_write(CSR_PMPADDR30, tmp); break;
454
    case 31: neorv32_cpu_csr_write(CSR_PMPADDR31, tmp); break;
455
    case 32: neorv32_cpu_csr_write(CSR_PMPADDR32, tmp); break;
456
    case 33: neorv32_cpu_csr_write(CSR_PMPADDR33, tmp); break;
457
    case 34: neorv32_cpu_csr_write(CSR_PMPADDR34, tmp); break;
458
    case 35: neorv32_cpu_csr_write(CSR_PMPADDR35, tmp); break;
459
    case 36: neorv32_cpu_csr_write(CSR_PMPADDR36, tmp); break;
460
    case 37: neorv32_cpu_csr_write(CSR_PMPADDR37, tmp); break;
461
    case 38: neorv32_cpu_csr_write(CSR_PMPADDR38, tmp); break;
462
    case 39: neorv32_cpu_csr_write(CSR_PMPADDR39, tmp); break;
463
    case 40: neorv32_cpu_csr_write(CSR_PMPADDR40, tmp); break;
464
    case 41: neorv32_cpu_csr_write(CSR_PMPADDR41, tmp); break;
465
    case 42: neorv32_cpu_csr_write(CSR_PMPADDR42, tmp); break;
466
    case 43: neorv32_cpu_csr_write(CSR_PMPADDR43, tmp); break;
467
    case 44: neorv32_cpu_csr_write(CSR_PMPADDR44, tmp); break;
468
    case 45: neorv32_cpu_csr_write(CSR_PMPADDR45, tmp); break;
469
    case 46: neorv32_cpu_csr_write(CSR_PMPADDR46, tmp); break;
470
    case 47: neorv32_cpu_csr_write(CSR_PMPADDR47, tmp); break;
471
    case 48: neorv32_cpu_csr_write(CSR_PMPADDR48, tmp); break;
472
    case 49: neorv32_cpu_csr_write(CSR_PMPADDR49, tmp); break;
473
    case 50: neorv32_cpu_csr_write(CSR_PMPADDR50, tmp); break;
474
    case 51: neorv32_cpu_csr_write(CSR_PMPADDR51, tmp); break;
475
    case 52: neorv32_cpu_csr_write(CSR_PMPADDR52, tmp); break;
476
    case 53: neorv32_cpu_csr_write(CSR_PMPADDR53, tmp); break;
477
    case 54: neorv32_cpu_csr_write(CSR_PMPADDR54, tmp); break;
478
    case 55: neorv32_cpu_csr_write(CSR_PMPADDR55, tmp); break;
479
    case 56: neorv32_cpu_csr_write(CSR_PMPADDR56, tmp); break;
480
    case 57: neorv32_cpu_csr_write(CSR_PMPADDR57, tmp); break;
481
    case 58: neorv32_cpu_csr_write(CSR_PMPADDR58, tmp); break;
482
    case 59: neorv32_cpu_csr_write(CSR_PMPADDR59, tmp); break;
483
    case 60: neorv32_cpu_csr_write(CSR_PMPADDR60, tmp); break;
484
    case 61: neorv32_cpu_csr_write(CSR_PMPADDR61, tmp); break;
485
    case 62: neorv32_cpu_csr_write(CSR_PMPADDR62, tmp); break;
486
    case 63: neorv32_cpu_csr_write(CSR_PMPADDR63, tmp); break;
487 40 zero_gravi
    default: break;
488
  }
489
 
490 42 zero_gravi
  // wait for HW to compute PMP-internal stuff (address masks)
491 40 zero_gravi
  for (tmp=0; tmp<16; tmp++) {
492
    asm volatile ("nop");
493
  }
494
 
495
  // set new configuration
496 45 zero_gravi
  __neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) | config_int);
497
 
498
  return 0;
499
}
500
 
501
 
502
/**********************************************************************//**
503
 * Internal helper function: Read PMP configuration register 0..15
504
 *
505
 * @warning This function requires the PMP CPU extension.
506
 *
507
 * @param[in] index PMP CFG configuration register ID (0..15).
508
 * @return PMP CFG read data.
509
 **************************************************************************/
510
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index) {
511
 
512
  uint32_t tmp = 0;
513 42 zero_gravi
  switch(index & 15) {
514 45 zero_gravi
    case 0:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);  break;
515
    case 1:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG1);  break;
516
    case 2:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG2);  break;
517
    case 3:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG3);  break;
518
    case 4:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG4);  break;
519
    case 5:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG5);  break;
520
    case 6:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG6);  break;
521
    case 7:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG7);  break;
522
    case 8:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG8);  break;
523
    case 9:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG9);  break;
524
    case 10: tmp = neorv32_cpu_csr_read(CSR_PMPCFG10); break;
525
    case 11: tmp = neorv32_cpu_csr_read(CSR_PMPCFG11); break;
526
    case 12: tmp = neorv32_cpu_csr_read(CSR_PMPCFG12); break;
527
    case 13: tmp = neorv32_cpu_csr_read(CSR_PMPCFG13); break;
528
    case 14: tmp = neorv32_cpu_csr_read(CSR_PMPCFG14); break;
529
    case 15: tmp = neorv32_cpu_csr_read(CSR_PMPCFG15); break;
530 42 zero_gravi
    default: break;
531 40 zero_gravi
  }
532
 
533 45 zero_gravi
  return tmp;
534 40 zero_gravi
}
535 42 zero_gravi
 
536
 
537
/**********************************************************************//**
538 45 zero_gravi
 * Internal helper function: Write PMP configuration register 0..15
539
 *
540
 * @warning This function requires the PMP CPU extension.
541
 *
542
 * @param[in] index PMP CFG configuration register ID (0..15).
543
 * @param[in] data PMP CFG write data.
544
 **************************************************************************/
545
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data) {
546
 
547
  switch(index & 15) {
548
    case 0:  neorv32_cpu_csr_write(CSR_PMPCFG0,  data); break;
549
    case 1:  neorv32_cpu_csr_write(CSR_PMPCFG1,  data); break;
550
    case 2:  neorv32_cpu_csr_write(CSR_PMPCFG2,  data); break;
551
    case 3:  neorv32_cpu_csr_write(CSR_PMPCFG3,  data); break;
552
    case 4:  neorv32_cpu_csr_write(CSR_PMPCFG4,  data); break;
553
    case 5:  neorv32_cpu_csr_write(CSR_PMPCFG5,  data); break;
554
    case 6:  neorv32_cpu_csr_write(CSR_PMPCFG6,  data); break;
555
    case 7:  neorv32_cpu_csr_write(CSR_PMPCFG7,  data); break;
556
    case 8:  neorv32_cpu_csr_write(CSR_PMPCFG8,  data); break;
557
    case 9:  neorv32_cpu_csr_write(CSR_PMPCFG9,  data); break;
558
    case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, data); break;
559
    case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, data); break;
560
    case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, data); break;
561
    case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, data); break;
562
    case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, data); break;
563
    case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, data); break;
564
    default: break;
565
  }
566
}
567
 
568
 
569
/**********************************************************************//**
570 42 zero_gravi
 * Hardware performance monitors (HPM): Get number of available HPM counters.
571
 *
572
 * @warning This function overrides all available mhpmcounter* CSRs.
573
 *
574
 * @return Returns number of available HPM counters (..29).
575
 **************************************************************************/
576
uint32_t neorv32_cpu_hpm_get_counters(void) {
577
 
578
  // try setting all mhpmcounter* CSRs to 1
579
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  1);
580
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER4,  1);
581
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER5,  1);
582
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER6,  1);
583
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER7,  1);
584
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER8,  1);
585
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER9,  1);
586
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER10, 1);
587
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER11, 1);
588
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER12, 1);
589
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER13, 1);
590
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER14, 1);
591
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER15, 1);
592
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER16, 1);
593
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER17, 1);
594
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER18, 1);
595
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER19, 1);
596
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER20, 1);
597
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER21, 1);
598
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER22, 1);
599
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER23, 1);
600
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER24, 1);
601
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER25, 1);
602
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER26, 1);
603
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER27, 1);
604
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1);
605
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1);
606
 
607
  // sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
608
  uint32_t num_hpm_cnts = 0;
609
 
610
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
611
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER4);
612
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER5);
613
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER6);
614
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER7);
615
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER8);
616
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER9);
617
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER10);
618
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER11);
619
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER12);
620
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER13);
621
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER14);
622
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER15);
623
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER16);
624
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER17);
625
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER18);
626
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER19);
627
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER20);
628
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER21);
629
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER22);
630
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER23);
631
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER24);
632
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER25);
633
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER26);
634
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER27);
635
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER28);
636
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER29);
637
 
638
  return num_hpm_cnts;
639
}

powered by: WebSVN 2.1.0

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