|
| 1 | +## Custom Features (non RISC-V standard) |
| 2 | + |
| 3 | +### Timer |
| 4 | + |
| 5 | +The timer supported in bi-RISC-V is a 32-bit cycle counter with the option to generate timer interrupts on match. |
| 6 | + |
| 7 | +The RISC-V privileged spec refers to memory mapped **mtime** and **mtimecmp** registers. |
| 8 | +In bi-RISC-V these are mapped to CSR registers for fast access and low external dependence. |
| 9 | + |
| 10 | +**mtime** is mapped to CSR **mcycle** and **rdtime** and is limited to 32-bits (continuously counting, wrapping). |
| 11 | +**mtimecmp** is mapped to a custom CSR address and is limited to 32-bits and will generate an interrupt on matching **mtime** (interrupt routed to **MSTATUS.MTIP**). |
| 12 | + |
| 13 | +``` |
| 14 | +#define csr_read(reg) ({ uint32_t __tmp; \ |
| 15 | + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ |
| 16 | + __tmp; }) |
| 17 | +
|
| 18 | +#define csr_write(reg, val) ({ \ |
| 19 | + asm volatile ("csrw " #reg ", %0" :: "rK"(val)); }) |
| 20 | +
|
| 21 | +void timer_set_mtimecmp(uint32_t next) |
| 22 | +{ |
| 23 | + csr_write(0x7c0, next); |
| 24 | +} |
| 25 | +
|
| 26 | +uint32_t timer_get_mtime(void) |
| 27 | +{ |
| 28 | + return csr_read(0xc00); // or 0xc01 |
| 29 | +} |
| 30 | +void timer_set_mtime(uint32_t value) |
| 31 | +{ |
| 32 | + csr_write(0xc01, value); |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +### Instruction Cache Flush |
| 37 | + |
| 38 | +Flushing the instruction cache is achieved using **fence.i** which is in-keeping with the behaviour specified in the *Zifence* section of the RISC-V ISA specification; |
| 39 | + |
| 40 | +``` |
| 41 | +void icache_flush(void) |
| 42 | +{ |
| 43 | + asm volatile ("fence.i"); |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +### Data Cache Control |
| 48 | + |
| 49 | +Cacheable regions of memory are specified at the core build time using the following parameters; |
| 50 | + |
| 51 | +``` |
| 52 | + ,.MEM_CACHE_ADDR_MIN(32'h80000000) |
| 53 | + ,.MEM_CACHE_ADDR_MAX(32'h8fffffff) |
| 54 | +``` |
| 55 | + |
| 56 | +The data cache also has the following dynamic controls; |
| 57 | +* Flush: Writeback all dirty lines, mark all lines as invalid (global flush). |
| 58 | +* Writeback: Writeback a specific line (if dirty), leave line as valid in the cache (if it was present). |
| 59 | +* Invalidate: Invalidate a specific line without writing back if dirty, mark line as invalid in the cache (if it was present). |
| 60 | + |
| 61 | +These controls are mapped to **pmpcfg0**, **pmpcfg1** and **pmpcfg2** CSRs currently; |
| 62 | + |
| 63 | +``` |
| 64 | +void dcache_flush(void) |
| 65 | +{ |
| 66 | + asm volatile ("csrw pmpcfg0, x0"); // 0x3a0 |
| 67 | +} |
| 68 | +void dcache_writeback(uint32_t addr) |
| 69 | +{ |
| 70 | + asm volatile ("csrw pmpcfg1, %0": : "r" (addr)); // 0x3a1 |
| 71 | +} |
| 72 | +void dcache_invalidate(uint32_t addr) |
| 73 | +{ |
| 74 | + asm volatile ("csrw pmpcfg2, %0": : "r" (addr)); // 0x3a2 |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +However, these mappings can be changed by altering the following definitions; |
| 79 | +``` |
| 80 | +`define CSR_DFLUSH 12'h3a0 |
| 81 | +`define CSR_DWRITEBACK 12'h3a1 |
| 82 | +`define CSR_DINVALIDATE 12'h3a2 |
| 83 | +``` |
0 commit comments