From 0038f3fff51cc4b7f474af1a5df5dbde551d1d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Mon, 18 Jul 2022 15:09:52 +0200 Subject: [PATCH] Add check for System Call instruction. --- power_fv/check/insn/all.py | 1 + power_fv/check/insn/syscall.py | 9 ++++++ power_fv/insn/const.py | 5 +++ power_fv/insn/field.py | 3 ++ power_fv/insn/spec/syscall.py | 56 ++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 power_fv/check/insn/syscall.py create mode 100644 power_fv/insn/spec/syscall.py diff --git a/power_fv/check/insn/all.py b/power_fv/check/insn/all.py index a30781a..c0f63fc 100644 --- a/power_fv/check/insn/all.py +++ b/power_fv/check/insn/all.py @@ -1,5 +1,6 @@ from .addsub import * from .branch import * +from .syscall import * from .loadstore import * from .cr import * from .compare import * diff --git a/power_fv/check/insn/syscall.py b/power_fv/check/insn/syscall.py new file mode 100644 index 0000000..b0f27ca --- /dev/null +++ b/power_fv/check/insn/syscall.py @@ -0,0 +1,9 @@ +from power_fv.insn import const +from power_fv.insn.spec.syscall import SystemCallSpec +from power_fv.check.insn import InsnCheck + + +__all__ = ["SC"] + + +class SC(InsnCheck, spec_cls=SystemCallSpec, insn_cls=const.SC): pass diff --git a/power_fv/insn/const.py b/power_fv/insn/const.py index b32cd1a..971b37e 100644 --- a/power_fv/insn/const.py +++ b/power_fv/insn/const.py @@ -21,6 +21,11 @@ class BCCTRL (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(5 class BCTAR (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(560), f.LK(0)) class BCTARL (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(560), f.LK(1)) +# System Call + +class SC (WordInsn): _fields = (f.PO(17), f.LEV(), f.SC_30(1)) +class SCV (WordInsn): _fields = (f.PO(17), f.LEV(), f.SC_30(0), f.SC_31(1)) + # Condition Register class CRAND (WordInsn): _fields = (f.PO(19), f.BT(), f.BA(), f.BB(), f.XO_XL(257)) diff --git a/power_fv/insn/field.py b/power_fv/insn/field.py index 3887a04..3be6c0a 100644 --- a/power_fv/insn/field.py +++ b/power_fv/insn/field.py @@ -18,6 +18,7 @@ class D (InsnField): _shape = signed(16); _offset = 16; _name = "D" class d0 (InsnField): _shape = signed(10); _offset = 16; _name = "d0" class d1 (InsnField): _shape = signed( 5); _offset = 11; _name = "d1" class d2 (InsnField): _shape = signed( 1); _offset = 31; _name = "d2" +class LEV (InsnField): _shape = unsigned( 7); _offset = 20; _name = "LEV" class L_D10 (InsnField): _shape = unsigned( 1); _offset = 10; _name = "L" class L_X10 (InsnField): _shape = unsigned( 1); _offset = 10; _name = "L" class L_X15 (InsnField): _shape = unsigned( 1); _offset = 15; _name = "L" @@ -32,6 +33,8 @@ class RB (InsnField): _shape = unsigned( 5); _offset = 16; _name = "RB" class Rc (InsnField): _shape = unsigned( 1); _offset = 31; _name = "Rc" class RS (InsnField): _shape = unsigned( 5); _offset = 6; _name = "RS" class RT (InsnField): _shape = unsigned( 5); _offset = 6; _name = "RT" +class SC_30 (InsnField): _shape = unsigned( 1); _offset = 30; _name = "_30" +class SC_31 (InsnField): _shape = unsigned( 1); _offset = 31; _name = "_31" class SI (InsnField): _shape = signed(16); _offset = 16; _name = "SI" class SH (InsnField): _shape = unsigned( 5); _offset = 16; _name = "SH" class UI (InsnField): _shape = unsigned(16); _offset = 16; _name = "UI" diff --git a/power_fv/insn/spec/syscall.py b/power_fv/insn/spec/syscall.py new file mode 100644 index 0000000..ec20f73 --- /dev/null +++ b/power_fv/insn/spec/syscall.py @@ -0,0 +1,56 @@ +from amaranth import * + +from power_fv import pfv +from power_fv.insn.const import * + +from . import InsnSpec +from .utils import iea + + +__all__ = ["SystemCallSpec"] + + +class SystemCallSpec(InsnSpec, Elaboratable): + def __init__(self, insn): + self.pfv = pfv.Interface() + self.insn = insn + + def elaborate(self, platform): + m = Module() + + m.d.comb += [ + self.pfv.stb .eq(1), + self.pfv.insn.eq(Cat(Const(0, 32), self.insn.as_value())), + self.pfv.msr.r_mask.sf.eq(1), + ] + + if isinstance(self.insn, SC): + def _msr_to_srr1(start, stop): + stmts = [ + self.pfv.msr .r_mask[63-stop:64-start].eq(Repl(1, stop-start+1)), + self.pfv.srr1.w_mask[63-stop:64-start].eq(Repl(1, stop-start+1)), + self.pfv.srr1.w_data[63-stop:64-start].eq(self.pfv.msr.r_data[63-stop:64-start]), + ] + return stmts + + m.d.comb += [ + self.pfv.srr0.w_mask.eq(Repl(1, 64)), + self.pfv.srr0.w_data.eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)), + + self.pfv.srr1.w_mask[63-36:64-33].eq(Repl(1, 4)), + self.pfv.srr1.w_data[63-36:64-33].eq(0), + self.pfv.srr1.w_mask[63-47:64-42].eq(Repl(1, 6)), + self.pfv.srr1.w_data[63-47:64-42].eq(0), + + _msr_to_srr1( 0, 32), + _msr_to_srr1(37, 41), + _msr_to_srr1(48, 63), + + self.pfv.intr.eq(1), + self.pfv.nia .eq(0xc00), + ] + + else: + assert False + + return m