Skip to content

Commit

Permalink
units.rvficon: add support for RISC-V CSRs.
Browse files Browse the repository at this point in the history
  • Loading branch information
jfng committed Oct 14, 2024
1 parent 4983734 commit b9fb6d8
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 44 deletions.
15 changes: 9 additions & 6 deletions minerva/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,6 @@ def __init__(self,
"dbus": Out(wishbone.Signature(addr_width=30, data_width=32, granularity=8,
features=("err", "cti", "bte"))),
}
if with_rvfi:
members["rvfi"] = Out(RVFISignature())

# Pipeline stages

Expand Down Expand Up @@ -223,15 +221,20 @@ def __init__(self,
self._multiplier = Multiplier()
self._divider = Divider()

if with_rvfi:
self._rvficon = RVFIController()

# Storage

self._gprf = gpr.RegisterFile()
self._csrf = csr.RegisterFile()

self._csrf.add("exception", self._exception.csr_bank, addr=0x300)
self._csrf.add(self._exception.csr_bank, addr=0x300)

# Verification

if with_rvfi:
self._rvficon = RVFIController(self._csrf.memory_map)
members.update({
"rvfi": Out(RVFISignature(self._csrf.memory_map))
})

super().__init__(members)

Expand Down
8 changes: 8 additions & 0 deletions minerva/csr/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ def __init__(self, shape, *, access, init=0):
def init(self):
return self._init

@property
def w_rvfi_wmask(self):
return (self.port.w_wp_en | self.w_en).replicate(Value.cast(self.port.w_wp_data).width)

@property
def w_rvfi_wdata(self):
return Mux(self.w_en, self.w_data, self.port.w_wp_data)

def elaborate(self, platform):
m = Module()

Expand Down
26 changes: 22 additions & 4 deletions minerva/csr/reg.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ def __init__(self, shape, access, members=()):
**members,
})

@property
def w_rvfi_wmask(self):
return self.port.w_wp_en.replicate(Value.cast(self.port.w_wp_data).width)

@property
def w_rvfi_wdata(self):
return self.port.w_wp_data


class Field:
def __init__(self, action_cls, *args, **kwargs):
Expand Down Expand Up @@ -159,6 +167,18 @@ def field(self):
def f(self):
return self._field

@property
def x_rvfi_rdata(self):
return self.x_rp_data

@property
def w_rvfi_wmask(self):
return Cat(field.w_rvfi_wmask for field_name, field in self)

@property
def w_rvfi_wdata(self):
return Cat(field.w_rvfi_wdata for field_name, field in self)

def __iter__(self):
if isinstance(self._field, FieldAction):
yield None, self._field
Expand Down Expand Up @@ -308,13 +328,11 @@ def memory_map(self):
self._memory_map.freeze()
return self._memory_map

def add(self, name, bank, *, addr):
if not (isinstance(name, str) and name):
raise TypeError(f"Bank name must be a non-empty string, not {name!r}")
def add(self, bank, *, addr):
if not isinstance(bank, RegisterBank):
raise TypeError(f"Bank must be an instance of RegisterBank, not {bank!r}")

self._memory_map.add_window(bank._memory_map, addr=addr, name=name)
self._memory_map.add_window(bank._memory_map, addr=addr, name=("bank", f"{addr:03x}"))
self._banks[bank.memory_map] = bank

def elaborate(self, platform):
Expand Down
107 changes: 73 additions & 34 deletions minerva/units/rvficon.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from amaranth.lib import wiring
from amaranth.lib.wiring import In, Out

from amaranth_soc.memory import MemoryMap

from .. import isa
from .. import csr


__all__ = ["RVFISignature", "RVFIController"]
Expand All @@ -14,8 +17,9 @@
# RISC-V Formal Interface

