summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtl/gfx/firmware/custom_ops.S103
-rw-r--r--rtl/gfx/firmware/gfx_bootrom.S76
-rw-r--r--rtl/gfx/gfx_bootrom.sv2
-rw-r--r--rtl/gfx/gfx_top.sv3
-rw-r--r--rtl/gfx/gfx_xbar_sched.sv36
5 files changed, 210 insertions, 10 deletions
diff --git a/rtl/gfx/firmware/custom_ops.S b/rtl/gfx/firmware/custom_ops.S
new file mode 100644
index 0000000..95a2f53
--- /dev/null
+++ b/rtl/gfx/firmware/custom_ops.S
@@ -0,0 +1,103 @@
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+
+#define regnum_q0 0
+#define regnum_q1 1
+#define regnum_q2 2
+#define regnum_q3 3
+
+#define regnum_x0 0
+#define regnum_x1 1
+#define regnum_x2 2
+#define regnum_x3 3
+#define regnum_x4 4
+#define regnum_x5 5
+#define regnum_x6 6
+#define regnum_x7 7
+#define regnum_x8 8
+#define regnum_x9 9
+#define regnum_x10 10
+#define regnum_x11 11
+#define regnum_x12 12
+#define regnum_x13 13
+#define regnum_x14 14
+#define regnum_x15 15
+#define regnum_x16 16
+#define regnum_x17 17
+#define regnum_x18 18
+#define regnum_x19 19
+#define regnum_x20 20
+#define regnum_x21 21
+#define regnum_x22 22
+#define regnum_x23 23
+#define regnum_x24 24
+#define regnum_x25 25
+#define regnum_x26 26
+#define regnum_x27 27
+#define regnum_x28 28
+#define regnum_x29 29
+#define regnum_x30 30
+#define regnum_x31 31
+
+#define regnum_zero 0
+#define regnum_ra 1
+#define regnum_sp 2
+#define regnum_gp 3
+#define regnum_tp 4
+#define regnum_t0 5
+#define regnum_t1 6
+#define regnum_t2 7
+#define regnum_s0 8
+#define regnum_s1 9
+#define regnum_a0 10
+#define regnum_a1 11
+#define regnum_a2 12
+#define regnum_a3 13
+#define regnum_a4 14
+#define regnum_a5 15
+#define regnum_a6 16
+#define regnum_a7 17
+#define regnum_s2 18
+#define regnum_s3 19
+#define regnum_s4 20
+#define regnum_s5 21
+#define regnum_s6 22
+#define regnum_s7 23
+#define regnum_s8 24
+#define regnum_s9 25
+#define regnum_s10 26
+#define regnum_s11 27
+#define regnum_t3 28
+#define regnum_t4 29
+#define regnum_t5 30
+#define regnum_t6 31
+
+// x8 is s0 and also fp
+#define regnum_fp 8
+
+#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
+.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
+
+#define picorv32_getq_insn(_rd, _qs) \
+r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_setq_insn(_qd, _rs) \
+r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
+
+#define picorv32_retirq_insn() \
+r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
+
+#define picorv32_maskirq_insn(_rd, _rs) \
+r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_waitirq_insn(_rd) \
+r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_timer_insn(_rd, _rs) \
+r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
+
+
diff --git a/rtl/gfx/firmware/gfx_bootrom.S b/rtl/gfx/firmware/gfx_bootrom.S
new file mode 100644
index 0000000..bf7bd7d
--- /dev/null
+++ b/rtl/gfx/firmware/gfx_bootrom.S
@@ -0,0 +1,76 @@
+#include "custom_ops.S"
+
+.text
+
+.global _start
+_start:
+
+ li a0, 0x00300000 # HOST_CTRL_BASE
+ li a1, 1 << 1 | 1 << 0 # ARINT | AWINT
+ li a2, 1 << 0 # B.VALID = 1
+ li a3, 0x8 # Firmware handover word
+ la a4, .read_data
+ li a5, 1 << 11 | 1 << 9 # CTRL.WVALID | CTRL.AWVALID
+ li a6, 1 << 12 # CTRL.BDONE, doesn't fit in andi
+
+ sw a1, 0(a0)
+
+.wait_axi:
+ picorv32_waitirq_insn(zero)
+
+ lw t0, 0(a0)
+ andi t1, t0, 1 << 8 # ARVALID
+ bne t1, zero, .read
+ and t0, t0, a5
+ beq t0, a5, .write
+ j .wait_axi
+
+.read:
+ lw t0, 4(a0)
+ andi t1, t0, 1 << 0 # AW.VALID
+ beq t1, zero, .wait_axi
+ andi t0, t0, 0b11 << 2
+ add t0, a4, t0
+ lw t0, 0(t0)
+ sw t0, 12(a0) # R.DATA
+
+.read_done:
+ lw t0, 0(a0)
+ andi t0, t0, 1 << 10 # CTRL.RDONE
+ beq t0, zero, .read_done
+ j .wait_axi
+
+.write:
+ lw t0, 8(a0)
+ andi t1, t0, 1 << 0 # AW.VALID
+ beq t1, zero, .wait_axi
+ lw t1, 16(a0)
+ sw a2, 20(a0)
+
+.write_done:
+ lw t2, 0(a0)
+ and t2, t2, a6
+ beq t2, zero, .write_done
+
+ andi t0, t0, ~0b11
+ bne t0, a3, .wait_axi
+ sw zero, 0(a0)
+ # Pass magic & hardware version
+ lw a0, 0(a4)
+ lw a1, 4(a4)
+ jalr t1
+ j .
+
+.balign 4
+
+.read_data:
+ # Magic
+ .word 0x4a7a7b0c
+ # Hardware major.minor.patch
+ .word 1 << 16 | 0 << 8 | 0 << 0
+ # Firmware yyyy.mm.dd.build
+ .word 2024 << 18 | 5 << 15 | 12 << 10 | 1 << 0
+ # Register map version, rev 0 means this is the bootrom firmware
+ .word 0
+
+.balign 4
diff --git a/rtl/gfx/gfx_bootrom.sv b/rtl/gfx/gfx_bootrom.sv
index a8f3b74..5a45da4 100644
--- a/rtl/gfx/gfx_bootrom.sv
+++ b/rtl/gfx/gfx_bootrom.sv
@@ -7,7 +7,7 @@ import gfx::*;
if_axil.s axis
);
- localparam ROM_WORDS_LOG = 8;
+ localparam ROM_WORDS_LOG = 7;
enum int unsigned
{
diff --git a/rtl/gfx/gfx_top.sv b/rtl/gfx/gfx_top.sv
index 5f58edd..93e3ad9 100644
--- a/rtl/gfx/gfx_top.sv
+++ b/rtl/gfx/gfx_top.sv
@@ -63,7 +63,8 @@ import gfx::*;
.debug(debug_axi.m),
.bootrom(bootrom_axi.m),
- .shader_0(shader_0_axi.m)
+ .shader_0(shader_0_axi.m),
+ .host_ctrl(host_ctrl_axi.m)
);
/*TODO
diff --git a/rtl/gfx/gfx_xbar_sched.sv b/rtl/gfx/gfx_xbar_sched.sv
index 5661012..32305cd 100644
--- a/rtl/gfx/gfx_xbar_sched.sv
+++ b/rtl/gfx/gfx_xbar_sched.sv
@@ -7,28 +7,34 @@ import gfx::*;
if_axil.s sched,
if_axil.m debug,
- if_axil.m bootrom,
- if_axil.m shader_0
+ bootrom,
+ shader_0,
+ host_ctrl
);
- localparam word BOOTROM_MASK = 32'hfff0_0000;
- localparam word DEBUG_BASE = 32'h0020_0000;
- localparam word DEBUG_MASK = 32'hfff0_0000;
- localparam word SHADER_0_BASE = 32'h0100_0000;
- localparam word SHADER_0_MASK = 32'hfff0_0000;
+ localparam word
+ BOOTROM_MASK = 32'hfff0_0000,
+ DEBUG_BASE = 32'h0020_0000,
+ DEBUG_MASK = 32'hfff0_0000,
+ HOST_CTRL_BASE = 32'h0030_0000,
+ HOST_CTRL_MASK = 32'hfff0_0000,
+ SHADER_0_BASE = 32'h0100_0000,
+ SHADER_0_MASK = 32'hfff0_0000;
defparam xbar.NM = 1;
- defparam xbar.NS = 3;
+ defparam xbar.NS = 4;
defparam xbar.OPT_LOWPOWER = 0;
defparam xbar.SLAVE_ADDR = {
SHADER_0_BASE,
+ HOST_CTRL_BASE,
DEBUG_BASE,
BOOTROM_BASE
};
defparam xbar.SLAVE_MASK = {
SHADER_0_MASK,
+ HOST_CTRL_MASK,
DEBUG_MASK,
BOOTROM_MASK
};
@@ -64,34 +70,40 @@ import gfx::*;
.M_AXI_AWADDR({
shader_0.awaddr,
+ host_ctrl.awaddr,
debug.awaddr,
bootrom.awaddr
}),
.M_AXI_AWPROT(),
.M_AXI_AWVALID({
shader_0.awvalid,
+ host_ctrl.awvalid,
debug.awvalid,
bootrom.awvalid
}),
.M_AXI_AWREADY({
shader_0.awready,
+ host_ctrl.awready,
debug.awready,
bootrom.awready
}),
.M_AXI_WDATA({
shader_0.wdata,
+ host_ctrl.wdata,
debug.wdata,
bootrom.wdata
}),
.M_AXI_WSTRB(),
.M_AXI_WVALID({
shader_0.wvalid,
+ host_ctrl.wvalid,
debug.wvalid,
bootrom.wvalid
}),
.M_AXI_WREADY({
shader_0.wready,
+ host_ctrl.wready,
debug.wready,
bootrom.wready
}),
@@ -99,45 +111,53 @@ import gfx::*;
.M_AXI_BRESP('0),
.M_AXI_BVALID({
shader_0.bvalid,
+ host_ctrl.bvalid,
debug.bvalid,
bootrom.bvalid
}),
.M_AXI_BREADY({
shader_0.bready,
+ host_ctrl.bready,
debug.bready,
bootrom.bready
}),
.M_AXI_ARADDR({
shader_0.araddr,
+ host_ctrl.araddr,
debug.araddr,
bootrom.araddr
}),
.M_AXI_ARPROT(),
.M_AXI_ARVALID({
shader_0.arvalid,
+ host_ctrl.arvalid,
debug.arvalid,
bootrom.arvalid
}),
.M_AXI_ARREADY({
shader_0.arready,
+ host_ctrl.arready,
debug.arready,
bootrom.arready
}),
.M_AXI_RDATA({
shader_0.rdata,
+ host_ctrl.rdata,
debug.rdata,
bootrom.rdata
}),
.M_AXI_RRESP('0),
.M_AXI_RVALID({
shader_0.rvalid,
+ host_ctrl.rvalid,
debug.rvalid,
bootrom.rvalid
}),
.M_AXI_RREADY({
shader_0.rready,
+ host_ctrl.rready,
debug.rready,
bootrom.rready
})