diff options
Diffstat (limited to 'rvcontroller.lua')
| -rw-r--r-- | rvcontroller.lua | 79 |
1 files changed, 60 insertions, 19 deletions
diff --git a/rvcontroller.lua b/rvcontroller.lua index 1acb1f1..37b09f5 100644 --- a/rvcontroller.lua +++ b/rvcontroller.lua @@ -50,6 +50,8 @@ Intended to be compliant with the following specifications: * Zbkx: Extension for Crossbar permutations, Version 1.0.0 * Xh3bextm: Hazard3 bit extract multiple - Note: Defined in the Hazard3 reference manual, available at https://github.com/Wren6991/Hazard3/releases/download/v1.1/hazard3.pdf +* Machine-Level ISA, Version 1.13 +* "Smdbltrp" Double Trap Extension, Version 1.0 See https://docs.riscv.org/reference/isa/unpriv/unpriv-index.html for full specifications. @@ -338,7 +340,7 @@ local function setreg(reg,val) end local function readram(address,bytes,instfetch) - local bigendian = mem.bigendian and not instfetch --Instruction fetches must always be little-endian + local bigendian = mem.mbe and not instfetch --Instruction fetches must always be little-endian if address > RAM_SIZE-1 and not (address >= mem.csr[0x801] and address <= mem.csr[0x801] + 1) then fault = instfetch and 1 or 5 return instfetch and 0x13 or 0 --0x13 = addi x0,x0,0 @@ -401,7 +403,7 @@ local function writeram(address,data,bytes,fake) local thisbyte = data % (2^((i+1)*8)) / 2^(i*8) thisbyte = math.floor(thisbyte) % 2^32 local offsetaddr - if mem.bigendian then + if mem.mbe then offsetaddr = address+bytes-1-i else offsetaddr = address+i @@ -492,7 +494,28 @@ local function stdout(text) end local function readcsr(address) - if not mem.csr[address] then + if address == 0x341 then --mepc + local ret = mem.csr[0x341] + --mepc[0] must be 0 + if ret%2 == 1 then ret = ret-1 end + --mepc[1] must be 0 if IALIGN=32 + if not mem.isa.c and ret%4 >= 2 then + ret = ret - 2 + end + return ret + elseif address == 0x300 then --mstatus + local bits = {} + bits[3] = mem.mie + bits[7] = mem.mpie + bits[11] = mem.mpp%2 == 1 + bits[12] = mem.mpp >= 2 + return implodebits(bits,32) + elseif address == 0x310 then --mstatush + local bits = {} + bits[5] = mem.mbe + bits[10] = mem.mdt + return implodebits(bits,32) + elseif not mem.csr[address] then digiline_send("monitordisp",string.format("Attempted read\nfrom unknown\nCSR 0x%03X\nPC: %08X",address,mem.registers.pc)) fault = 2 return 0 @@ -505,16 +528,24 @@ local function writecsr(address,data) --jvt data = math.floor(data/2^6)*2^6 --WARL, and mode is required to be 0 elseif address == 0xc00 or address == 0xc01 or address == 0xc02 or address == 0xc80 or address == 0xc81 or address == 0xc82 then - --One of the read-only CSRs from Zicntr, just ignore the write + --One of the read-only CSRs from Zicntr + fault = 2 return - elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 or address == 0x300 then - --Read-only machine information register, ignore write + elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 then + --Read-only machine information register + fault = 2 + return + elseif address == 0x300 then + --mstatus + local bits = explodebits(data,32) + mem.mie = bits[3] and not mem.mdt + mem.mpie = bits[7] return elseif address == 0x310 then --mstatush local bits = explodebits(data,32) - mem.bigendian = bits[5] - mem.csr[0x310] = mem.bigendian and 0x20 or 0 + mem.mbe = bits[5] + mem.mdt = bits[10] return elseif address == 0x301 then --misa @@ -556,7 +587,10 @@ local function trap(reason) writecsr(0x342,reason) --mcause writecsr(0x341,mem.registers.pc) --mepc writecsr(0x343,0) --mtval - if mem.trapbase then + mem.mpie = mem.mie + mem.mie = false + if not mem.mdt then + mem.mdt = 1 if mem.trapmode == 1 then --vectored mode local int = reason >= 0x8000000 @@ -569,7 +603,7 @@ local function trap(reason) return true,false end else - digiline_send("monitordisp","Unhandled trap!") + digiline_send("monitordisp","Unexpected trap!") digiline_send("monitordisp",traptypes[reason] or "Unknown reason") digiline_send("monitordisp",string.format("PC: %08X",mem.registers.pc)) digiline_send("monitordisp","System halted") @@ -859,8 +893,8 @@ local operations = { if rd == 0 or rd == 31 then return end if imm >= 2^11 then imm = imm - 2^12 end local address = getreg(rs1)+imm - setreg(rd,readram(address+(mem.bigendian and 4 or 0),4)) - setreg(rd+1,readram(address+(mem.bigendian and 0 or 4),4)) + setreg(rd,readram(address+(mem.mbe and 4 or 0),4)) + setreg(rd+1,readram(address+(mem.mbe and 0 or 4),4)) end, lhu = function(rd,rs1,imm) if imm >= 2^11 then imm = imm - 2^12 end @@ -888,8 +922,8 @@ local operations = { if rs2 == 31 then return end if imm >= 2^11 then imm = imm - 2^12 end local address = getreg(rs1)+imm - writeram(address+(mem.bigendian and 4 or 0),getreg(rs2),4) - writeram(address+(mem.bigendian and 0 or 4),getreg(rs2+1),4) + writeram(address+(mem.mbe and 4 or 0),getreg(rs2),4) + writeram(address+(mem.mbe and 0 or 4),getreg(rs2+1),4) end, ecall = function() local func = mem.isa.i and getreg(17) or getreg(15) @@ -1787,6 +1821,10 @@ local operations = { end, mret = function() mem.registers.pc = readcsr(0x341) + mem.mie = mem.mpie + mem.mpie = true + mem.mpp = 3 + mem.mdt = false return true end, } @@ -2714,7 +2752,6 @@ if event.type == "program" or event.iid == "reset" then [0x300] = 0, --mstatus [0x301] = 0x40001107, --misa (RV32IMACB) [0x305] = 0, --mtvec - [0x310] = 0, --mstatush [0x340] = 0, --mscratch [0x341] = 0, --mepc [0x342] = 0, --mcause @@ -2737,7 +2774,7 @@ if event.type == "program" or event.iid == "reset" then mem.breakpoint = -1 mem.hexloading = false mem.reservationset = nil - mem.bigendian = false + mem.mbe = false mem.isa = { a = true, b = true, @@ -2748,8 +2785,12 @@ if event.type == "program" or event.iid == "reset" then mem.meseconsdir = {} mem.meseconsdata = {} port = {} - mem.trapbase = nil - mem.trapmode = nil + mem.trapbase = 0 + mem.trapmode = 0 + mem.mie = false + mem.mpie = true + mem.mpp = 3 + mem.mdt = true elseif event.type == "on" or event.type == "off" then local pname = string.lower(event.pin.name) local pstate = pin[pname] @@ -2923,7 +2964,7 @@ elseif event.channel == "monitorkb" then digiline_send("monitordisp",string.format("%03X: %08X",address,readcsr(address))) elseif argv[1] == "endian" then if argc == 1 then - digiline_send("monitordisp",mem.bigendian and "Big-endian" or "Little-endian") + digiline_send("monitordisp",mem.mbe and "Big-endian" or "Little-endian") elseif argv[2] == "b" or argv[2] == "big" then local bits = explodebits(readcsr(0x310),32) --mstatush bits[5] = true --MBE |