class RVFISignature(wiring.Signature):
def __init__(self):
super().__init__({
def __init__(self, csr_map):
assert isinstance(csr_map, MemoryMap)
members = {
"valid": Out(1),
"order": Out(64),
"insn": Out(32),
Expand All @@ -40,41 +44,55 @@ def __init__(self):
"mem_wmask": Out(4),
"mem_rdata": Out(32),
"mem_wdata": Out(32),
})
}
for res_info in csr_map.all_resources():
csr_name = res_info.path[-1][0]
members.update({
f"csr_{csr_name}_rmask": Out(32),
f"csr_{csr_name}_wmask": Out(32),
f"csr_{csr_name}_rdata": Out(32),
f"csr_{csr_name}_wdata": Out(32),
})
super().__init__(members)


class RVFIController(wiring.Component):
rvfi: Out(RVFISignature())

d_insn: In(32)
d_rs1_addr: In(5)
d_rs2_addr: In(5)
d_ready: In(1)

x_rs1_rdata: In(32)
x_rs2_rdata: In(32)
x_mem_addr: In(32)
x_mem_wmask: In(4)
x_mem_rmask: In(4)
x_mem_wdata: In(32)
x_mtvec_base: In(30)
x_mepc_base: In(30)
x_ready: In(1)

m_mem_rdata: In(32)
m_fetch_misaligned: In(1)
m_illegal_insn: In(1)
m_load_misaligned: In(1)
m_store_misaligned: In(1)
m_exception: In(1)
m_mret: In(1)
m_branch_taken: In(1)
m_branch_target: In(32)
m_pc_rdata: In(32)
m_ready: In(1)
m_valid: In(1)
w_rd_addr: In(5)
w_rd_wdata: In(32)
def __init__(self, csr_map):
assert isinstance(csr_map, MemoryMap)
self._csr_map = csr_map
super().__init__({
"rvfi": Out(RVFISignature(csr_map)),

"d_insn": In(32),
"d_rs1_addr": In(5),
"d_rs2_addr": In(5),
"d_ready": In(1),

"x_rs1_rdata": In(32),
"x_rs2_rdata": In(32),
"x_mem_addr": In(32),
"x_mem_wmask": In(4),
"x_mem_rmask": In(4),
"x_mem_wdata": In(32),
"x_mtvec_base": In(30),
"x_mepc_base": In(30),
"x_ready": In(1),

"m_mem_rdata": In(32),
"m_fetch_misaligned": In(1),
"m_illegal_insn": In(1),
"m_load_misaligned": In(1),
"m_store_misaligned": In(1),
"m_exception": In(1),
"m_mret": In(1),
"m_branch_taken": In(1),
"m_branch_target": In(32),
"m_pc_rdata": In(32),
"m_ready": In(1),
"m_valid": In(1),
"w_rd_addr": In(5),
"w_rd_wdata": In(32),
})

def elaborate(self, platform):
m = Module()
Expand Down Expand Up @@ -201,4 +219,25 @@ def elaborate(self, platform):
self.rvfi.mem_rdata.eq(self.m_mem_rdata)
]

# CSRs

for res_info in self._csr_map.all_resources():
csr_reg, csr_name = res_info.resource, res_info.path[-1][0]
assert isinstance(csr_reg, csr.Register)

m_csr_rdata = Signal(32, name=f"m_csr_{csr_name}_rdata")
w_csr_rdata = Signal(32, name=f"w_csr_{csr_name}_rdata")

with m.If(self.x_ready):
m.d.sync += m_csr_rdata.eq(csr_reg.x_rvfi_rdata)
with m.If(self.m_ready):
m.d.sync += w_csr_rdata.eq(m_csr_rdata)

m.d.comb += [
getattr(self.rvfi, f"csr_{csr_name}_rmask").eq(Const(1).replicate(32)),
getattr(self.rvfi, f"csr_{csr_name}_rdata").eq(w_csr_rdata),
getattr(self.rvfi, f"csr_{csr_name}_wmask").eq(csr_reg.w_rvfi_wmask),
getattr(self.rvfi, f"csr_{csr_name}_wdata").eq(csr_reg.w_rvfi_wdata),
]

return m

0 comments on commit b9fb6d8

Please sign in to comment.