Skip to content

Commit

Permalink
Use a new method to decode instructions (#2)
Browse files Browse the repository at this point in the history
* Add zig to nix flake

* Add direnv

* Update imgfile

* Use a new method to decode instructions

* Remove zig 0.12.0 from ci
  • Loading branch information
Emin017 authored May 10, 2024
1 parent b8f143e commit 47b716e
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 101 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
zig: [ 0.12.0, master ]
zig: [ master ]
os: [ ubuntu-latest]
runs-on: ${{ matrix.os }}
name: Zig ${{ matrix.zig }} on ${{ matrix.os }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.direnv
# zig build output
zig-out/
zig-cache/
Expand Down
70 changes: 69 additions & 1 deletion flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 46 additions & 33 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
{
description = "MEMU";
description = "MEMU";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
zig-overlay.url = "github:mitchellh/zig-overlay";
};

outputs = { self, nixpkgs, flake-utils }@inputs:
flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs { inherit system;};
deps = with pkgs; [
git
gnumake autoconf automake
cmake ninja
pkgsCross.riscv64-embedded.buildPackages.gcc
];
in
{
legacyPackages = pkgs;
devShell = pkgs.mkShell.override { stdenv = pkgs.clangStdenv; } {
buildInputs = deps;
RV64_TOOLCHAIN_ROOT = "${pkgs.pkgsCross.riscv64-embedded.buildPackages.gcc}";
shellHook = ''
export EMU_CC=$RV64_TOOLCHAIN_ROOT/bin/riscv64-none-elf-gcc
export EMU_OBJCOPY=$RV64_TOOLCHAIN_ROOT/bin/riscv64-none-elf-objcopy
make test-img
unset EMU_CC
unset EMU_OBJCOPY
'';
};
}
)
// { inherit inputs;};
outputs = {
self,
zig-overlay,
nixpkgs,
flake-utils,
} @ inputs:
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = import nixpkgs {
inherit system;
overlays = [zig-overlay.overlays.default];
};
deps = with pkgs; [
git
gnumake
autoconf
automake
cmake
ninja
zigpkgs.master
pkgsCross.riscv64-embedded.buildPackages.gcc
];
in {
legacyPackages = pkgs;
formatter = pkgs.alejandra;
devShells.default = pkgs.mkShell.override {stdenv = pkgs.clangStdenv;} {
buildInputs = deps;
RV64_TOOLCHAIN_ROOT = "${pkgs.pkgsCross.riscv64-embedded.buildPackages.gcc}";
shellHook = ''
export EMU_CC=$RV64_TOOLCHAIN_ROOT/bin/riscv64-none-elf-gcc
export EMU_OBJCOPY=$RV64_TOOLCHAIN_ROOT/bin/riscv64-none-elf-objcopy
make test-img
unset EMU_CC
unset EMU_OBJCOPY
'';
};
}
)
// {inherit inputs;};
}
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,
};
}
};
Loading

0 comments on commit 47b716e

Please sign in to comment.