From 681036ddc3891904f13c84197cd90e2472cb3e1c Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Fri, 23 Jul 2021 20:49:14 +0200 Subject: Change folder name --- pyscv/InstructionSets/RV32I.py | 466 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 pyscv/InstructionSets/RV32I.py (limited to 'pyscv/InstructionSets/RV32I.py') diff --git a/pyscv/InstructionSets/RV32I.py b/pyscv/InstructionSets/RV32I.py new file mode 100644 index 0000000..3fa02ad --- /dev/null +++ b/pyscv/InstructionSets/RV32I.py @@ -0,0 +1,466 @@ +from .instructions import Instruction, InstructionSet +from ctypes import c_uint32 + +RV32I = InstructionSet() + +class R(Instruction): + funct3 = None + funct7 = None + opcode = None + def __init__(self, rd, rs1, rs2): + self.rd = rd + self.rs1 = rs1 + self.rs2 = rs2 + + def compile(self): + # TODO: ensure sizes and convert register names to number... + return c_uint32( + (self.funct7 << 25) +\ + (self.rs2 << 20) +\ + (self.rs1 << 15) +\ + (self.funct3 << 12) +\ + (self.rd << 7) +\ + self.opcode + ) + +class I(Instruction): + funct3 = None + opcode = None + + def __init__(self, rd, rs, imm): + self.rd = rd + self.rs = rs + self.imm = imm + + def compile(self): + return c_uint32( + (self.imm << 20) +\ + (self.rs << 15) +\ + (self.funct3 << 12) +\ + (self.rd << 7) +\ + self.opcode + ) + +class S(Instruction): + funct3 = None + opcode = None + + def __init__(self, rs1, rs2, imm): + self.rs1 = rs1 + self.rs2 = rs2 + self.imm = imm + + def compile(self): + imm_0_4 = self.imm & 0x1F + imm_5_11 = (self.imm & 0xFE0)>>5 + return c_uint32( + (imm_5_11 << 25) +\ + (self.rs1 << 20) +\ + (self.rs2 << 15) +\ + (self.funct3 << 12) +\ + (imm_0_4 << 7) +\ + self.opcode + ) + +class B(Instruction): + funct3 = None + opcode = None + + def __init__(self, rs1, rs2, imm): + self.rs1 = rs1 + self.rs2 = rs2 + self.imm = imm + + def compile(self): + # NOTE: The lowest bit of the imm is always 0 because instructions + # are at least 16 bits wide, so it's not used, that's why this + # instruction looks that weird + imm_12 = (self.imm & 0b1000000000000)>>12 + imm_11 = (self.imm & 0b0100000000000)>>11 + imm_5_10 = (self.imm & 0b0011111100000)>>5 + imm_1_4 = (self.imm & 0b0000000011110)>>1 + return c_uint32( + (imm_12 << 31) +\ + (imm_5_10 << 25) +\ + (self.rs2 << 20) +\ + (self.rs1 << 15) +\ + (self.funct3 << 12) +\ + (imm_1_4 << 8) +\ + (imm_11 << 7) +\ + self.opcode + ) + + def patch(imm): + self.imm = imm + + +class U(Instruction): + opcode = None + def __init__(self, rd, imm): + self.rd = rd + self.imm = imm + + def compile(self): + # NOTE: U Type is for AUIPC and LUI that only use the high part of the + # immediate + imm_12_32 = (self.imm & 0xFFFFF000)>>12 + return c_uint32( + (imm_12_32 << 12) +\ + (self.rd << 7) +\ + self.opcode + ) + +class J(Instruction): + opcode = None + + def __init__(self, rd, imm): + self.rd = rd + self.imm = imm + + def compile(self): + # NOTE: Jumps are also weird + imm_20 = (self.imm & 0x100000)>>20 + imm_12_19 = (self.imm & 0x0FF000)>>12 + imm_11 = (self.imm & 0x000800)>>11 + imm_1_10 = (self.imm & 0x0007FE)>>1 + return c_uint32( + (imm_20 << 31) +\ + (imm_1_10 << 21) +\ + (imm_11 << 20) +\ + (imm_12_19 << 12) +\ + (self.rd << 7) +\ + self.opcode + ) + + def patch(imm): + self.imm = imm + + + +@RV32I.instruction +class lui(U): + name = "lui" + opcode = 0b0110111 + +@RV32I.instruction +class auipc(U): + name = "auipc" + opcode = 0b0010111 + +@RV32I.instruction +class jal(J): + name = "jal" + opcode = 0b1101111 + + def execute(self, pc): + # TODO + # - Save current pc in rd + # - Make pc from `imm` + # - Return new pc + return pc + +@RV32I.instruction +class jalr(I): + name = "jalr" + opcode = 0b1100111 + funct3 = 0b000 + +@RV32I.instruction +class beq(B): + name = "beq" + opcode = 0b1100011 + funct3 = 0b000 + +@RV32I.instruction +class bne(B): + name = "bne" + opcode = 0b1100011 + funct3 = 0b001 + +@RV32I.instruction +class blt(B): + name = "blt" + opcode = 0b1100011 + funct3 = 0b100 + +@RV32I.instruction +class bge(B): + name = "bge" + opcode = 0b1100011 + funct3 = 0b101 + +@RV32I.instruction +class bltu(B): + name = "bltu" + opcode = 0b1100011 + funct3 = 0b110 + +@RV32I.instruction +class bgeu(B): + name = "bgeu" + opcode = 0b1100011 + funct3 = 0b111 + +@RV32I.instruction +class lb(I): + name = "lb" + opcode = 0b0000011 + funct3 = 0b000 + +@RV32I.instruction +class lh(I): + name = "lh" + opcode = 0b0000011 + funct3 = 0b001 + +@RV32I.instruction +class lw(I): + name = "lw" + opcode = 0b0000011 + funct3 = 0b010 + +@RV32I.instruction +class lbu(I): + name = "lbu" + opcode = 0b0000011 + funct3 = 0b100 + +@RV32I.instruction +class lhu(I): + name = "lhu" + opcode = 0b0000011 + funct3 = 0b101 + + +@RV32I.instruction +class sb(S): + name = "sb" + opcode = 0b0100011 + funct3 = 0b000 + +@RV32I.instruction +class sh(S): + name = "sh" + opcode = 0b0100011 + funct3 = 0b001 + +@RV32I.instruction +class sw(S): + name = "sw" + opcode = 0b0100011 + funct3 = 0b010 + +@RV32I.instruction +class addi(I): + name = "addi" + opcode = 0b0010011 + funct3 = 0b000 + + def execute(self, pc): + # TODO + return pc + self.size + +@RV32I.instruction +class slti(I): + name = "slti" + opcode = 0b0010011 + funct3 = 0b010 + +@RV32I.instruction +class sltiu(I): + name = "sltiu" + opcode = 0b0010011 + funct3 = 0b011 + +@RV32I.instruction +class xori(I): + name = "xori" + opcode = 0b0010011 + funct3 = 0b100 + +@RV32I.instruction +class ori(I): + name = "ori" + opcode = 0b0010011 + funct3 = 0b110 + +@RV32I.instruction +class andi(I): + name = "andi" + opcode = 0b0010011 + funct3 = 0b111 + + +class ShiftImm(I): + # NOTE: This is an special type used for shifting operations because they + # have 7 bits left after the maximum shift (5bits -> 32 rotations) + # they can apply. + # In RV64I they can indicate rotation with 1 bit more (64 rotations) so + # they use a funct6 instead. + funct7 = None + funct3 = None + opcode = None + + def __init__(self, rd, rs, imm): + self.rd = rd + self.rs = rs + self.imm = imm + + def compile(self): + return c_uint32( + (self.funct7 << 25) +\ + (self.imm << 20) +\ + (self.rs << 15) +\ + (self.funct3 << 12) +\ + (self.rd << 7) +\ + self.opcode + ) + +@RV32I.instruction +class slli(ShiftImm): + name = "slli" + opcode = 0b0010011 + funct3 = 0b001 + funct7 = 0b0000000 + +@RV32I.instruction +class srli(ShiftImm): + name = "srli" + opcode = 0b0010011 + funct3 = 0b101 + funct7 = 0b0000000 + +@RV32I.instruction +class srai(ShiftImm): + name = "srai" + opcode = 0b0010011 + funct3 = 0b101 + funct7 = 0b0100000 + + +@RV32I.instruction +class add(R): + name = "add" + opcode = 0b0110011 + funct3 = 0b000 + funct7 = 0b0000000 + + def execute(self, pc): + # TODO + return pc + self.size + +@RV32I.instruction +class sub(R): + name = "sub" + opcode = 0b0110011 + funct3 = 0b000 + funct7 = 0b0100000 + +@RV32I.instruction +class sll(R): + name = "sll" + opcode = 0b0110011 + funct3 = 0b001 + funct7 = 0b0000000 + +@RV32I.instruction +class slt(R): + name = "slt" + opcode = 0b0110011 + funct3 = 0b010 + funct7 = 0b0000000 + +@RV32I.instruction +class sltu(R): + name = "sltu" + opcode = 0b0110011 + funct3 = 0b011 + funct7 = 0b0000000 + +@RV32I.instruction +class xor(R): + name = "xor" + opcode = 0b0110011 + funct3 = 0b100 + funct7 = 0b0000000 + +@RV32I.instruction +class srl(R): + name = "srl" + opcode = 0b0110011 + funct3 = 0b101 + funct7 = 0b0000000 + +@RV32I.instruction +class sra(R): + name = "sra" + opcode = 0b0110011 + funct3 = 0b101 + funct7 = 0b0100000 + +@RV32I.instruction +class _or(R): + name = "or" + opcode = 0b0110011 + funct3 = 0b110 + funct7 = 0b0000000 + +@RV32I.instruction +class _and(R): + name = "and" + opcode = 0b0110011 + funct3 = 0b111 + funct7 = 0b0000000 + +@RV32I.instruction +class ecall(I): + name = "ecall" + opcode = 0b1110011 + funct3 = 0b000 + + def __init__(self): + # NOTE: ecall is a I-type instruction but doesn't get any arg and sets + # every field to 0 + self.rd = 0b00000 + self.rs = 0b00000 + self.imm = 0b000000000000 + + +@RV32I.instruction +class ebreak(I): + name = "ebreak" + opcode = 0b1110011 + funct3 = 0b000 + + def __init__(self): + # NOTE: ebreak is a I-type instruction but doesn't get any arg and pre- + # -sets every field to a fixed value + self.rd = 0b00000 + self.rs = 0b00000 + self.imm = 0b000000000001 + + + + + + + + + + + + + + + + +@RV32I.pseudoinstruction +class j(J): + name = "j" + def __new__(cls, imm): + return jal("x0", imm) + + +if __name__ == "__main__": + print(RV32I) + print(RV32I.instructions) -- cgit v1.2.3