Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add adapter module for bus #566

Merged
merged 12 commits into from
Jan 29, 2024
23 changes: 15 additions & 8 deletions coreblocks/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from transactron.core import Transaction, TModule
from transactron.lib import FIFO, ConnectTrans
from coreblocks.params.layouts import *
from coreblocks.params.keys import BranchResolvedKey, GenericCSRRegistersKey, InstructionPrecommitKey, WishboneDataKey
from coreblocks.params.keys import BranchResolvedKey, GenericCSRRegistersKey, InstructionPrecommitKey, CommonBusDataKey
from coreblocks.params.genparams import GenParams
from coreblocks.params.isa import Extension
from coreblocks.frontend.decode import Decode
Expand All @@ -19,7 +19,8 @@
from coreblocks.scheduler.scheduler import Scheduler
from coreblocks.stages.backend import ResultAnnouncement
from coreblocks.stages.retirement import Retirement
from coreblocks.frontend.icache import ICache, SimpleWBCacheRefiller, ICacheBypass
from coreblocks.frontend.icache import ICache, SimpleCommonBusCacheRefiller, ICacheBypass
from coreblocks.peripherals.bus_adapter import WishboneMasterAdapter
from coreblocks.peripherals.wishbone import WishboneMaster, WishboneBus
from coreblocks.frontend.fetch import Fetch, UnalignedFetch
from transactron.lib.transformers import MethodMap, MethodProduct
Expand All @@ -38,6 +39,9 @@ def __init__(self, *, gen_params: GenParams, wb_instr_bus: WishboneBus, wb_data_
self.wb_master_instr = WishboneMaster(self.gen_params.wb_params)
self.wb_master_data = WishboneMaster(self.gen_params.wb_params)

self.bus_master_instr_adapter = WishboneMasterAdapter(self.wb_master_instr)
self.bus_master_data_adapter = WishboneMasterAdapter(self.wb_master_data)

self.core_counter = CoreInstructionCounter(self.gen_params)

# make fetch_continue visible outside the core for injecting instructions
Expand All @@ -55,20 +59,20 @@ def __init__(self, *, gen_params: GenParams, wb_instr_bus: WishboneBus, wb_data_

cache_layouts = self.gen_params.get(ICacheLayouts)
if gen_params.icache_params.enable:
self.icache_refiller = SimpleWBCacheRefiller(
cache_layouts, self.gen_params.icache_params, self.wb_master_instr
self.icache_refiller = SimpleCommonBusCacheRefiller(
cache_layouts, self.gen_params.icache_params, self.bus_master_instr_adapter
)
self.icache = ICache(cache_layouts, self.gen_params.icache_params, self.icache_refiller)
else:
self.icache = ICacheBypass(cache_layouts, gen_params.icache_params, self.wb_master_instr)
self.icache = ICacheBypass(cache_layouts, gen_params.icache_params, self.bus_master_instr_adapter)

self.FRAT = FRAT(gen_params=self.gen_params)
self.RRAT = RRAT(gen_params=self.gen_params)
self.RF = RegisterFile(gen_params=self.gen_params)
self.ROB = ReorderBuffer(gen_params=self.gen_params)

connections = gen_params.get(DependencyManager)
connections.add_dependency(WishboneDataKey(), self.wb_master_data)
connections.add_dependency(CommonBusDataKey(), self.bus_master_data_adapter)

self.exception_cause_register = ExceptionCauseRegister(self.gen_params, rob_get_indices=self.ROB.get_indices)

Expand All @@ -94,12 +98,15 @@ def __init__(self, *, gen_params: GenParams, wb_instr_bus: WishboneBus, wb_data_
def elaborate(self, platform):
m = TModule()

m.d.comb += self.wb_master_instr.wbMaster.connect(self.wb_instr_bus)
m.d.comb += self.wb_master_data.wbMaster.connect(self.wb_data_bus)
m.d.comb += self.wb_master_instr.wb_master.connect(self.wb_instr_bus)
m.d.comb += self.wb_master_data.wb_master.connect(self.wb_data_bus)

m.submodules.wb_master_instr = self.wb_master_instr
m.submodules.wb_master_data = self.wb_master_data

m.submodules.bus_master_instr_adapter = self.bus_master_instr_adapter
m.submodules.bus_master_data_adapter = self.bus_master_data_adapter

m.submodules.free_rf_fifo = free_rf_fifo = self.free_rf_fifo
m.submodules.FRAT = frat = self.FRAT
m.submodules.RRAT = rrat = self.RRAT
Expand Down
30 changes: 13 additions & 17 deletions coreblocks/frontend/icache.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from transactron.utils import assign, OneHotSwitchDynamic
from transactron.utils._typing import HasElaborate
from transactron.lib import *
from coreblocks.peripherals.wishbone import WishboneMaster
from coreblocks.peripherals.bus_adapter import BusMasterInterface


__all__ = ["ICache", "ICacheBypass", "ICacheInterface", "SimpleWBCacheRefiller"]
__all__ = ["ICache", "ICacheBypass", "ICacheInterface", "SimpleCommonBusCacheRefiller"]


def extract_instr_from_word(m: TModule, params: ICacheParameters, word: Signal, addr: Value):
Expand Down Expand Up @@ -67,9 +67,9 @@ class CacheRefillerInterface(HasElaborate, Protocol):


class ICacheBypass(Elaboratable, ICacheInterface):
def __init__(self, layouts: ICacheLayouts, params: ICacheParameters, wb_master: WishboneMaster) -> None:
def __init__(self, layouts: ICacheLayouts, params: ICacheParameters, bus_master: BusMasterInterface) -> None:
self.params = params
self.wb_master = wb_master
self.bus_master = bus_master

self.issue_req = Method(i=layouts.issue_req)
self.accept_res = Method(o=layouts.accept_res)
Expand All @@ -83,17 +83,15 @@ def elaborate(self, platform):
@def_method(m, self.issue_req)
def _(addr: Value) -> None:
m.d.sync += req_addr.eq(addr)
self.wb_master.request(
self.bus_master.request_read(
m,
addr=addr >> log2_int(self.params.word_width_bytes),
data=0,
we=0,
sel=C(1).replicate(self.wb_master.wb_params.data_width // self.wb_master.wb_params.granularity),
sel=C(1).replicate(self.bus_master.params.data_width // self.bus_master.params.granularity),
)

@def_method(m, self.accept_res)
def _():
res = self.wb_master.result(m)
res = self.bus_master.get_read_response(m)
return {
"instr": extract_instr_from_word(m, self.params, res.data, req_addr),
"error": res.err,
Expand Down Expand Up @@ -367,10 +365,10 @@ def elaborate(self, platform):
return m


class SimpleWBCacheRefiller(Elaboratable, CacheRefillerInterface):
def __init__(self, layouts: ICacheLayouts, params: ICacheParameters, wb_master: WishboneMaster):
class SimpleCommonBusCacheRefiller(Elaboratable, CacheRefillerInterface):
def __init__(self, layouts: ICacheLayouts, params: ICacheParameters, bus_master: BusMasterInterface):
self.params = params
self.wb_master = wb_master
self.bus_master = bus_master

self.start_refill = Method(i=layouts.start_refill)
self.accept_refill = Method(o=layouts.accept_refill)
Expand All @@ -388,12 +386,10 @@ def elaborate(self, platform):

with Transaction().body(m):
address = address_fwd.read(m)
self.wb_master.request(
self.bus_master.request_read(
m,
addr=Cat(address["word_counter"], address["refill_address"]),
data=0,
we=0,
sel=C(1).replicate(self.wb_master.wb_params.data_width // self.wb_master.wb_params.granularity),
sel=C(1).replicate(self.bus_master.params.data_width // self.bus_master.params.granularity),
)

@def_method(m, self.start_refill, ready=~refill_active)
Expand All @@ -407,7 +403,7 @@ def _(addr) -> None:

@def_method(m, self.accept_refill, ready=refill_active)
def _():
fetched = self.wb_master.result(m)
fetched = self.bus_master.get_read_response(m)

last = (word_counter == (self.params.words_in_block - 1)) | fetched.err

Expand Down
56 changes: 36 additions & 20 deletions coreblocks/lsu/dummyLsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

from transactron import Method, def_method, Transaction, TModule
from coreblocks.params import *
from coreblocks.peripherals.wishbone import WishboneMaster
from coreblocks.peripherals.bus_adapter import BusMasterInterface
from transactron.lib.connectors import Forwarder
from transactron.utils import assign, ModuleLike, DependencyManager
from coreblocks.utils.protocols import FuncBlock
from transactron.lib.simultaneous import condition

from coreblocks.lsu.pma import PMAChecker

__all__ = ["LSUDummy", "LSUBlockComponent"]


class LSURequesterWB(Elaboratable):
class LSURequester(Elaboratable):
"""
Wishbone request logic for the load/store unit. Its job is to interface
between the LSU and the Wishbone bus.
Bus request logic for the load/store unit. Its job is to interface
between the LSU and the bus.

Attributes
----------
Expand All @@ -25,14 +26,14 @@ class LSURequesterWB(Elaboratable):
Retrieves a result from the bus.
"""

def __init__(self, gen_params: GenParams, bus: WishboneMaster) -> None:
def __init__(self, gen_params: GenParams, bus: BusMasterInterface) -> None:
"""
Parameters
----------
gen_params : GenParams
Parameters to be used during processor generation.
bus : WishboneMaster
An instance of the Wishbone master for interfacing with the data bus.
bus : BusMasterInterface
An instance of the bus master for interfacing with the data bus.
"""
self.gen_params = gen_params
self.bus = bus
Expand All @@ -43,7 +44,7 @@ def __init__(self, gen_params: GenParams, bus: WishboneMaster) -> None:
self.accept = Method(o=lsu_layouts.accept)

def prepare_bytes_mask(self, m: ModuleLike, funct3: Value, addr: Value) -> Signal:
mask_len = self.gen_params.isa.xlen // self.bus.wb_params.granularity
mask_len = self.gen_params.isa.xlen // self.bus.params.granularity
mask = Signal(mask_len)
with m.Switch(funct3):
with m.Case(Funct3.B, Funct3.BU):
Expand Down Expand Up @@ -112,10 +113,17 @@ def _(addr: Value, data: Value, funct3: Value, store: Value):

aligned = self.check_align(m, funct3, addr)
bytes_mask = self.prepare_bytes_mask(m, funct3, addr)
wb_data = self.prepare_data_to_save(m, funct3, data, addr)
bus_data = self.prepare_data_to_save(m, funct3, data, addr)

with condition(m, nonblocking=False, priority=False) as branch:
with branch(aligned & store):
self.bus.request_write(m, addr=addr >> 2, data=bus_data, sel=bytes_mask)
with branch(aligned & ~store):
self.bus.request_read(m, addr=addr >> 2, sel=bytes_mask)
with branch(~aligned):
pass

with m.If(aligned):
self.bus.request(m, addr=addr >> 2, we=store, sel=bytes_mask, data=wb_data)
m.d.sync += request_sent.eq(1)
m.d.sync += addr_reg.eq(addr)
m.d.sync += funct3_reg.eq(funct3)
Expand All @@ -130,15 +138,23 @@ def _(addr: Value, data: Value, funct3: Value, store: Value):

@def_method(m, self.accept, request_sent)
def _():
data = Signal(self.gen_params.isa.xlen)
exception = Signal()
cause = Signal(ExceptionCause)
err = Signal()

fetched = self.bus.result(m)
m.d.sync += request_sent.eq(0)
with condition(m, nonblocking=False, priority=False) as branch:
with branch(store_reg):
fetched = self.bus.get_write_response(m)
err = fetched.err
with branch(~store_reg):
fetched = self.bus.get_read_response(m)
err = fetched.err
data = self.postprocess_load_data(m, funct3_reg, fetched.data, addr_reg)

data = self.postprocess_load_data(m, funct3_reg, fetched.data, addr_reg)
m.d.sync += request_sent.eq(0)

with m.If(fetched.err):
with m.If(err):
m.d.av_comb += exception.eq(1)
m.d.av_comb += cause.eq(
Mux(store_reg, ExceptionCause.STORE_ACCESS_FAULT, ExceptionCause.LOAD_ACCESS_FAULT)
Expand Down Expand Up @@ -172,14 +188,14 @@ class LSUDummy(FuncBlock, Elaboratable):
Used to inform LSU that new instruction is ready to be retired.
"""

def __init__(self, gen_params: GenParams, bus: WishboneMaster) -> None:
def __init__(self, gen_params: GenParams, bus: BusMasterInterface) -> None:
"""
Parameters
----------
gen_params : GenParams
Parameters to be used during processor generation.
bus : WishboneMaster
An instance of the Wishbone master for interfacing with the data bus.
bus : BusMasterInterface
An instance of the bus master for interfacing with the data bus.
"""

self.gen_params = gen_params
Expand Down Expand Up @@ -207,7 +223,7 @@ def elaborate(self, platform):
current_instr = Record(self.lsu_layouts.rs.data_layout)

m.submodules.pma_checker = pma_checker = PMAChecker(self.gen_params)
m.submodules.requester = requester = LSURequesterWB(self.gen_params, self.bus)
m.submodules.requester = requester = LSURequester(self.gen_params, self.bus)

m.submodules.results = results = self.forwarder = Forwarder(self.lsu_layouts.accept)

Expand Down Expand Up @@ -303,8 +319,8 @@ def _(rob_id: Value, side_fx: Value):
class LSUBlockComponent(BlockComponentParams):
def get_module(self, gen_params: GenParams) -> FuncBlock:
connections = gen_params.get(DependencyManager)
wb_master = connections.get_dependency(WishboneDataKey())
unit = LSUDummy(gen_params, wb_master)
bus_master = connections.get_dependency(CommonBusDataKey())
unit = LSUDummy(gen_params, bus_master)
connections.add_dependency(InstructionPrecommitKey(), unit.precommit)
return unit

Expand Down
6 changes: 3 additions & 3 deletions coreblocks/params/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from transactron.lib.dependencies import SimpleKey, UnifierKey
from transactron import Method
from transactron.lib import MethodTryProduct, Collector
from coreblocks.peripherals.wishbone import WishboneMaster
from coreblocks.peripherals.bus_adapter import BusMasterInterface
from amaranth import Signal

if TYPE_CHECKING:
from coreblocks.structs_common.csr_generic import GenericCSRRegisters # noqa: F401

__all__ = [
"WishboneDataKey",
"CommonBusDataKey",
"InstructionPrecommitKey",
"BranchResolvedKey",
"ExceptionReportKey",
Expand All @@ -22,7 +22,7 @@


@dataclass(frozen=True)
class WishboneDataKey(SimpleKey[WishboneMaster]):
class CommonBusDataKey(SimpleKey[BusMasterInterface]):
pass


Expand Down
6 changes: 3 additions & 3 deletions coreblocks/peripherals/axi_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AXILiteParameters:
def __init__(self, *, data_width: int = 64, addr_width: int = 64):
self.data_width = data_width
self.addr_width = addr_width
self.granularity = 8


class AXILiteLayout:
Expand Down Expand Up @@ -174,6 +175,8 @@ class AXILiteMaster(Elaboratable):

def __init__(self, axil_params: AXILiteParameters):
self.axil_params = axil_params
self.axil_layout = AXILiteLayout(self.axil_params).axil_layout
self.axil_master = Record(self.axil_layout)

self.method_layouts = AXILiteMasterMethodLayouts(self.axil_params)

Expand Down Expand Up @@ -223,9 +226,6 @@ def result_handler(self, m: TModule, forwarder: Forwarder, *, data: bool, channe
def elaborate(self, platform):
m = TModule()

self.axil_layout = AXILiteLayout(self.axil_params).axil_layout
self.axil_master = Record(self.axil_layout)

m.submodules.rd_forwarder = rd_forwarder = Forwarder(self.method_layouts.rd_response_layout)
m.submodules.wr_forwarder = wr_forwarder = Forwarder(self.method_layouts.wr_response_layout)

Expand Down
Loading
Loading