1 /* See LICENSE for license details. */
2 #include <gd32vf103.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #if   defined (__ICCRISCV__)
8     #include "compiler.h"
9 #elif defined ( __GNUC__ )
10     #include <unistd.h>
11 #endif
12 
13 #include "riscv_encoding.h"
14 #include "n200_func.h"
15 
16 /* Configure PMP to make all the address space accesable and executable */
pmp_open_all_space(void)17 void pmp_open_all_space(void){
18     /* Config entry0 addr to all 1s to make the range cover all space */
19     asm volatile ("li x6, 0xffffffff":::"x6");
20     asm volatile ("csrw pmpaddr0, x6":::);
21     /* Config entry0 cfg to make it NAPOT address mode, and R/W/X okay */
22     asm volatile ("li x6, 0x7f":::"x6");
23     asm volatile ("csrw pmpcfg0, x6":::);
24 }
25 
switch_m2u_mode(void)26 void switch_m2u_mode(void){
27 #if   defined (__ICCRISCV__)
28     clear_csr (CSR_MSTATUS,MSTATUS_MPP);
29 #elif defined ( __GNUC__ )
30     clear_csr (mstatus,MSTATUS_MPP);
31 #endif
32     /* printf("\nIn the m2u function, the mstatus is 0x%x\n", read_csr(mstatus)); */
33     /* printf("\nIn the m2u function, the mepc is 0x%x\n", read_csr(mepc)); */
34 #if defined ( __GNUC__ )
35     asm volatile ("la x6, 1f    ":::"x6");
36 #endif
37     asm volatile ("csrw mepc, x6":::);
38     asm volatile ("mret":::);
39     asm volatile ("1:":::);
40 }
41 
mtime_lo(void)42 uint32_t mtime_lo(void)
43 {
44   return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
45 }
46 
47 
mtime_hi(void)48 uint32_t mtime_hi(void)
49 {
50   return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME + 4);
51 }
52 
get_timer_value(void)53 uint64_t get_timer_value(void)
54 {
55   while (1) {
56     uint32_t hi = mtime_hi();
57     uint32_t lo = mtime_lo();
58     if (hi == mtime_hi())
59       return ((uint64_t)hi << 32) | lo;
60   }
61 }
62 
get_timer_freq(void)63 uint32_t get_timer_freq(void)
64 {
65   return TIMER_FREQ;
66 }
67 
get_instret_value(void)68 uint64_t get_instret_value(void)
69 {
70   while (1) {
71 #if   defined (__ICCRISCV__)
72     uint32_t hi = read_csr(CSR_MINSTRETH);
73     uint32_t lo = read_csr(CSR_MINSTRETH);
74     if (hi == read_csr(CSR_MINSTRETH))
75 #elif defined ( __GNUC__ )
76     uint32_t hi = read_csr(minstreth);
77     uint32_t lo = read_csr(minstret);
78     if (hi == read_csr(minstreth))
79 #endif
80 
81       return ((uint64_t)hi << 32) | lo;
82   }
83 }
84 
get_cycle_value(void)85 uint64_t get_cycle_value(void)
86 {
87   while (1) {
88 #if   defined (__ICCRISCV__)
89     uint32_t hi = read_csr(CSR_MCYCLEH);
90     uint32_t lo = read_csr(CSR_MCYCLE);
91     if (hi == read_csr(CSR_MCYCLEH))
92 #elif defined ( __GNUC__ )
93     uint32_t hi = read_csr(mcycleh);
94     uint32_t lo = read_csr(mcycle);
95     if (hi == read_csr(mcycleh))
96 #endif
97 
98       return ((uint64_t)hi << 32) | lo;
99   }
100 }
101 
measure_cpu_freq(size_t n)102 uint32_t __attribute__((noinline)) measure_cpu_freq(size_t n)
103 {
104   uint32_t start_mtime, delta_mtime;
105   uint32_t mtime_freq = get_timer_freq();
106 
107   /* Don't start measuruing until we see an mtime tick */
108   uint32_t tmp = mtime_lo();
109   do {
110     start_mtime = mtime_lo();
111   } while (start_mtime == tmp);
112 
113 #if   defined (__ICCRISCV__)
114   uint32_t start_mcycle = read_csr(CSR_MCYCLE);
115 #elif defined ( __GNUC__ )
116   uint32_t start_mcycle = read_csr(mcycle);
117 #endif
118 
119   do {
120     delta_mtime = mtime_lo() - start_mtime;
121   } while (delta_mtime < n);
122 
123 #if   defined (__ICCRISCV__)
124   uint32_t delta_mcycle = read_csr(CSR_MCYCLE) - start_mcycle;
125 #elif defined ( __GNUC__ )
126   uint32_t delta_mcycle = read_csr(mcycle) - start_mcycle;
127 #endif
128 
129   return (delta_mcycle / delta_mtime) * mtime_freq
130          + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
131 }
132 
get_cpu_freq(void)133 uint32_t get_cpu_freq(void)
134 {
135   uint32_t cpu_freq;
136 
137   /* warm up */
138   measure_cpu_freq(1);
139   /* measure for real */
140   cpu_freq = measure_cpu_freq(100);
141 
142   return cpu_freq;
143 }
144 
145 /* Note that there are no assertions or bounds checking on these */
146 /* parameter values. */
eclic_init(uint32_t num_irq)147 void eclic_init ( uint32_t num_irq )
148 {
149 
150   typedef volatile uint32_t vuint32_t;
151 
152   /* clear cfg register */
153   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET)=0;
154 
155   /* clear minthresh register */
156   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET)=0;
157 
158   /* clear all IP/IE/ATTR/CTRL bits for all interrupt sources */
159   vuint32_t * ptr;
160 
161   vuint32_t * base = (vuint32_t*)(ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET);
162   vuint32_t * upper = (vuint32_t*)(base + num_irq*4);
163 
164   for (ptr = base; ptr < upper; ptr=ptr+4){
165     *ptr = 0;
166   }
167 }
168 
eclic_enable_interrupt(uint32_t source)169 void eclic_enable_interrupt (uint32_t source) {
170     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 1;
171 }
172 
eclic_disable_interrupt(uint32_t source)173 void eclic_disable_interrupt (uint32_t source){
174     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 0;
175 }
176 
eclic_set_pending(uint32_t source)177 void eclic_set_pending(uint32_t source){
178     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 1;
179 }
180 
eclic_clear_pending(uint32_t source)181 void eclic_clear_pending(uint32_t source){
182     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 0;
183 }
184 
eclic_set_intctrl(uint32_t source,uint8_t intctrl)185 void eclic_set_intctrl (uint32_t source, uint8_t intctrl){
186   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4) = intctrl;
187 }
188 
eclic_get_intctrl(uint32_t source)189 uint8_t eclic_get_intctrl  (uint32_t source){
190   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4);
191 }
192 
eclic_set_intattr(uint32_t source,uint8_t intattr)193 void eclic_set_intattr (uint32_t source, uint8_t intattr){
194   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4) = intattr;
195 }
196 
eclic_get_intattr(uint32_t source)197 uint8_t eclic_get_intattr  (uint32_t source){
198   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4);
199 }
200 
eclic_set_cliccfg(uint8_t cliccfg)201 void eclic_set_cliccfg (uint8_t cliccfg){
202   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET) = cliccfg;
203 }
204 
eclic_get_cliccfg(void)205 uint8_t eclic_get_cliccfg (void){
206   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET);
207 }
208 
eclic_set_mth(uint8_t mth)209 void eclic_set_mth (uint8_t mth){
210   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET) = mth;
211 }
212 
eclic_get_mth(void)213 uint8_t eclic_get_mth (void){
214   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET);
215 }
216 
217 /* sets nlbits */
eclic_set_nlbits(uint8_t nlbits)218 void eclic_set_nlbits(uint8_t nlbits) {
219   /* shift nlbits to correct position */
220   uint8_t nlbits_shifted = nlbits << ECLIC_CFG_NLBITS_LSB;
221 
222   /* read the current cliccfg */
223   uint8_t old_cliccfg = eclic_get_cliccfg();
224   uint8_t new_cliccfg = (old_cliccfg & (~ECLIC_CFG_NLBITS_MASK)) | (ECLIC_CFG_NLBITS_MASK & nlbits_shifted);
225 
226   eclic_set_cliccfg(new_cliccfg);
227 }
228 
229 /* get nlbits */
eclic_get_nlbits(void)230 uint8_t eclic_get_nlbits(void) {
231   /* extract nlbits */
232   uint8_t nlbits = eclic_get_cliccfg();
233   nlbits = (nlbits & ECLIC_CFG_NLBITS_MASK) >> ECLIC_CFG_NLBITS_LSB;
234   return nlbits;
235 }
236 
237 /* sets an interrupt level based encoding of nlbits and ECLICINTCTLBITS */
eclic_set_irq_lvl(uint32_t source,uint8_t lvl)238 void eclic_set_irq_lvl(uint32_t source, uint8_t lvl) {
239   /* extract nlbits */
240   uint8_t nlbits = eclic_get_nlbits();
241   if (nlbits > ECLICINTCTLBITS) {
242     nlbits = ECLICINTCTLBITS;
243   }
244 
245   /* shift lvl right to mask off unused bits */
246   lvl = lvl >> (8-nlbits);
247   /* shift lvl into correct bit position */
248   lvl = lvl << (8-nlbits);
249 
250   /* write to clicintctrl */
251   uint8_t current_intctrl = eclic_get_intctrl(source);
252   /* shift intctrl left to mask off unused bits */
253   current_intctrl = current_intctrl << nlbits;
254   /* shift intctrl into correct bit position */
255   current_intctrl = current_intctrl >> nlbits;
256 
257   eclic_set_intctrl(source, (current_intctrl | lvl));
258 }
259 
260 /* gets an interrupt level based encoding of nlbits */
eclic_get_irq_lvl(uint32_t source)261 uint8_t eclic_get_irq_lvl(uint32_t source) {
262   /* extract nlbits */
263   uint8_t nlbits = eclic_get_nlbits();
264   if (nlbits > ECLICINTCTLBITS) {
265     nlbits = ECLICINTCTLBITS;
266   }
267 
268   uint8_t intctrl = eclic_get_intctrl(source);
269 
270   /* shift intctrl */
271   intctrl = intctrl >> (8-nlbits);
272   /* shift intctrl */
273   uint8_t lvl = intctrl << (8-nlbits);
274 
275   return lvl;
276 }
277 
eclic_set_irq_lvl_abs(uint32_t source,uint8_t lvl_abs)278 void eclic_set_irq_lvl_abs(uint32_t source, uint8_t lvl_abs) {
279   /* extract nlbits */
280   uint8_t nlbits = eclic_get_nlbits();
281   if (nlbits > ECLICINTCTLBITS) {
282     nlbits = ECLICINTCTLBITS;
283   }
284 
285   /* shift lvl_abs into correct bit position */
286   uint8_t lvl = lvl_abs << (8-nlbits);
287 
288   /* write to clicintctrl */
289   uint8_t current_intctrl = eclic_get_intctrl(source);
290   /* shift intctrl left to mask off unused bits */
291   current_intctrl = current_intctrl << nlbits;
292   /* shift intctrl into correct bit position */
293   current_intctrl = current_intctrl >> nlbits;
294 
295   eclic_set_intctrl(source, (current_intctrl | lvl));
296 }
297 
eclic_get_irq_lvl_abs(uint32_t source)298 uint8_t eclic_get_irq_lvl_abs(uint32_t source) {
299   /* extract nlbits */
300   uint8_t nlbits = eclic_get_nlbits();
301   if (nlbits > ECLICINTCTLBITS) {
302     nlbits = ECLICINTCTLBITS;
303   }
304 
305   uint8_t intctrl = eclic_get_intctrl(source);
306 
307   /* shift intctrl */
308   intctrl = intctrl >> (8-nlbits);
309   /* shift intctrl */
310   uint8_t lvl_abs = intctrl;
311 
312   return lvl_abs;
313 }
314 
315 /* sets an interrupt priority based encoding of nlbits and ECLICINTCTLBITS */
eclic_set_irq_priority(uint32_t source,uint8_t priority)316 uint8_t eclic_set_irq_priority(uint32_t source, uint8_t priority) {
317     /* extract nlbits */
318     uint8_t nlbits = eclic_get_nlbits();
319     if (nlbits >= ECLICINTCTLBITS) {
320         nlbits = ECLICINTCTLBITS;
321         return 0;
322     }
323 
324     /* shift priority into correct bit position */
325     priority = priority << (8 - ECLICINTCTLBITS);
326 
327     /* write to eclicintctrl */
328     uint8_t current_intctrl = eclic_get_intctrl(source);
329     /* shift intctrl right to mask off unused bits */
330     current_intctrl = current_intctrl >> (8-nlbits);
331     /* shift intctrl into correct bit position */
332     current_intctrl = current_intctrl << (8-nlbits);
333 
334     eclic_set_intctrl(source, (current_intctrl | priority));
335 
336     return priority;
337 }
338 
339 /* gets an interrupt priority based encoding of nlbits */
eclic_get_irq_priority(uint32_t source)340 uint8_t eclic_get_irq_priority(uint32_t source) {
341     /* extract nlbits */
342     uint8_t nlbits = eclic_get_nlbits();
343     if (nlbits > ECLICINTCTLBITS) {
344           nlbits = ECLICINTCTLBITS;
345     }
346 
347     uint8_t intctrl = eclic_get_intctrl(source);
348 
349     /* shift intctrl */
350     intctrl = intctrl << nlbits;
351     /* shift intctrl */
352     uint8_t priority = intctrl >> (nlbits+(8 - ECLICINTCTLBITS));
353 
354     return priority;
355 }
356 
eclic_mode_enable()357 void eclic_mode_enable() {
358 #if   defined (__ICCRISCV__)
359   uint32_t mtvec_value = read_csr(CSR_MTVEC);
360   mtvec_value = mtvec_value & 0xFFFFFFC0;
361   mtvec_value = mtvec_value | 0x00000003;
362   write_csr(CSR_MTVEC,mtvec_value);
363 #elif defined ( __GNUC__ )
364   uint32_t mtvec_value = read_csr(mtvec);
365   mtvec_value = mtvec_value & 0xFFFFFFC0;
366   mtvec_value = mtvec_value | 0x00000003;
367   write_csr(mtvec,mtvec_value);
368 #endif
369 
370 }
371 
372 /* sets vector-mode or non-vector mode */
eclic_set_vmode(uint32_t source)373 void eclic_set_vmode(uint32_t source) {
374   /* read the current attr */
375   uint8_t old_intattr = eclic_get_intattr(source);
376       /*  Keep other bits unchanged and only set the LSB bit */
377   uint8_t new_intattr = (old_intattr | 0x1);
378 
379   eclic_set_intattr(source,new_intattr);
380 }
381 
eclic_set_nonvmode(uint32_t source)382 void eclic_set_nonvmode(uint32_t source) {
383   /* read the current attr */
384   uint8_t old_intattr = eclic_get_intattr(source);
385       /* Keep other bits unchanged and only clear the LSB bit*/
386   uint8_t new_intattr = (old_intattr & (~0x1));
387 
388   eclic_set_intattr(source,new_intattr);
389 }
390 
391 /* sets interrupt as level sensitive
392 Bit 1, trig[0], is defined as "edge-triggered" (0: level-triggered, 1: edge-triggered);
393 Bit 2, trig[1], is defined as "negative-edge" (0: positive-edge, 1: negative-edge).*/
394 
eclic_set_level_trig(uint32_t source)395 void eclic_set_level_trig(uint32_t source) {
396   /* read the current attr */
397   uint8_t old_intattr = eclic_get_intattr(source);
398       /* Keep other bits unchanged and only clear the bit 1 */
399   uint8_t new_intattr = (old_intattr & (~0x2));
400 
401   eclic_set_intattr(source,new_intattr);
402 }
403 
eclic_set_posedge_trig(uint32_t source)404 void eclic_set_posedge_trig(uint32_t source) {
405   /* read the current attr */
406   uint8_t old_intattr = eclic_get_intattr(source);
407       /* Keep other bits unchanged and only set the bit 1 */
408   uint8_t new_intattr = (old_intattr | 0x2);
409       /* Keep other bits unchanged and only clear the bit 2 */
410   new_intattr = (old_intattr & (~0x4));
411 
412   eclic_set_intattr(source,new_intattr);
413 }
414 
eclic_set_negedge_trig(uint32_t source)415 void eclic_set_negedge_trig(uint32_t source) {
416   /*read the current attr */
417   uint8_t old_intattr = eclic_get_intattr(source);
418       /* Keep other bits unchanged and only set the bit 1*/
419   uint8_t new_intattr = (old_intattr | 0x2);
420       /* Keep other bits unchanged and only set the bit 2*/
421   new_intattr = (old_intattr | 0x4);
422 
423   eclic_set_intattr(source,new_intattr);
424 }
425