Skip to content

Commit

Permalink
Use a new method to decode instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Emin017 committed May 10, 2024
1 parent 1bd6eb5 commit 9124788
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 66 deletions.
30 changes: 30 additions & 0 deletions src/arch/rv64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
// See the Mulan PSL v2 for more details.

const std = @import("std");
const decode = @import("../cpu/decode.zig");
const cpu = @import("../cpu/cpu.zig");
const setState = @import("../cpu/exu.zig").setState;

pub const word_t = u64;
pub const vaddr_t = u64;
Expand All @@ -20,3 +23,30 @@ pub const riscv64_ISADecodeInfo = packed struct {
val: u32,
};
};

pub const MatchOp = *const fn (inst: decode.Instruction) void;

pub fn addi(inst: decode.Instruction) void {
const op = inst.addi;
cpu.setGPRs(op.rd, cpu.GPRs(op.rs1) +% op.imm);
return;
}

pub fn ebreak(inst: decode.Instruction) void {
if (inst.ebreak.halt == 1) {
// std.debug.print("is halt:{}\n", .{inst.ebreak.halt});
setState(true);
} else {
const out: u8 = @intCast(cpu.cpu.gprs[11] & 0xff);
std.debug.print("{c}", .{out});
setState(false);
}
return;
}

pub fn inst2exu(inst: decode.Instruction) MatchOp {
return switch (inst) {
.addi => addi,
.ebreak => ebreak,
};
}
93 changes: 59 additions & 34 deletions src/cpu/decode.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const word_t = isa.word_t;
const testing = std.testing;
const expect = std.testing.expect;
const print = @import("../common.zig").print;
const cpu = @import("./cpu.zig");
const utils = @import("../util.zig");

