runt/instruction_decoder.py
David Lenfesty e850430a8c """Finished""" base RV32I instructions
Still a few base instructions to go, but those are waiting on the
privileged implementation. My game plan:

- implement privileged spec (M-only), adding way to handle traps
- finish implementing last of the base instructions
- add in exceptions that have been ignored in all instructions
- clean up main memory interface, mmaybe add some caching, at least some
  instruction cache.
2021-05-29 19:42:11 -06:00

79 lines
3.2 KiB
Python

from nmigen import *
from opcodes import Opcodes
class InstructionDecoder(Elaboratable):
def __init__(self):
#### Input
self.instr = Signal(unsigned(32))
#### Output
self.opcode = Signal(Opcodes)
self.funct3 = Signal(unsigned(3))
self.funct7 = Signal(unsigned(7))
self.imm = Signal(32)
self.immu = Signal(unsigned(32))
# Register selection
self.src1 = Signal(unsigned(5))
self.src2 = Signal(unsigned(5))
self.dest = Signal(unsigned(5))
self.base = Signal(unsigned(5))
def ports(self) -> tuple:
return (self.instr, self.opcode, self.funct3, self.imm, self.immu, self.src1, self.dest, self.base)
def elaborate(self, platform):
m = Module()
m.d.comb += self.opcode.eq(self.instr[0:6])
# Default immediate to 0 whenever we can
m.d.comb += self.imm.eq(0)
m.d.comb += self.immu.eq(0)
m.d.comb += self.dest.eq(self.instr[7:11]) # TODO will likely move back into the switch
with m.Switch(self.opcode):
# I-Type Instructions
with m.Case(Opcodes.OP_IMM, Opcodes.JALR, Opcodes.LOAD, Opcodes.MISC_MEM):
# TODO does this sign-extend?
m.d.comb += self.imm.eq(self.instr[20:31].as_signed())
m.d.comb += self.immu.eq(self.instr[20:31])
m.d.comb += self.funct3.eq(self.instr[12:14])
m.d.comb += self.src1.eq(self.instr[15:19])
# U-Type Instructions
with m.Case(Opcodes.LUI, Opcodes.AUIPC):
m.d.comb += self.imm[12:31].eq(self.instr[12:31].as_signed())
m.d.comb += self.immu[12:31].eq(self.instr[12:31])
# R-Type Instructions
with m.Case(Opcodes.OP):
m.d.comb += self.funct3.eq(self.instr[12:14])
m.d.comb += self.funct7.eq(self.instr[25:31])
m.d.comb += self.src1.eq(self.instr[15:19])
m.d.comb += self.src2.eq(self.instr[20:24])
# J-Type Instructions
with m.Case(Opcodes.JAL):
imm = Cat(Const(0, shape=1), self.instr[21:30], self.instr[20], self.instr[12:19], self.instr[31])
m.d.comb += self.imm.eq(imm.as_signed())
m.d.comb += self.immu.eq(imm.as_unsigned())
# B-Type Instructions
with m.Case(Opcodes.BRANCH):
imm = Cat(Const(0, shape=1), self.instr[8:11], self.instr[25:30], self.instr[7], self.instr[31])
m.d.comb += self.imm.eq(imm.as_signed())
m.d.comb += self.immu.eq(imm.as_unsigned())
m.d.comb += self.funct3.eq(self.instr[12:14])
m.d.comb += self.src1.eq(self.instr[15:19])
m.d.comb += self.src2.eq(self.instr[20:24])
# S-Type Instructions
with m.Case(Opcodes.STORE):
m.d.comb += self.funct3.eq(self.instr[12:14])
m.d.comb += self.base.eq(self.instr[15:19])
m.d.comb += self.src1.eq(self.instr[20:24])
m.d.comb += self.imm.eq(Cat(self.instr[7:11], self.instr[25:31]).as_signed())
m.d.comb += self.immu.eq(Cat(self.instr[7:11], self.instr[25:31]).as_unsigned())
return m