from nmigen import * class rvfi_insn_auipc(Elaboratable): def __init__(self, RISCV_FORMAL_ILEN=32, RISCV_FORMAL_XLEN=32, RISCV_FORMAL_CSR_MISA=False): self.RISCV_FORMAL_ILEN = RISCV_FORMAL_ILEN self.RISCV_FORMAL_XLEN = RISCV_FORMAL_XLEN self.RISCV_FORMAL_CSR_MISA = RISCV_FORMAL_CSR_MISA self.rvfi_valid = Signal(1) self.rvfi_insn = Signal(self.RISCV_FORMAL_ILEN) self.rvfi_pc_rdata = Signal(self.RISCV_FORMAL_XLEN) self.rvfi_rs1_rdata = Signal(self.RISCV_FORMAL_XLEN) self.rvfi_rs2_rdata = Signal(self.RISCV_FORMAL_XLEN) self.rvfi_mem_rdata = Signal(self.RISCV_FORMAL_XLEN) if self.RISCV_FORMAL_CSR_MISA: self.rvfi_csr_misa_rdata = Signal(self.RISCV_FORMAL_XLEN) self.spec_csr_misa_rmask = Signal(self.RISCV_FORMAL_XLEN) self.spec_valid = Signal(1) self.spec_trap = Signal(1) self.spec_rs1_addr = Signal(5) self.spec_rs2_addr = Signal(5) self.spec_rd_addr = Signal(5) self.spec_rd_wdata = Signal(self.RISCV_FORMAL_XLEN) self.spec_pc_wdata = Signal(self.RISCV_FORMAL_XLEN) self.spec_mem_addr = Signal(self.RISCV_FORMAL_XLEN) self.spec_mem_rmask = Signal(int(self.RISCV_FORMAL_XLEN // 8)) self.spec_mem_wmask = Signal(int(self.RISCV_FORMAL_XLEN // 8)) self.spec_mem_wdata = Signal(self.RISCV_FORMAL_XLEN) def ports(self): input_ports = [ self.rvfi_valid, self.rvfi_insn, self.rvfi_pc_rdata, self.rvfi_rs1_rdata, self.rvfi_rs2_rdata, self.rvfi_mem_rdata ] output_ports = [ self.spec_valid, self.spec_trap, self.spec_rs1_addr, self.spec_rs2_addr, self.spec_rd_addr, self.spec_rd_wdata, self.spec_pc_wdata, self.spec_mem_addr, self.spec_mem_rmask, self.spec_mem_wmask, self.spec_mem_wdata ] if self.RISCV_FORMAL_CSR_MISA: input_ports.append(self.rvfi_csr_misa_rdata) output_ports.append(self.spec_csr_misa_rmask) return input_ports + output_ports def elaborate(self, platform): m = Module() # U-type instruction format insn_padding = Signal(self.RISCV_FORMAL_ILEN) m.d.comb += insn_padding.eq(self.rvfi_insn >> 32) insn_imm = Signal(self.RISCV_FORMAL_XLEN) m.d.comb += insn_imm.eq(Value.as_signed(self.rvfi_insn[12:32] << 12)) insn_rd = Signal(5) m.d.comb += insn_rd.eq(self.rvfi_insn[7:12]) insn_opcode = Signal(7) m.d.comb += insn_opcode.eq(self.rvfi_insn[:7]) misa_ok = Signal(1) if self.RISCV_FORMAL_CSR_MISA: m.d.comb += misa_ok.eq((self.rvfi_csr_misa_rdata & 0) == 0) m.d.comb += self.spec_csr_misa_rmask.eq(0) else: m.d.comb += misa_ok.eq(1) # AUIPC instruction m.d.comb += self.spec_valid.eq(self.rvfi_valid & (~insn_padding) & (insn_opcode == 0b0010111)) m.d.comb += self.spec_rd_addr.eq(insn_rd) m.d.comb += self.spec_rd_wdata.eq(Mux(self.spec_rd_addr, self.rvfi_pc_rdata + insn_imm, 0)) m.d.comb += self.spec_pc_wdata.eq(self.rvfi_pc_rdata + 4) # default assignments m.d.comb += self.spec_rs1_addr.eq(0) m.d.comb += self.spec_rs2_addr.eq(0) m.d.comb += self.spec_trap.eq(~misa_ok) m.d.comb += self.spec_mem_addr.eq(0) m.d.comb += self.spec_mem_rmask.eq(0) m.d.comb += self.spec_mem_wmask.eq(0) m.d.comb += self.spec_mem_wdata.eq(0) return m