const DECODE_TYPE = enum {
TYPE_I,
Expand All @@ -34,40 +36,63 @@ pub const Decode = struct {
inst: u32,
};

fn BITSMASK(hi: u5, lo: u5) u32 {
return ((@as(u32, 1) << (hi - lo + 1)) - 1) << lo;
}
pub const TypeB = struct {
imm: u32,
rs1: u32,
rs2: u32,
rd: u32,
};

pub const TypeI = struct {
imm: u32,
rs1: u32,
rd: u32,
pub fn decode(inst: u32) TypeI {
const imm: u32 = utils.BITS(inst, 31, 20);
const rs1: u32 = utils.BITS(inst, 19, 15);
const rd: u32 = utils.BITS(inst, 11, 7);
return TypeI{
.imm = imm,
.rs1 = rs1,
.rd = rd,
};
}
pub fn Operand(funct3: u32) !Operand {
return switch (funct3) {
0 => Operand.addi,
else => unreachable,
};
}
};

fn BITS(x: u32, hi: u5, lo: u5) u32 {
const mask = BITSMASK(hi, lo);
return (x & mask) >> @intCast(lo);
}
pub const TypeEnv = struct {
ebreak: u32,
ret: u64,
halt: u32,
const inst_ebreak: u32 = 0b00000000000100000000000001110011;
pub fn decode(inst: u32) TypeEnv {
// Halt emu when is ebreak
if (inst == inst_ebreak) {
if (cpu.GPRs(10) == 1) return TypeEnv{ .ebreak = 1, .ret = cpu.GPRs(10), .halt = 1 } else return TypeEnv{ .ebreak = 1, .ret = cpu.GPRs(10), .halt = 0 };
}
return TypeEnv{ .ebreak = 0, .ret = cpu.GPRs(10), .halt = 0 };
}
};

pub const Instruction = union(enum) {
addi: TypeI,
ebreak: TypeEnv,

pub fn decode_operand(s: *Decode, dest: *word_t, src1: *word_t, src2: *word_t, inst_type: *word_t, imm: *word_t) void {
const i: u32 = s.*.inst;
const rd: u32 = BITS(i, 11, 7);
const rs1: u32 = BITS(i, 19, 15);
const rs2: u32 = BITS(i, 24, 20);
const opcode: u32 = BITS(i, 6, 0);
const imm_i: u32 = BITS(i, 31, 20);
dest.* = rd;
src1.* = rs1;
src2.* = rs2;
inst_type.* = opcode;
imm.* = imm_i;
}
pub fn DecodePattern(op: anytype, val: anytype) Instruction {
return @unionInit(Instruction, @tagName(op), val); // Return the union with the tag name of the operation and the value
}

test "decode_operand" {
var s: Decode = undefined;
s.inst = 0x00000033;
var dest: word_t = undefined;
var src1: word_t = undefined;
var src2: word_t = undefined;
var opcode: word_t = undefined;
decode_operand(&s, &dest, &src1, &src2, &opcode);
print("dest: {}, src1: {}, src2: {}, opcode: {}\n", .{ dest, src1, src2, opcode });
try testing.expect(dest == 0);
try testing.expect(src1 == 0);
try testing.expect(src2 == 0);
try testing.expect(opcode == 51);
}
pub fn decode32(inst: u32) anyerror!Instruction {
const opcode: u32 = utils.BITS(inst, 6, 0);
return switch (opcode) {
0b0010011 => DecodePattern(.addi, TypeI.decode(inst)),
0b1110011 => DecodePattern(.ebreak, TypeEnv.decode(inst)),
else => unreachable,
};
}
};
52 changes: 21 additions & 31 deletions src/cpu/exu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,35 @@ const std = @import("std");

const M = @import("../mem.zig").MEM;
const c = @import("cpu.zig");
const Decode = @import("decode.zig").Decode;
const decode = @import("decode.zig").decode_operand;
const decode = @import("decode.zig");
const word_t = @import("../arch/rv64.zig").word_t;
const print = @import("../common.zig").print;
const print = @import("../util.zig").print;
const ifu = @import("ifu.zig");
const isa = @import("../arch/rv64.zig");

var halt = false;

pub fn exu_cycle() void {
const inst: u32 = ifu.inst_fetch(c.cpu.pc, &M.memory);
var s: Decode = undefined;
s.inst = inst;
var dest: word_t = undefined;
var src1: word_t = undefined;
var src2: word_t = undefined;
var opcode: word_t = undefined;
var imm_i: word_t = undefined;
decode(&s, &dest, &src1, &src2, &opcode, &imm_i);
const nrZero: bool = if (dest != 0) true else false;
const addi: bool = if ((inst & 0x7f) == 0x13 and ((inst >> 12 & 0x7)) == 0) true else false;
const ebreak: bool = if ((inst & 0x00100073) != 0) true else false;
if (addi) {
if (nrZero) {
c.setGPRs(@intCast(dest), c.cpu.gprs[src1] + imm_i);
}
} else if (ebreak) {
if (c.cpu.gprs[10] == 0) {
const out: u8 = @intCast(c.cpu.gprs[11] & 0xff);
print("{c}", .{out});
} else if (c.cpu.gprs[10] == 1) {
halt = true;
} else {
print("Unsupported ebreak command\n", .{});
}
} else {
print("Unsupported instruction\n", .{});
}
var failed: anyerror = undefined;
const inst_test: ?decode.Instruction = decode.Instruction.decode32(inst) catch |err| {
failed = err;
return;
};
const exu = isa.inst2exu(inst_test.?);
const ret = exu(inst_test.?);
_ = ret;
}

pub fn isHalt() bool {
pub fn ishalt() bool {
return halt;
}

pub fn setState(x: bool) void {
if (x) {
halt = true;
} else {
halt = false;
}
return;
}
2 changes: 1 addition & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

const std = @import("std");
const c = @import("cpu/cpu.zig");
const halt = @import("cpu/exu.zig").isHalt;
const halt = @import("cpu/exu.zig").ishalt;
const initMemory = @import("mem.zig").initMem;

pub const reg_display = @import("cpu/reg.zig").reg_display;
Expand Down
13 changes: 13 additions & 0 deletions src/util.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,16 @@ pub const print = std.debug.print;
pub fn putchar(c: u8) void {
std.os.write(std.os.Stdout, &c, 1);
}

pub inline fn CONCACT(a: u32, b: u32) u64 {
return @intCast(a << 32 | b);
}

pub fn BITSMASK(hi: u5, lo: u5) u32 {
return ((@as(u32, 1) << (hi - lo + 1)) - 1) << lo;
}

pub fn BITS(x: u32, hi: u5, lo: u5) u32 {
const mask = BITSMASK(hi, lo);
return (x & mask) >> @intCast(lo);
}

0 comments on commit 9124788

Please sign in to comment.