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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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