OP_CODE = 1 MISALIGNED_INSTR = 2 from isa import * from units.loadstore import LoadStoreUnit, MemoryUnit, MemoryArbiter, match_load, match_loadstore_unit from units.logic import LogicUnit, match_logic_unit from units.adder import AdderUnit, match_adder_unit from units.shifter import ShifterUnit, match_shifter_unit from units.compare import CompareUnit, match_compare_unit from units.upper import match_lui, match_auipc from units.rvficon import RVFIController, rvfi_layout from common import matcher match_jal = matcher([ (InstrType.JAL, ), ]) match_jalr = matcher([ (InstrType.JALR, Funct3.JALR), ]) match_branch = matcher([ (InstrType.BRANCH, Funct3.BEQ), (InstrType.BRANCH, Funct3.BNE), (InstrType.BRANCH, Funct3.BLT), (InstrType.BRANCH, Funct3.BGE), (InstrType.BRANCH, Funct3.BLTU), (InstrType.BRANCH, Funct3.BGEU), ])
Mux(self.sub, self.src1 - self.src2, self.src1 + self.src2 ) ) with m.If(self.sub): with m.If( (self.src1[-1] != self.src2[-1]) & (self.src1[-1] != self.res[-1]) ): m.d.comb += self.overflow.eq(1) with m.Else(): # add with m.If( (self.src1[-1] == self.src2[-1]) & (self.src1[-1] != self.res[-1]) ): m.d.comb += self.overflow.eq(1) return m from common import matcher from isa import Funct3, Funct7, InstrType match_adder_unit = matcher([ (InstrType.ALU, Funct3.ADD, Funct7.ADD), (InstrType.ALU, Funct3.SUB, Funct7.SUB), (InstrType.OP_IMM, Funct3.ADD), (InstrType.OP_IMM, Funct3.SUB), ])
from common import matcher from isa import Funct3, InstrType match_lui = matcher([ (InstrType.LUI, ), ]) match_auipc = matcher([ (InstrType.AUIPC, ), ])
self.shift = Signal(5, name="shifter_shift") # 5 lowest imm bits self.res = Signal(32, name="shifter_res") self.funct3 = Signal(Funct3) def elaborate(self, platform): # TODO get rid of S{L/R/A}I (because they are the same as S{L/R/A}) m = Module() with m.Switch(self.funct3): with m.Case(Funct3.SLL): # | Funct3.SLLI m.d.comb += self.res.eq(self.src1 << self.shift) with m.Case(Funct3.SRL): # | Funct3.SRLI m.d.comb += self.res.eq(self.src1 >> self.shift) with m.Case(Funct3.SRA): # | Funct3.SRAI m.d.comb += [ self.src1signed.eq(self.src1), self.res.eq(self.src1signed >> self.shift), ] return m from common import matcher match_shifter_unit = matcher([ (InstrType.OP_IMM, Funct3.SLLI, Funct7.SLLI), (InstrType.OP_IMM, Funct3.SRLI, Funct7.SRLI), (InstrType.OP_IMM, Funct3.SRAI, Funct7.SRAI), (InstrType.ALU, Funct3.SRA, Funct7.SRA), (InstrType.ALU, Funct3.SRL, Funct7.SRL), (InstrType.ALU, Funct3.SLL, Funct7.SLL), ])
class LogicUnit(Elaboratable): def __init__(self): self.src1 = Signal(32, name="logic_src1") self.src2 = Signal(32, name="logic_src2") self.res = Signal(32, name="logic_res") self.funct3 = Signal(Funct3) def elaborate(self, platform): m = Module() with m.Switch(self.funct3): with m.Case(Funct3.OR): m.d.comb += self.res.eq(self.src1 | self.src2) with m.Case(Funct3.AND): m.d.comb += self.res.eq(self.src1 & self.src2) with m.Case(Funct3.XOR): m.d.comb += self.res.eq(self.src1 ^ self.src2) return m from common import matcher match_logic_unit = matcher([ (InstrType.ALU, Funct3.OR, 0b0000000), (InstrType.ALU, Funct3.AND, 0b0000000), (InstrType.ALU, Funct3.XOR, 0b0000000), (InstrType.OP_IMM, Funct3.XOR), (InstrType.OP_IMM, Funct3.OR), (InstrType.OP_IMM, Funct3.AND), ])
raise ValueError(f"Negative priority passed! {priority} < 0.") if priority in self.ports: raise ValueError( "Conflicting priority passed to MemoryArbiter.port()") port = self.ports[priority] = Record.like(self.bus, name=f"PORT{priority}") return port from common import matcher from isa import Funct3, InstrType match_load = matcher([ (InstrType.LOAD, Funct3.W), (InstrType.LOAD, Funct3.B), (InstrType.LOAD, Funct3.BU), (InstrType.LOAD, Funct3.H), (InstrType.LOAD, Funct3.HU), ]) match_store = matcher([ (InstrType.STORE, Funct3.W), (InstrType.STORE, Funct3.B), # (InstrType.STORE, Funct3.BU), # it doesn't exist (InstrType.STORE, Funct3.H), # (InstrType.STORE, Funct3.HU), # it doesn't exist ]) match_loadstore_unit = lambda op, f3, f7: match_load(op, f3, f7) | match_store( op, f3, f7)
with m.Case(Funct3.SLT): m.d.comb += self.condition_met.eq(self.negative | self.overflow) with m.Case(Funct3.SLTU): m.d.comb += self.condition_met.eq(self.carry) with m.Case(Funct3.BEQ): m.d.comb += self.condition_met.eq(self.zero) with m.Case(Funct3.BNE): m.d.comb += self.condition_met.eq(~self.zero) with m.Case(Funct3.BLT): m.d.comb += self.condition_met.eq(self.negative ^ self.overflow) with m.Case(Funct3.BGE): m.d.comb += self.condition_met.eq(~(self.negative ^ self.overflow)) with m.Case(Funct3.BLTU): m.d.comb += self.condition_met.eq(self.carry) with m.Case(Funct3.BGEU): m.d.comb += self.condition_met.eq(~self.carry) return m from common import matcher match_compare_unit = matcher([ (InstrType.ALU, Funct3.SLT), (InstrType.ALU, Funct3.SLTU), (InstrType.OP_IMM, Funct3.SLT), (InstrType.OP_IMM, Funct3.SLTU), ])