Skip to content

Commit d9cd460

Browse files
authored
Merge pull request #66 from Mes0903/master
Migrate to ACLINT
2 parents 59d39f5 + 8171414 commit d9cd460

File tree

7 files changed

+400
-142
lines changed

7 files changed

+400
-142
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ OBJS := \
5353
plic.o \
5454
uart.o \
5555
main.o \
56-
clint.o \
56+
aclint.o \
5757
$(OBJS_EXTRA)
5858

5959
deps := $(OBJS:%.o=.%.o.d)

aclint.c

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#include <stdint.h>
2+
#include "device.h"
3+
#include "riscv.h"
4+
#include "riscv_private.h"
5+
6+
/* ACLINT MTIMER */
7+
void aclint_mtimer_update_interrupts(hart_t *hart, mtimer_state_t *mtimer)
8+
{
9+
if (semu_timer_get(&mtimer->mtime) >= mtimer->mtimecmp[hart->mhartid])
10+
hart->sip |= RV_INT_STI_BIT; /* Set Supervisor Timer Interrupt */
11+
else
12+
hart->sip &= ~RV_INT_STI_BIT; /* Clear Supervisor Timer Interrupt */
13+
}
14+
15+
static bool aclint_mtimer_reg_read(mtimer_state_t *mtimer,
16+
uint32_t addr,
17+
uint32_t *value)
18+
{
19+
/* 'addr & 0x4' is used to determine the upper or lower 32 bits
20+
* of the mtimecmp register. If 'addr & 0x4' is 0, then the lower 32
21+
* bits are accessed.
22+
*
23+
* 'addr >> 3' is used to get the index of the mtimecmp array. In
24+
* "ACLINT MTIMER Compare Register Map", each mtimecmp register is 8
25+
* bytes long. So, we need to divide the address by 8 to get the index.
26+
*/
27+
28+
/* mtimecmp (0x4300000 ~ 0x4307FF8) */
29+
if (addr < 0x7FF8) {
30+
*value =
31+
(uint32_t) (mtimer->mtimecmp[addr >> 3] >> (addr & 0x4 ? 32 : 0));
32+
return true;
33+
}
34+
35+
/* mtime (0x4307FF8 ~ 0x4308000) */
36+
if (addr < 0x8000) {
37+
*value = (uint32_t) (semu_timer_get(&mtimer->mtime) >>
38+
(addr & 0x4 ? 32 : 0));
39+
return true;
40+
}
41+
return false;
42+
}
43+
44+
static bool aclint_mtimer_reg_write(mtimer_state_t *mtimer,
45+
uint32_t addr,
46+
uint32_t value)
47+
{
48+
/* The 'cmp_val & 0xFFFFFFFF' is used to select the upper 32 bits
49+
* of mtimer->mtimecmp[addr >> 3], then shift the value to the left by
50+
* 32 bits to set the upper 32 bits.
51+
*
52+
* Similarly, 'cmp_val & 0xFFFFFFFF00000000ULL' is used to select the lower
53+
* 32 bits of mtimer->mtimecmp[addr >> 3].
54+
*/
55+
56+
/* mtimecmp (0x4300000 ~ 0x4307FF8) */
57+
if (addr < 0x7FF8) {
58+
uint64_t cmp_val = mtimer->mtimecmp[addr >> 3];
59+
60+
if (addr & 0x4)
61+
cmp_val = (cmp_val & 0xFFFFFFFF) | ((uint64_t) value << 32);
62+
else
63+
cmp_val = (cmp_val & 0xFFFFFFFF00000000ULL) | value;
64+
65+
mtimer->mtimecmp[addr >> 3] = cmp_val;
66+
return true;
67+
}
68+
69+
/* mtime (0x4307FF8 ~ 0x4308000) */
70+
if (addr < 0x8000) {
71+
uint64_t mtime_val = mtimer->mtime.begin;
72+
if (addr & 0x4)
73+
mtime_val = (mtime_val & 0xFFFFFFFF) | ((uint64_t) value << 32);
74+
else
75+
mtime_val = (mtime_val & 0xFFFFFFFF00000000ULL) | value;
76+
77+
semu_timer_rebase(&mtimer->mtime, mtime_val);
78+
return true;
79+
}
80+
81+
return false;
82+
}
83+
84+
void aclint_mtimer_read(hart_t *hart,
85+
mtimer_state_t *mtimer,
86+
uint32_t addr,
87+
uint8_t width,
88+
uint32_t *value)
89+
{
90+
if (!aclint_mtimer_reg_read(mtimer, addr, value))
91+
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
92+
93+
*value >>= RV_MEM_SW - width;
94+
}
95+
96+
void aclint_mtimer_write(hart_t *hart,
97+
mtimer_state_t *mtimer,
98+
uint32_t addr,
99+
uint8_t width,
100+
uint32_t value)
101+
{
102+
if (!aclint_mtimer_reg_write(mtimer, addr, value << (RV_MEM_SW - width)))
103+
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
104+
}
105+
106+
/* ACLINT MSWI */
107+
void aclint_mswi_update_interrupts(hart_t *hart, mswi_state_t *mswi)
108+
{
109+
if (mswi->msip[hart->mhartid])
110+
hart->sip |= RV_INT_SSI_BIT; /* Set Machine Software Interrupt */
111+
else
112+
hart->sip &= ~RV_INT_SSI_BIT; /* Clear Machine Software Interrupt */
113+
}
114+
115+
static bool aclint_mswi_reg_read(mswi_state_t *mswi,
116+
uint32_t addr,
117+
uint32_t *value)
118+
{
119+
/* 'msip' is an array where each entry corresponds to a Hart,
120+
* each entry is 4 bytes (32 bits). So, we need to divide the address
121+
* by 4 to get the index.
122+
*/
123+
124+
/* Address range for msip: 0x4400000 ~ 0x4404000 */
125+
if (addr < 0x4000) {
126+
*value = mswi->msip[addr >> 2];
127+
return true;
128+
}
129+
return false;
130+
}
131+
132+
static bool aclint_mswi_reg_write(mswi_state_t *mswi,
133+
uint32_t addr,
134+
uint32_t value)
135+
{
136+
if (addr < 0x4000) {
137+
mswi->msip[addr >> 2] = value & 0x1; /* Only the LSB is valid */
138+
return true;
139+
}
140+
return false;
141+
}
142+
143+
void aclint_mswi_read(hart_t *hart,
144+
mswi_state_t *mswi,
145+
uint32_t addr,
146+
uint8_t width,
147+
uint32_t *value)
148+
{
149+
if (!aclint_mswi_reg_read(mswi, addr, value))
150+
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
151+
152+
*value >>= RV_MEM_SW - width;
153+
}
154+
155+
void aclint_mswi_write(hart_t *hart,
156+
mswi_state_t *mswi,
157+
uint32_t addr,
158+
uint8_t width,
159+
uint32_t value)
160+
{
161+
if (!aclint_mswi_reg_write(mswi, addr, value << (RV_MEM_SW - width)))
162+
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
163+
}
164+
165+
/* ACLINT SSWI */
166+
void aclint_sswi_update_interrupts(hart_t *hart, sswi_state_t *sswi)
167+
{
168+
if (sswi->ssip[hart->mhartid])
169+
hart->sip |= RV_INT_SSI_BIT; /* Set Supervisor Software Interrupt */
170+
else
171+
hart->sip &= ~RV_INT_SSI_BIT; /* Clear Supervisor Software Interrupt */
172+
}
173+
174+
static bool aclint_sswi_reg_read(__attribute__((unused)) sswi_state_t *sswi,
175+
uint32_t addr,
176+
uint32_t *value)
177+
{
178+
/* Address range for ssip: 0x4500000 ~ 0x4504000 */
179+
if (addr < 0x4000) {
180+
*value = 0; /* Upper 31 bits are zero, and LSB reads as 0 */
181+
return true;
182+
}
183+
return false;
184+
}
185+
186+
static bool aclint_sswi_reg_write(sswi_state_t *sswi,
187+
uint32_t addr,
188+
uint32_t value)
189+
{
190+
if (addr < 0x4000) {
191+
sswi->ssip[addr >> 2] = value & 0x1; /* Only the LSB is valid */
192+
193+
return true;
194+
}
195+
return false;
196+
}
197+
198+
void aclint_sswi_read(hart_t *hart,
199+
sswi_state_t *sswi,
200+
uint32_t addr,
201+
uint8_t width,
202+
uint32_t *value)
203+
{
204+
if (!aclint_sswi_reg_read(sswi, addr, value))
205+
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
206+
207+
*value >>= RV_MEM_SW - width;
208+
}
209+
210+
void aclint_sswi_write(hart_t *hart,
211+
sswi_state_t *sswi,
212+
uint32_t addr,
213+
uint8_t width,
214+
uint32_t value)
215+
{
216+
if (!aclint_sswi_reg_write(sswi, addr, value << (RV_MEM_SW - width)))
217+
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
218+
}

clint.c

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)