summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assembly/extint-test/Makefile24
-rw-r--r--assembly/extint-test/extint-test.S145
-rwxr-xr-xassembly/extint-test/extint-test.elfbin0 -> 6376 bytes
-rw-r--r--assembly/extint-test/extint-test.hex46
-rw-r--r--assembly/extint-test/extint-test.obin0 -> 3064 bytes
l---------assembly/extint-test/rvcontroller.ld1
-rw-r--r--rvcontroller.lua53
7 files changed, 262 insertions, 7 deletions
diff --git a/assembly/extint-test/Makefile b/assembly/extint-test/Makefile
new file mode 100644
index 0000000..2464c5e
--- /dev/null
+++ b/assembly/extint-test/Makefile
@@ -0,0 +1,24 @@
+MARCH ?= rv32imacbzicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt
+
+.PHONY: all dump load clean
+
+all: extint-test.hex
+
+extint-test.o: extint-test.S
+ riscv32-none-elf-as -I../rvcontroller-libraries -march=${MARCH} -o extint-test.o extint-test.S
+
+extint-test.elf: extint-test.o
+ riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o extint-test.elf extint-test.o
+
+dump: extint-test.elf
+ riscv32-none-elf-objdump -d extint-test.elf
+
+extint-test.hex: extint-test.elf
+ riscv32-none-elf-objcopy -O ihex extint-test.elf extint-test.hex
+
+load: extint-test.hex
+ bash -c "wl-copy < extint-test.hex"
+
+clean:
+ rm -f extint-test.hex extint-test.elf extint-test.o
+
diff --git a/assembly/extint-test/extint-test.S b/assembly/extint-test/extint-test.S
new file mode 100644
index 0000000..c1b872d
--- /dev/null
+++ b/assembly/extint-test/extint-test.S
@@ -0,0 +1,145 @@
+li t0,0xffff0000
+csrw 0x801,t0 # Map the MMIO region somewhere
+la t0,handler
+csrw mtvec,t0 # Set up trap handler
+li t0,0x400
+csrc mstatush,t0 # Turn off MDT
+li t0,0x30000
+csrw mie,t0 # Mask all interrupts except mesecons/digilines
+csrw mip,zero # Clear any pending interrupts
+csrsi mstatus,0x8 # Turn on MIE to enable interrupts
+
+mainloop:
+li a7,4
+la a0,waitingmsg
+ecall # Print waiting message
+wfi # And do nothing else, this program is entirely interrupt-driven
+j mainloop
+
+
+
+.align 4
+handler:
+csrrw x31,mscratch,x31 # Free up x31 to hold the context address
+la x31,hcontext # Using x register numbers here since trap handlers don't use the usual calling convention
+sw x1,0(x31) # Save all the registers to the context
+sd x2,4(x31) # Two at a time since we have Zilsd/Zclsd
+sd x4,12(x31) # Note that I don't actually _need_ all of the registers in the handler,
+sd x6,20(x31) # but I wanted to try this anyway to see how it goes
+sd x8,28(x31)
+sd x10,36(x31)
+sd x12,44(x31)
+sd x14,52(x31)
+sd x16,60(x31)
+sd x18,68(x31)
+sd x20,76(x31)
+sd x22,84(x31)
+sd x24,92(x31)
+sd x26,100(x31)
+sd x28,108(x31)
+sw x30,116(x31)
+csrr x30,mscratch # Get the old x31 value back into a register
+sw x30,120(x31) # and write that back out too
+
+csrr t0,mcause # Read why the trap occurred
+
+li t1,0x80000010 # Interrupt 16 = mesecons
+beq t0,t1,handler_mesecons
+
+li t1,0x80000011 # Interrupt 17 = digilines
+beq t0,t1,handler_digilines
+
+j handler_other # Something else
+
+handler_mesecons:
+li a7,4
+la a0,meseconsmsg
+ecall # Show that this was a mesecons event
+
+li a7,1
+li t0,0xffff0000
+lb a0,1(t0) # Read the mesecons I/O port value
+ecall # And print that
+
+li a7,11
+li a0,'\n'
+ecall # Line feed
+
+j handler_epilogue
+
+handler_digilines:
+li a7,4
+la a0,digilinesmsg
+ecall # Show that this was a digilines event
+
+li a7,135
+la a0,channelbuf
+li a1,21
+la a2,msgbuf
+li a3,21
+ecall # Read what the event was
+
+li a7,4
+la a0,channelbuf
+ecall # Print the channel
+
+li a7,4
+la a0,digilinesmsg2
+ecall # "Message:", this has its own line feeds in it
+
+li a7,4
+la a0,msgbuf
+ecall # Print the message
+
+li a7,11
+li a0,'\n'
+ecall # Line feed
+
+li a7,134
+ecall # Clear out any other digilines messages
+
+j handler_epilogue
+
+handler_other:
+li a7,4
+la a0,unimplementedmsg
+ecall # Display unimplemented trap message
+
+csrr a0,mcause # Read what the cause was
+li a7,1
+ecall # Tell the user
+
+li a7,10
+ecall # Then halt
+
+handler_epilogue:
+csrw mip,zero # Clear out all pending interrupts
+la x31,hcontext # x numbers here for the same reason as during the save
+lw x1,0(x31) # Load all of the registers from the context
+ld x2,4(x31) # Two at a time since we have Zilsd/Zclsd
+ld x4,12(x31)
+ld x6,20(x31)
+ld x8,28(x31)
+ld x10,36(x31)
+ld x12,44(x31)
+ld x14,52(x31)
+ld x16,60(x31)
+ld x18,68(x31)
+ld x20,76(x31)
+ld x22,84(x31)
+ld x24,92(x31)
+ld x26,100(x31)
+ld x28,108(x31)
+ld x30,116(x31)
+mret # Return to the program (not that the rest of the program does much)
+
+hcontext: .skip 32*4
+
+
+waitingmsg: .asciz "Waiting...\n"
+meseconsmsg: .asciz "Mesecons event!\nInput value: "
+digilinesmsg: .asciz "Digilines event!\nChannel:\n"
+digilinesmsg2: .asciz "\nMessage:\n"
+unimplementedmsg: .asciz "Unimplemented trap!\nmcause: "
+channelbuf: .asciz " "
+msgbuf: .asciz " "
diff --git a/assembly/extint-test/extint-test.elf b/assembly/extint-test/extint-test.elf
new file mode 100755
index 0000000..15f2f80
--- /dev/null
+++ b/assembly/extint-test/extint-test.elf
Binary files differ
diff --git a/assembly/extint-test/extint-test.hex b/assembly/extint-test/extint-test.hex
new file mode 100644
index 0000000..c3382c4
--- /dev/null
+++ b/assembly/extint-test/extint-test.hex
@@ -0,0 +1,46 @@
+:10000000C17273901280970200009382A2037390D2
+:1000100052309302004073B00231B7020300739074
+:10002000423073104034736004309148170500006B
+:100030001305A51F7300000073005010FDB70100E9
+:10004000F39F0F34970F0000938F2F1623A01F00EC
+:1000500023B22F0023B64F0023BA6F0023BE8F00B8
+:1000600023B2AF0223B6CF0223BAEF0223BE0F039F
+:1000700023B22F0523B64F0523BA6F0523BE8F0584
+:1000800023B2AF0723B6CF0723AAEF07732F00349D
+:1000900023ACEF07F3222034370300804103638849
+:1000A00062003703008045036385620271A09148B6
+:1000B0001705000013052518730000008548C1725C
+:1000C0000385120073000000AD482945730000004D
+:1000D00059A09148170500001305C51773000000CB
+:1000E00093087008170500001305F51AD545170683
+:1000F00000001306A61BD5467300000091481705A3
+:100100000000130555197300000091481705000001
+:100110001305F5157300000091481705000013053D
+:10012000E51873000000AD482945730000009308EE
+:1001300060087300000005A0914817050000130532
+:10014000C513730000007325203485487300000038
+:10015000A9487300000073104034970F0000938F7C
+:10016000CF0483A00F0003B14F0003B2CF0003B34D
+:100170004F0103B4CF0103B54F0203B6CF0203B75B
+:100180004F0303B8CF0303B94F0403BACF0403BB33
+:100190004F0503BCCF0503BD4F0603BECF0603BF0B
+:1001A0004F07730020300000000000000000000036
+:1001B000000000000000000000000000000000003F
+:1001C000000000000000000000000000000000002F
+:1001D000000000000000000000000000000000001F
+:1001E000000000000000000000000000000000000F
+:1001F00000000000000000000000000000000000FF
+:1002000000000000000000000000000000000000EE
+:1002100000000000000000000000000000000000DE
+:1002200000000000000057616974696E672E2E2E71
+:100230000A004D657365636F6E73206576656E7435
+:10024000210A496E7075742076616C75653A2000DC
+:10025000446967696C696E6573206576656E7421A3
+:100260000A4368616E6E656C3A0A000A4D657373E5
+:100270006167653A0A00556E696D706C656D656EF3
+:100280007465642074726170210A6D6361757365B1
+:100290003A20002020202020202020202020202064
+:1002A000202020202020200020202020202020206E
+:1002B00020202020202020202020202000000100BD
+:0402C0001300000027
+:00000001FF
diff --git a/assembly/extint-test/extint-test.o b/assembly/extint-test/extint-test.o
new file mode 100644
index 0000000..3aba761
--- /dev/null
+++ b/assembly/extint-test/extint-test.o
Binary files differ
diff --git a/assembly/extint-test/rvcontroller.ld b/assembly/extint-test/rvcontroller.ld
new file mode 120000
index 0000000..bc01402
--- /dev/null
+++ b/assembly/extint-test/rvcontroller.ld
@@ -0,0 +1 @@
+../../rvcontroller.ld \ No newline at end of file
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