Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 96 additions & 22 deletions modules/riscv32-common/src/riscv32_common.zig
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,42 @@ pub const csr = struct {
pub const mconfigptr = Csr(0xF15, u32);

pub const mstatus = Csr(0x300, packed struct {
reserved0: u3,
mie: u1,
reserved1: u28,
pub const XS = enum(u2) {
/// Extension unit status
off = 0b00,
initial = 0b01,
clean = 0b10,
dirty = 0b11,
pub const zero = .off;
pub const mask = .dirty;
};
pub const FS = XS;
pub const VS = XS;
pub const MPP = enum(u2) {
user = 0b00,
supervisor = 0b01,
hypervisor = 0b10,
machine = 0b11,
pub const zero = .user;
pub const mask = .machine;
};

reserved0: u1 = 0,
sie: u1 = 0,
reserved2: u1 = 0,
mie: u1 = 0,
reserved4: u1 = 0,
spie: u1 = 0,
ube: u1 = 0,
mpie: u1 = 0,
spp: u1 = 0,
vs: VS = .zero,
mpp: MPP = .zero,
fs: FS = .zero,
xs: XS = .zero,
mprv: u1 = 0,
reserved18: u13 = 0,
sd: u1 = 0,
});
pub const misa = Csr(0x301, u32);
pub const medeleg = Csr(0x302, u32);
Expand All @@ -150,8 +183,8 @@ pub const csr = struct {
vectored = 0b01,
};

mode: Mode,
base: u30,
mode: Mode = .direct,
base: u30 = 0,
});
pub const mcounteren = Csr(0x306, u32);
pub const mstatush = Csr(0x310, u32);
Expand Down Expand Up @@ -384,6 +417,15 @@ pub const csr = struct {
return struct {
const Self = @This();

/// Convert from basic types to CSR packed struct
pub inline fn from_val(val: anytype) T {
switch (@typeInfo(@TypeOf(val))) {
.comptime_int => return @bitCast(@as(u32, val)),
.int => return @bitCast(val),
else => @compileError("unsupported type"),
}
}

pub inline fn read_raw() u32 {
return asm volatile ("csrr %[value], " ++ ident
: [value] "=r" (-> u32),
Expand All @@ -394,11 +436,18 @@ pub const csr = struct {
return @bitCast(read_raw());
}

pub inline fn write_raw(value: u32) void {
asm volatile ("csrw " ++ ident ++ ", %[value]"
:
: [value] "r" (value),
);
pub inline fn write_raw(bits: u32) void {
if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) {
asm volatile ("csrwi " ++ ident ++ ", %[bits]"
:
: [bits] "i" (bits),
);
} else {
asm volatile ("csrw " ++ ident ++ ", %[bits]"
:
: [bits] "r" (bits),
);
}
}

pub inline fn write(value: T) void {
Expand All @@ -420,25 +469,39 @@ pub const csr = struct {
}

pub inline fn set_raw(bits: u32) void {
asm volatile ("csrs " ++ ident ++ ", %[bits]"
:
: [bits] "r" (bits),
);
if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) {
asm volatile ("csrsi " ++ ident ++ ", %[bits]"
:
: [bits] "i" (bits),
);
} else {
asm volatile ("csrs " ++ ident ++ ", %[bits]"
:
: [bits] "r" (bits),
);
}
}

pub inline fn set(fields: anytype) void {
set_raw(get_bits(fields));
pub inline fn set(fields: T) void {
set_raw(@bitCast(fields));
}

pub inline fn clear_raw(bits: u32) void {
asm volatile ("csrc " ++ ident ++ ", %[bits]"
:
: [bits] "r" (bits),
);
if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) {
asm volatile ("csrci " ++ ident ++ ", %[bits]"
:
: [bits] "i" (bits),
);
} else {
asm volatile ("csrc " ++ ident ++ ", %[bits]"
:
: [bits] "r" (bits),
);
}
}

pub inline fn clear(fields: anytype) void {
clear_raw(get_bits(fields));
pub inline fn clear(fields: T) void {
clear_raw(@bitCast(fields));
}

pub inline fn read_set_raw(bits: u32) u32 {
Expand Down Expand Up @@ -476,6 +539,17 @@ pub const csr = struct {
else => @compileError("unsupported type"),
};
}

inline fn is_comptime(x: anytype) bool {
// Voodoo to determine whether x is comptime known
return comptime check: {
// For anonymous tuple types,
// if the value of a field is comptime known,
// then the corresponding field in that tuple's type is comptime.
const field = @typeInfo(@TypeOf(.{x})).@"struct".fields[0];
break :check field.is_comptime;
};
}
};
}
};
Expand Down
14 changes: 7 additions & 7 deletions port/wch/ch32v/src/cpus/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ pub const csr = struct {

/// Machine Mode Status Register
pub const mstatus = Csr(0x300, packed struct(u32) {
pub const Fs = enum(u2) {
pub const FS = enum(u2) {
/// Floating-point unit status
off = 0b00,
initial = 0b01,
Expand All @@ -432,19 +432,19 @@ pub const csr = struct {
/// [2:0] Reserved
reserved0: u3 = 0,
/// [3] Machine mode interrupt enable
mie: u1,
mie: u1 = 0,
/// [6:4] Reserved
reserved4: u3 = 0,
/// [7] Interrupt enable state before entering interrupt
mpie: u1,
mpie: u1 = 0,
/// [10:8] Reserved
reserved8: u3 = 0,
/// [12:11] Privileged mode before entering break
mpp: u2 = 0,
/// [14:13] Floating-point unit status
/// Valid only for WCH-V4F
/// NOTE: reserved on other chips
fs: Fs = .off,
fs: FS = .off,
/// [31:15] Reserved
reserved15: u17 = 0,
});
Expand All @@ -459,16 +459,16 @@ pub const csr = struct {
/// Interrupt or exception entry address mode selection.
/// 0: Use of the uniform entry address.
/// 1: Address offset based on interrupt number *4.
mode0: u1,
mode0: u1 = 0,
/// [1] Mode 1
/// Interrupt vector table identifies patterns.
/// 0: Identification by jump instruction,
/// limited range, support for non-jump 0 instructions.
/// 1: Identify by absolute address, support
/// full range, but must jump.
mode1: u1,
mode1: u1 = 0,
/// [31:2] Base address of the interrupt vector table
base: u30,
base: u30 = 0,
});

pub const mscratch = riscv32_common.csr.mscratch;
Expand Down
Loading