summaryrefslogtreecommitdiff
path: root/rvcontroller.lua
diff options
context:
space:
mode:
Diffstat (limited to 'rvcontroller.lua')
-rw-r--r--rvcontroller.lua53
1 files changed, 46 insertions, 7 deletions
diff --git a/rvcontroller.lua b/rvcontroller.lua
index 8711a51..e6e86e5 100644
--- a/rvcontroller.lua
+++ b/rvcontroller.lua
@@ -207,6 +207,14 @@ Base + 10: mtimecmp (see RISC-V Machine Level ISA specification)
Base + 18 - Base + 255: Reserved
+Interrupts:
+
+Bits 7/16/17 of mie/mip are currently implemented.
+
+Bit 7: MTIP (machine timer interrupt), standard
+Bit 16: MCIP (mesecons input interrupt), custom for RVController
+Bit 17: DGIP (digilines receive interrupt), custom for RVController
+
]]
--Settings
@@ -765,15 +773,17 @@ end
local function checkinterrupts()
local miebits = explodebits(mem.csr[0x304],32)
- local mipbits = {}
+ local mipbits = explodebits(mem.csr[0x344],32)
if mem.mtimecmphigh == mem.csr[0xc81] and (os.time() - mem.starttime) >= mem.mtimecmplow then
mipbits[7] = true --mtip
elseif mem.mtimecmphigh < mem.csr[0xc81] then
mipbits[7] = true --mtip
+ else
+ mipbits[7] = false
end
mem.csr[0x344] = implodebits(mipbits,32)
if not mem.mie then return end
- local order = {11,3,7,9,1,5,13}
+ local order = {11,3,7,9,1,5,13,16,17}
for _,i in ipairs(order) do
if miebits[i] and mipbits[i] then
return trap(0x80000000+i)
@@ -1211,30 +1221,39 @@ local operations = {
return trap(3,0)
end,
csrrw = function(rd,rs1,imm)
- setreg(rd,readcsr(imm))
+ local out = readcsr(imm)
writecsr(imm,getreg(rs1))
+ setreg(rd,out)
return checkinterrupts()
end,
csrrs = function(rd,rs1,imm)
- setreg(rd,readcsr(imm))
- if rs1 == 0 then return end
+ local out = readcsr(imm)
+ if rs1 == 0 then
+ setreg(rd,out)
+ return
+ end
local csrbits = explodebits(readcsr(imm),32)
local rs1bits = explodebits(getreg(rs1),32)
for i=0,31 do
csrbits[i] = csrbits[i] or rs1bits[i]
end
writecsr(imm,implodebits(csrbits,32))
+ setreg(rd,out)
return checkinterrupts()
end,
csrrc = function(rd,rs1,imm)
- setreg(rd,readcsr(imm))
- if rs1 == 0 then return end
+ local out = readcsr(imm)
+ if rs1 == 0 then
+ setreg(rd,out)
+ return
+ end
local csrbits = explodebits(readcsr(imm),32)
local rs1bits = explodebits(getreg(rs1),32)
for i=0,31 do
csrbits[i] = csrbits[i] and not rs1bits[i]
end
writecsr(imm,implodebits(csrbits,32))
+ setreg(rd,out)
return checkinterrupts()
end,
csrrwi = function(rd,rs1,imm)
@@ -3041,6 +3060,16 @@ elseif event.type == "on" or event.type == "off" then
--MMIO is enabled
writeram(readcsr(0x801)+1,0,1,true) --Invalidate any existing reservation set
end
+ local mipbits = explodebits(mem.csr[0x344],32)
+ mipbits[16] = true
+ mem.csr[0x344] = implodebits(mipbits,32)
+ local miebits = explodebits(mem.csr[0x304],32)
+ if miebits[16] and mem.interruptwaiting then
+ mem.interruptwaiting = false
+ mem.running = true
+ digiline_send("monitordisp","CPU started")
+ interrupt(1/CLOCK_SPEED,"tick")
+ end
end
elseif event.channel == "reset" then
mem.running = false
@@ -3345,6 +3374,16 @@ elseif event.type == "digiline" then
if mem.csr[0x800]%2 == 1 then
interrupt(0,"tick")
end
+ local mipbits = explodebits(mem.csr[0x344],32)
+ mipbits[17] = true
+ mem.csr[0x344] = implodebits(mipbits,32)
+ local miebits = explodebits(mem.csr[0x304],32)
+ if miebits[17] and mem.interruptwaiting then
+ mem.interruptwaiting = false
+ mem.running = true
+ digiline_send("monitordisp","CPU started")
+ interrupt(1/CLOCK_SPEED,"tick")
+ end
elseif event.iid == "tick" and mem.running then
run(INSTRUCTIONS_PER_CLOCK)
if mem.csr[0x800]%2 == 1 then