]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cache.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / cache.c
1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <metal/cache.h>
5 #include <metal/machine.h>
6
7 extern __inline__ void metal_cache_init(struct metal_cache *cache, int ways);
8 extern __inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache);
9 extern __inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways);
10
11 int metal_dcache_l1_available(int hartid) {
12     switch (hartid) {
13     case 0:
14 #ifdef __METAL_CPU_0_DCACHE_HANDLE
15         return __METAL_CPU_0_DCACHE_HANDLE;
16 #endif  
17         break;
18     case 1:
19 #ifdef __METAL_CPU_1_DCACHE_HANDLE
20         return __METAL_CPU_1_DCACHE_HANDLE;
21 #endif
22         break;
23     case 2:
24 #ifdef __METAL_CPU_2_DCACHE_HANDLE
25         return __METAL_CPU_2_DCACHE_HANDLE;
26 #endif
27         break;
28     case 3:
29 #ifdef __METAL_CPU_3_DCACHE_HANDLE
30         return __METAL_CPU_3_DCACHE_HANDLE;
31 #endif
32         break;
33     case 4:
34 #ifdef __METAL_CPU_4_DCACHE_HANDLE
35         return __METAL_CPU_4_DCACHE_HANDLE;
36 #endif
37         break;
38     case 5:
39 #ifdef __METAL_CPU_5_DCACHE_HANDLE
40         return __METAL_CPU_5_DCACHE_HANDLE;
41 #endif
42         break;
43     case 6:
44 #ifdef __METAL_CPU_6_DCACHE_HANDLE
45         return __METAL_CPU_6_DCACHE_HANDLE;
46 #endif
47         break;
48     case 7:
49 #ifdef __METAL_CPU_7_DCACHE_HANDLE
50         return __METAL_CPU_7_DCACHE_HANDLE;
51 #endif
52         break;
53     case 8:
54 #ifdef __METAL_CPU_8_DCACHE_HANDLE
55         return __METAL_CPU_8_DCACHE_HANDLE;
56 #endif
57         break;
58     }
59     return 0;
60 }
61
62 int metal_icache_l1_available(int hartid) {
63     switch (hartid) {
64     case 0:
65 #ifdef __METAL_CPU_0_ICACHE_HANDLE
66         return __METAL_CPU_0_ICACHE_HANDLE;
67 #endif
68         break;
69     case 1:
70 #ifdef __METAL_CPU_1_ICACHE_HANDLE
71         return __METAL_CPU_1_ICACHE_HANDLE;
72 #endif
73         break;
74     case 2:
75 #ifdef __METAL_CPU_2_ICACHE_HANDLE
76         return __METAL_CPU_2_ICACHE_HANDLE;
77 #endif
78         break;
79     case 3:
80 #ifdef __METAL_CPU_3_ICACHE_HANDLE
81         return __METAL_CPU_3_ICACHE_HANDLE;
82 #endif
83         break;
84     case 4:
85 #ifdef __METAL_CPU_4_ICACHE_HANDLE
86         return __METAL_CPU_4_ICACHE_HANDLE;
87 #endif
88         break;
89     case 5:
90 #ifdef __METAL_CPU_5_ICACHE_HANDLE
91         return __METAL_CPU_5_ICACHE_HANDLE;
92 #endif
93         break;
94     case 6:
95 #ifdef __METAL_CPU_6_ICACHE_HANDLE
96         return __METAL_CPU_6_ICACHE_HANDLE;
97 #endif
98         break;
99     case 7:
100 #ifdef __METAL_CPU_7_ICACHE_HANDLE
101         return __METAL_CPU_7_ICACHE_HANDLE;
102 #endif
103         break;
104     case 8:
105 #ifdef __METAL_CPU_8_ICACHE_HANDLE
106         return __METAL_CPU_8_ICACHE_HANDLE;
107 #endif
108         break;
109     }
110     return 0;
111 }
112
113 /*!
114  * @brief CFlush.D.L1 instruction is a custom instruction implemented as a
115  * state machine in L1 Data Cache (D$) with funct3=0, (for core with data caches)
116  * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
117  * 31     28 27    24 23    20 19     16 15   12 11     8 7      4 3      0
118  * |--------|--------|--------|--------|--------|--------|--------|--------|
119  * +-------------+------------+----------+------+--------+-----------------+
120  * |sign immediate12b (simm12)|   rs1    | func3|    rd  |      opcode     |
121  * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-x-x-x-x-x|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
122  * +--------------------------+----------+------+--------+-----------------+
123  * 31     -0x40              20          15  0  12   x0  7      0x73       0
124  * +--------+--------+--------+----------+------+--------+--------+--------+
125  * where,
126  * rs1 = 0x0, CFLUSH.D.L1 writes back and invalidates all lines in the L1 D$
127  * rs1 != x0, CFLUSH.D.L1 writes back and invalidates the L1 D$ line containing
128  *            the virtual address in integer register rs1.
129  */
130 void metal_dcache_l1_flush(int hartid, uintptr_t address)
131 {
132    if (metal_dcache_l1_available(hartid)) {
133         // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
134         __asm__ __volatile__ (".insn i 0x73, 0, x0, %0, -0x40" : : "r" (address));
135         __asm__ __volatile__ ("fence.i");         // FENCE
136     }
137 }
138
139 /*!
140  * @brief CDiscard.D.L1 instruction is a custom instruction implemented as a
141  * state machine in L1 Data Cache (D$) with funct3=0, (for core with data caches)
142  * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
143  * 31     28 27    24 23    20 19     16 15   12 11     8 7      4 3      0
144  * |--------|--------|--------|--------|--------|--------|--------|--------|
145  * +-------------+------------+----------+------+--------+-----------------+
146  * |sign immediate12b (simm12)|   rs1    | func3|    rd  |      opcode     |
147  * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-x-x-x-x-x|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
148  * +--------------------------+----------+------+--------+-----------------+
149  * 31     -0x3E              20          15  0  12   x0  7      0x73       0
150  * +--------+--------+--------+----------+------+--------+--------+--------+
151  * where,
152  * rs1 = 0x0, CDISCARD.D.L1 invalidates all lines in the L1 D$ with no writes back.
153  * rs1 != x0, CDISCARD.D.L1 invalidates the L1 D$ line containing the virtual address
154  *            in integer register rs1, with no writes back.
155  */
156 void metal_dcache_l1_discard(int hartid, uintptr_t address)
157 {
158    if (metal_dcache_l1_available(hartid)) {
159         // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
160         __asm__ __volatile__ (".insn i 0x73, 0, x0, %0, -0x3E" : : "r" (address));
161         __asm__ __volatile__ ("fence.i");         // FENCE
162     }
163 }
164
165 /*!
166  * @brief CFlush.I.L1 instruction is a custom instruction implemented as a state
167  * machine in L1 Instruction Cache (I$) with funct3=0, (for core with data caches)
168  * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
169  * 31     28 27    24 23    20 19     16 15   12 11     8 7      4 3      0
170  * |--------|--------|--------|--------|--------|--------|--------|--------|
171  * +-------------+------------+----------+------+--------+-----------------+
172  * |sign immediate12b (simm12)|   rs1    | func3|    rd  |      opcode     |
173  * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-0-0-0-0-0|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
174  * +--------------------------+----------+------+--------+-----------------+
175  * 31     -0x3F              20          15  0  12   x0  7      0x73       0
176  * +--------+--------+--------+----------+------+--------+--------+--------+
177  * CFLUSH.I.L1 invalidates all lines in the L1 I$.
178  */
179 void metal_icache_l1_flush(int hartid)
180 {
181    if (metal_icache_l1_available(hartid)) {
182         // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
183         __asm__ __volatile__ (".insn i 0x73, 0, x0, x0, -0x3F" : : );
184         __asm__ __volatile__ ("fence.i");         // FENCE
185     }
186 }
187