summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assembly/zicboztest/Makefile24
l---------assembly/zicboztest/rvcontroller.ld1
-rw-r--r--assembly/zicboztest/zicboztest.S17
-rw-r--r--doc/_start_here.txt7
-rw-r--r--doc/hpm.txt11
-rw-r--r--rvcontroller.lua81
6 files changed, 127 insertions, 14 deletions
diff --git a/assembly/zicboztest/Makefile b/assembly/zicboztest/Makefile
new file mode 100644
index 0000000..60747f2
--- /dev/null
+++ b/assembly/zicboztest/Makefile
@@ -0,0 +1,24 @@
+MARCH ?= rv32imacbzicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt_zicboz
+
+.PHONY: all dump load clean
+
+all: zicboztest.hex
+
+zicboztest.o: zicboztest.S
+ riscv32-none-elf-as -I../rvcontroller-libraries -march=${MARCH} -o zicboztest.o zicboztest.S
+
+zicboztest.elf: zicboztest.o
+ riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o zicboztest.elf zicboztest.o
+
+dump: zicboztest.elf
+ riscv32-none-elf-objdump -d zicboztest.elf
+
+zicboztest.hex: zicboztest.elf
+ riscv32-none-elf-objcopy -O ihex zicboztest.elf zicboztest.hex
+
+load: zicboztest.hex
+ bash -c "wl-copy < zicboztest.hex"
+
+clean:
+ rm -f zicboztest.hex zicboztest.elf zicboztest.o
+
diff --git a/assembly/zicboztest/rvcontroller.ld b/assembly/zicboztest/rvcontroller.ld
new file mode 120000
index 0000000..bc01402
--- /dev/null
+++ b/assembly/zicboztest/rvcontroller.ld
@@ -0,0 +1 @@
+../../rvcontroller.ld \ No newline at end of file
diff --git a/assembly/zicboztest/zicboztest.S b/assembly/zicboztest/zicboztest.S
new file mode 100644
index 0000000..c9c5289
--- /dev/null
+++ b/assembly/zicboztest/zicboztest.S
@@ -0,0 +1,17 @@
+li t0,0x4000
+li t1,0xdeadbeef
+li t2,0x7000
+1: sw t1,0(t0)
+addi t0,t0,4
+andi t3,t0,0xff
+bnez t3,2f
+li a7,11
+li a0,'.'
+ecall
+2: blt t0,t2,1b
+
+li a0,0x5000
+cbo.zero 0(a0)
+
+li a7,10
+ecall
diff --git a/doc/_start_here.txt b/doc/_start_here.txt
index de41840..125de5f 100644
--- a/doc/_start_here.txt
+++ b/doc/_start_here.txt
@@ -5,7 +5,7 @@ RVController is a program for use in Luacontrollers (from the mesecons mod) in L
It emulates a single RISC-V hart and a configurable amount (64KiB default) of RAM.
Features:
-* RV32IMACBZicfilp_Zicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zilsd_Zimop_Zabha_Zacas_Zalasr_Zawrs_Zcb_Zclsd_Zcmop_Zcmp_Zcmt_Zbkb_Zbkx_Xh3bextm_Xh3misa instruction set provides:
+* RV32IMACBZicboz_Zicfilp_Zicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zihpm_Zilsd_Zimop_Zabha_Zacas_Zalasr_Zawrs_Zcb_Zclsd_Zcmop_Zcmp_Zcmt_Zbkb_Zbkx_Xh3bextm_Xh3misa instruction set provides:
- 32-bit address space
- 32 32-bit registers (31 general-purpose + 1 zero register)
- Selectable endianness
@@ -40,7 +40,8 @@ RVController is intended to be compliant with the following specifications:
- Note: Implemented as a 'nop' instruction as memory is always consistent (see note on RVWMO below)
* "Zicsr" Extension for Control and Status Register (CSR) Instructions, Version 2.0
* "Zicond" Extension for Integer Conditional Operations, Version 1.0.0
-* "Zicntr" Extension for Counters, Version 2.0
+* "Zicntr" Extension for Base Counters and Timers, Version 2.0
+* "Zihpm" Extension for Hardware Performance Counters, Version 2.0
* "Zimop" Extension for May-Be-Operations, Version 1.0
* "M" Extension for Integer Multiplication and Division, Version 2.0
- Note: This implies the following:
@@ -52,6 +53,7 @@ RVController is intended to be compliant with the following specifications:
* RVWMO Memory Consistency Model, Version 2.0
- Note: The actual implemented memory model is significantly more strict (memory is always consistent, there is no cache)
* "Ztso" Extension for Total Store Ordering, Version 1.0
+* "CMO" Extensions for Base Cache Management Operation ISA, Version 1.0.0 (Zicboz only)
* "C" Extension for Compressed Instructions, Version 2.0
- Note: This implies the following:
- * "Zca" Extension for Code Size Reduction, Version 1.0.0
@@ -91,3 +93,4 @@ Documentation files:
* csr.txt: Control and status registers
* mmio.txt: Memory-mapped I/O
* instructions.txt: List of all supported instructions, sorted by extension
+* hpm.txt: List of counters supported as part of the Zihpm extension
diff --git a/doc/hpm.txt b/doc/hpm.txt
new file mode 100644
index 0000000..07ae2e1
--- /dev/null
+++ b/doc/hpm.txt
@@ -0,0 +1,11 @@
+RVController Zihpm Counter List
+===============================
+
+The following counters are supported as part of the Zihpm extension:
+
+* hpmcounter3: Number of interrupts serviced
+* hpmcounter4: Number of non-interrupt traps handled
+* hpmcounter5: Number of digilines messages received (excluding console)
+* hpmcounter6: Number of console events received
+
+The upper word of each of these values is available in the corresponding hpmcounterXXh CSR.
diff --git a/rvcontroller.lua b/rvcontroller.lua
index 6f97a32..9d9a337 100644
--- a/rvcontroller.lua
+++ b/rvcontroller.lua
@@ -469,7 +469,7 @@ local function readcsr(address)
false, --Zfa
false, --Zfh
false, --Zfhmin
- false, --Zicboz
+ true, --Zicboz
true, --Zicond
false, --Zihintntl
true, --Zihintpause
@@ -514,9 +514,9 @@ local function readcsr(address)
true, --Zifencei
mem.isa.m, --Zmmul
false, --Zibi
- false, --supm(?)
+ false, --supm(S-mode?)
true, --Zicntr
- false, --Zihpm
+ true, --Zihpm
false, --Zfbfmin
false, --Zvfbfmin
false, --Zvfbfwma
@@ -576,6 +576,11 @@ local function writecsr(address,data)
fault = 2
fval = readram(mem.registers.pc,4)
return
+ elseif (address >= 0xc03 and address <= 0xc1f) or (address >= 0xc83 and address < 0xc9f) then
+ --One of the read-only CSRs from Zihpm
+ fault = 2
+ fval = readram(mem.registers.pc,4)
+ return
elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 then
--Read-only machine information register
fault = 2
@@ -644,6 +649,15 @@ local function writecsr(address,data)
end
local function trap(reason,val)
+ if reason >= 0x8000000 then
+ --Interrupt
+ mem.csr[0xc03] = (mem.csr[0xc03]+1)%0x100000000 --hpmcounter3
+ if mem.csr[0xc03] == 0 then mem.csr[0xc83] = (mem.csr[0xc83]+1)%0x100000000 end --hpmcounter3h
+ else
+ --Other
+ mem.csr[0xc04] = (mem.csr[0xc04]+1)%0x100000000 --hpmcounter4
+ if mem.csr[0xc04] == 0 then mem.csr[0xc84] = (mem.csr[0xc84]+1)%0x100000000 end --hpmcounter4h
+ end
local oldreason = reason
if mem.mdt then
writecsr(0x34b,reason) --mtval2
@@ -1973,6 +1987,15 @@ local operations = {
interrupt(1,"checkinterrupt")
return false,true
end,
+ cbozero = function(rs1)
+ local address = getreg(rs1)
+ address = address - (address%0x100)
+ if address >= RAM_SIZE then
+ return trap(7,getreg(rs1))
+ end
+ local segment = address/0x100
+ mem.ram[segment] = string.rep(string.char(0),256)
+ end,
}
local function runinst(instruction)
@@ -2438,11 +2461,22 @@ local function runinst(instruction)
end
end
elseif opcode == 0x0f then
- --Memory is always consistent on this implementation,
- --so all fences can just turn into NOPs
+ local immbits = {[0] = bits[20],bits[21],bits[22],bits[23],bits[24],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[31]}
+ local imm = implodebits(immbits,12)
+ local f3 = implodebits({[0] = bits[12],bits[13],bits[14]},3)
+ local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5)
+ local rs1 = implodebits({[0] = bits[15],bits[16],bits[17],bits[18],bits[19]},5)
if instruction == 0x0100000f then
--pause
return false,true
+ elseif f3 == 0 or f3 == 1 then
+ --fence, fence.tso, or fence.i
+ --Memory is always consistent on this implementation,
+ --so all fences can just turn into NOPs
+ return false,false
+ elseif f3 == 2 and rd == 0 and imm == 4 then
+ --cbo.zero
+ return operations.cbozero(rs1)
end
elseif opcode == 0x0b and mem.isa.x then
--Custom0 instruction (currently all R-type)
@@ -2828,7 +2862,10 @@ local function run(limit)
first = false
local instruction = readram(mem.registers.pc,4,true)
if mem.elp and mem.mlpe then
- if instruction%2^12 == 0x017 and mem.registers.pc%4 == 0 and (math.floor(instruction/2^12) == math.floor(getreg(7)/2^12) or math.floor(instruction/2^12) == 0) then
+ if instruction%2^12 == 0x017
+ and mem.registers.pc%4 == 0
+ and (math.floor(instruction/2^12) == math.floor(getreg(7)/2^12)
+ or math.floor(instruction/2^12) == 0) then
mem.elp = false
else
trap(18,2)
@@ -2935,6 +2972,14 @@ local csraliases = {
minstreth = 0xb82,
mseccfg = 0x747,
["h3.misa"] = 0xbf1,
+ hpmcounter3 = 0xc03,
+ hpmcounter4 = 0xc04,
+ hpmcounter5 = 0xc05,
+ hpmcounter6 = 0xc06,
+ hpmcounter3h = 0xc83,
+ hpmcounter4h = 0xc84,
+ hpmcounter5h = 0xc85,
+ hpmcounter6h = 0xc86,
}
if event.type == "program" or event.iid == "reset" then
@@ -2969,12 +3014,20 @@ if event.type == "program" or event.iid == "reset" then
[0x800] = 0, --Clock Controls
[0x801] = 0, --MMIO Base Address
[0xbf1] = 0, --h3.misa
- [0xc00] = 0, --CYCLE
- [0xc01] = 0, --TIME
- [0xc02] = 0, --INSTRET
- [0xc80] = 0, --CYCLEH
- [0xc81] = 0, --TIMEH
- [0xc82] = 0, --INSTRETH
+ [0xc00] = 0, --cycle
+ [0xc01] = 0, --time
+ [0xc02] = 0, --instret
+ [0xc03] = 0, --hpmcounter3
+ [0xc04] = 0, --hpmcounter4
+ [0xc05] = 0, --hpmcounter5
+ [0xc06] = 0, --hpmcounter6
+ [0xc80] = 0, --cycleh
+ [0xc81] = 0, --timeh
+ [0xc82] = 0, --instreth
+ [0xc83] = 0, --hpmcounter3h
+ [0xc84] = 0, --hpmcounter4h
+ [0xc85] = 0, --hpmcounter5h
+ [0xc86] = 0, --hpmcounter6h
}
for i=1,6 do mem.stdout[i] = "" end
local mdisp = event.type == "program" and "\nReset: Cold" or "\nReset: Warm"
@@ -3259,6 +3312,8 @@ elseif event.channel == "monitorkb" then
digiline_send("monitordisp","Unknown command")
end
elseif event.channel == "stdin" then
+ mem.csr[0xc06] = (mem.csr[0xc06]+1)%0x100000000 --hpmcounter6
+ if mem.csr[0xc06] == 0 then mem.csr[0xc86] = (mem.csr[0xc86]+1)%0x100000000 end --hpmcounter6h
if mem.inputwaiting then
--Blocking read in progress
if mem.inputwaittype == "string" then
@@ -3336,6 +3391,8 @@ elseif event.channel == "load" then
end
end
elseif event.type == "digiline" then
+ mem.csr[0xc05] = (mem.csr[0xc05]+1)%0x100000000 --hpmcounter5
+ if mem.csr[0xc05] == 0 then mem.csr[0xc85] = (mem.csr[0xc85]+1)%0x100000000 end --hpmcounter5h
--Unrecognized digilines signals get forwarded on to the program
event.channel = string.sub(event.channel,1,256)
event.msg = string.sub(tostring(event.msg),1,256)