Skip to content

Commit

Permalink
Merge branch 'master' into zicond
Browse files Browse the repository at this point in the history
  • Loading branch information
piotro888 authored Nov 26, 2024
2 parents 8aba8e6 + 40c82ee commit f12a7a1
Show file tree
Hide file tree
Showing 127 changed files with 2,683 additions and 14,160 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ jobs:
# https://github.com/actions/runner/issues/2033
chown -R $(id -u):$(id -g) $PWD
- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -114,9 +111,6 @@ jobs:
# https://github.com/actions/runner/issues/2033
chown -R $(id -u):$(id -g) $PWD
- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -165,9 +159,6 @@ jobs:
# https://github.com/actions/runner/issues/2033
chown -R $(id -u):$(id -g) $PWD
- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/deploy_gh_pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
15 changes: 0 additions & 15 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -153,9 +150,6 @@ jobs:
git config --global --add safe.directory /__w/coreblocks/coreblocks
git submodule > .gitmodules-hash
- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -263,9 +257,6 @@ jobs:
git config --global --add safe.directory /__w/coreblocks/coreblocks
git submodule > .gitmodules-hash
- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -318,9 +309,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -353,9 +341,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Checkout submodules
run: git submodule update --init --recursive amaranth-stubs

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,3 @@
[submodule "test/external/riscof/riscv-arch-test"]
path = test/external/riscof/riscv-arch-test
url = https://github.com/riscv-non-isa/riscv-arch-test.git
[submodule "amaranth-stubs"]
path = amaranth-stubs
url = https://github.com/kuznia-rdzeni/amaranth-stubs.git
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Coreblocks is an experimental, modular out-of-order [RISC-V](https://riscv.org/s
* Simplicity. Coreblocks is an academic project, accessible to students.
It should be suitable for teaching essentials of out-of-order architectures.
* Modularity. We want to be able to easily experiment with the core by adding, replacing and modifying modules without changing the source too much.
For this goal, we designed a [transaction system](https://kuznia-rdzeni.github.io/coreblocks/Transactions.html) inspired by [Bluespec](http://wiki.bluespec.com/).
For this goal, we designed a transaction system called [Transactron](https://github.com/kuznia-rdzeni/transactron), which is inspired by [Bluespec](http://wiki.bluespec.com/).
* Fine-grained testing. Outside of the integration tests for the full core, modules are tested individually.
This is to support an agile style of development.

Expand All @@ -25,9 +25,6 @@ The core currently supports the full RV32I instruction set and several extension
Exceptions and some of machine-mode CSRs are supported, the support for interrupts is currently rudimentary and incompatible with the RISC-V spec.
Coreblocks can be used with [LiteX](https://github.com/enjoy-digital/litex) (currently using a [patched version](https://github.com/kuznia-rdzeni/litex/tree/coreblocks)).

The transaction system we use as the foundation for the core is well-tested and usable.
We plan to make it available as a separate Python package.

## Documentation

The [documentation for our project](https://kuznia-rdzeni.github.io/coreblocks/) is automatically generated using [Sphinx](https://www.sphinx-doc.org/).
Expand Down
1 change: 0 additions & 1 deletion amaranth-stubs
Submodule amaranth-stubs deleted from c0325b
6 changes: 6 additions & 0 deletions coreblocks/arch/isa_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ class PrivilegeLevel(IntEnum, shape=2):
MACHINE = 0b11


@unique
class TrapVectorMode(IntEnum, shape=2):
DIRECT = 0b00
VECTORED = 0b01


@unique
class InterruptCauseNumber(IntEnum):
SSI = 1 # supervisor software interrupt
Expand Down
31 changes: 24 additions & 7 deletions coreblocks/backend/retirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from coreblocks.arch import ExceptionCause
from coreblocks.interface.keys import CoreStateKey, CSRInstancesKey, InstructionPrecommitKey
from coreblocks.priv.csr.csr_instances import CSRAddress, DoubleCounterCSR
from coreblocks.arch.isa_consts import TrapVectorMode


class Retirement(Elaboratable):
Expand Down Expand Up @@ -55,11 +56,16 @@ def __init__(
max_latency=2 * 2**gen_params.rob_entries_bits,
)

layouts = self.gen_params.get(RetirementLayouts)
self.dependency_manager = DependencyContext.get()
self.core_state = Method(o=self.gen_params.get(RetirementLayouts).core_state, nonexclusive=True)
self.dependency_manager.add_dependency(CoreStateKey(), self.core_state)

self.precommit = Method(o=self.gen_params.get(RetirementLayouts).precommit, nonexclusive=True)
# The argument is only used in argument validation, it is not needed in the method body.
# A dummy combiner is provided.
self.precommit = Method(
i=layouts.precommit_in, o=layouts.precommit_out, nonexclusive=True, combiner=lambda m, args, runs: 0
)
self.dependency_manager.add_dependency(InstructionPrecommitKey(), self.precommit)

def elaborate(self, platform):
Expand Down Expand Up @@ -208,8 +214,17 @@ def flush_instr(rob_entry):
self.perf_trap_latency.stop(m)

handler_pc = Signal(self.gen_params.isa.xlen)
# mtvec without mode is [mxlen-1:2], mode is two last bits. Only direct mode is supported
m.d.av_comb += handler_pc.eq(m_csr.mtvec.read(m).data & ~(0b11))
mtvec_offset = Signal(self.gen_params.isa.xlen)
mtvec_base = m_csr.mtvec_base.read(m).data
mtvec_mode = m_csr.mtvec_mode.read(m).data
mcause = m_csr.mcause.read(m).data

# When mode is Vectored, interrupts set pc to base + 4 * cause_number
with m.If(mcause[-1] & (mtvec_mode == TrapVectorMode.VECTORED)):
m.d.av_comb += mtvec_offset.eq(mcause << 2)

# (mtvec_base stores base[MXLEN-1:2])
m.d.av_comb += handler_pc.eq((mtvec_base << 2) + mtvec_offset)

resume_pc = Mux(continue_pc_override, continue_pc, handler_pc)
m.d.sync += continue_pc_override.eq(0)
Expand All @@ -228,9 +243,11 @@ def flush_instr(rob_entry):
def _():
return {"flushing": core_flushing}

@def_method(m, self.precommit)
def _():
rob_entry = self.rob_peek(m)
return {"rob_id": rob_entry.rob_id, "side_fx": side_fx}
rob_id_val = Signal(self.gen_params.rob_entries_bits)

@def_method(m, self.precommit, validate_arguments=lambda rob_id: rob_id == rob_id_val)
def _(rob_id):
m.d.top_comb += rob_id_val.eq(self.rob_peek(m).rob_id)
return {"side_fx": side_fx}

return m
20 changes: 13 additions & 7 deletions coreblocks/core.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from amaranth import *
from amaranth.lib.wiring import Component, flipped, connect, Out
from amaranth.lib.wiring import Component, flipped, connect, In, Out
from transactron.utils.amaranth_ext.elaboratables import ModuleConnector

from transactron.utils.dependencies import DependencyContext
from coreblocks.priv.traps.instr_counter import CoreInstructionCounter
from coreblocks.func_blocks.interface.func_blocks_unifier import FuncBlocksUnifier
from coreblocks.priv.traps.interrupt_controller import InternalInterruptController
from coreblocks.priv.traps.interrupt_controller import ISA_RESERVED_INTERRUPTS, InternalInterruptController
from transactron.core import Transaction, TModule
from transactron.lib import ConnectTrans, MethodProduct
from coreblocks.interface.layouts import *
Expand Down Expand Up @@ -35,12 +35,14 @@
class Core(Component):
wb_instr: WishboneInterface
wb_data: WishboneInterface
interrupts: Signal

def __init__(self, *, gen_params: GenParams):
super().__init__(
{
"wb_instr": Out(WishboneSignature(gen_params.wb_params)),
"wb_data": Out(WishboneSignature(gen_params.wb_params)),
"interrupts": In(ISA_RESERVED_INTERRUPTS + gen_params.interrupt_custom_count),
}
)

Expand Down Expand Up @@ -96,8 +98,8 @@ def __init__(self, *, gen_params: GenParams):
def elaborate(self, platform):
m = TModule()

connect(m, flipped(self.wb_instr), self.wb_master_instr.wb_master)
connect(m, flipped(self.wb_data), self.wb_master_data.wb_master)
connect(m.top_module, flipped(self.wb_instr), self.wb_master_instr.wb_master)
connect(m.top_module, flipped(self.wb_data), self.wb_master_data.wb_master)

m.submodules.wb_master_instr = self.wb_master_instr
m.submodules.wb_master_data = self.wb_master_data
Expand All @@ -115,6 +117,8 @@ def elaborate(self, platform):

m.submodules.csr_generic = self.csr_generic
m.submodules.interrupt_controller = self.interrupt_controller
m.d.comb += self.interrupt_controller.internal_report_level.eq(self.interrupts[0:16])
m.d.comb += self.interrupt_controller.custom_report.eq(self.interrupts[16:])

m.submodules.core_counter = core_counter = CoreInstructionCounter(self.gen_params)

Expand All @@ -136,10 +140,12 @@ def elaborate(self, platform):

m.submodules.exception_information_register = self.exception_information_register

fetch_resume_fb, fetch_resume_unifiers = self.connections.get_dependency(FetchResumeKey())
m.submodules.fetch_resume_unifiers = ModuleConnector(**fetch_resume_unifiers)
fetch_resume = self.connections.get_optional_dependency(FetchResumeKey())
if fetch_resume is not None:
fetch_resume_fb, fetch_resume_unifiers = fetch_resume
m.submodules.fetch_resume_unifiers = ModuleConnector(**fetch_resume_unifiers)

m.submodules.fetch_resume_connector = ConnectTrans(fetch_resume_fb, self.frontend.resume_from_unsafe)
m.submodules.fetch_resume_connector = ConnectTrans(fetch_resume_fb, self.frontend.resume_from_unsafe)

m.submodules.announcement = self.announcement
m.submodules.func_blocks_unifier = self.func_blocks_unifier
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/core_structs/rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, *, gen_params: GenParams):
self.internal_layout = make_layout(("reg_val", gen_params.isa.xlen), ("valid", 1))
self.read_layout = layouts.rf_read_out
self.entries = Array(
Signal(self.internal_layout, reset={"reg_val": 0, "valid": k == 0})
Signal(self.internal_layout, init={"reg_val": 0, "valid": k == 0})
for k in range(2**gen_params.phys_regs_bits)
)

Expand Down
7 changes: 3 additions & 4 deletions coreblocks/core_structs/rob.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from amaranth import *
from amaranth.lib.data import View
import amaranth.lib.memory as memory
from transactron import Method, Transaction, def_method, TModule
from transactron.lib.metrics import *
Expand All @@ -19,7 +18,7 @@ def __init__(self, gen_params: GenParams) -> None:
self.retire = Method()
self.done = Array(Signal() for _ in range(2**self.params.rob_entries_bits))
self.exception = Array(Signal() for _ in range(2**self.params.rob_entries_bits))
self.data = memory.Memory(shape=layouts.data_layout.size, depth=2**self.params.rob_entries_bits, init=[])
self.data = memory.Memory(shape=layouts.data_layout, depth=2**self.params.rob_entries_bits, init=[])
self.get_indices = Method(o=layouts.get_indices, nonexclusive=True)

self.perf_rob_wait_time = FIFOLatencyMeasurer(
Expand Down Expand Up @@ -54,8 +53,8 @@ def elaborate(self, platform):

@def_method(m, self.peek, ready=peek_possible)
def _():
return { # remove View after Amaranth upgrade
"rob_data": View(self.params.get(ROBLayouts).data_layout, read_port.data),
return {
"rob_data": read_port.data,
"rob_id": start_idx,
"exception": self.exception[start_idx],
}
Expand Down
10 changes: 8 additions & 2 deletions coreblocks/frontend/fetch/fetch.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from amaranth import *
from amaranth.lib.data import ArrayLayout
from amaranth.lib.coding import PriorityEncoder
from coreblocks.interface.keys import FetchResumeKey
from transactron.lib import BasicFifo, Semaphore, ConnectTrans, logging, Pipe
from transactron.lib.metrics import *
from transactron.lib.simultaneous import condition
from transactron.utils import MethodLayout, popcount, assign
from transactron.utils.dependencies import DependencyContext
from transactron.utils.transactron_helpers import from_method_layout, make_layout
from transactron.utils.amaranth_ext.coding import PriorityEncoder
from transactron import *

from coreblocks.cache.iface import CacheInterface
Expand Down Expand Up @@ -402,7 +402,13 @@ def _():
if self.gen_params.extra_verification:
expect_unstall_unsafe = Signal()
prev_stalled_unsafe = Signal()
unifier_ready = DependencyContext.get().get_dependency(FetchResumeKey())[0].ready
dependencies = DependencyContext.get()
fetch_resume = dependencies.get_optional_dependency(FetchResumeKey())
if fetch_resume is not None:
unifier_ready = fetch_resume[0].ready
else:
unifier_ready = C(0)

m.d.sync += prev_stalled_unsafe.eq(stalled_unsafe)
with m.FSM("running"):
with m.State("running"):
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/frontend/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(self, *, gen_params: GenParams, instr_bus: BusMasterInterface):
def elaborate(self, platform):
m = TModule()

if self.icache_refiller:
if self.gen_params.icache_params.enable:
m.submodules.icache_refiller = self.icache_refiller
m.submodules.icache = self.icache

Expand Down
14 changes: 4 additions & 10 deletions coreblocks/func_blocks/csr/csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,12 @@ def elaborate(self, platform):
done = Signal()
call_resume = Signal()
exception = Signal()
precommitting = Signal()

current_result = Signal(self.gen_params.isa.xlen)

instr = Signal(StructLayout(self.csr_layouts.rs.data_layout.members | {"valid": 1}))

m.d.comb += ready_to_process.eq(precommitting & instr.valid & (instr.rp_s1 == 0))
m.d.comb += ready_to_process.eq(instr.valid & (instr.rp_s1 == 0))

# RISCV Zicsr spec Table 1.1
should_read_csr = Signal()
Expand All @@ -134,6 +133,9 @@ def elaborate(self, platform):

# Methods used within this Tranaction are CSRRegister internal _fu_(read|write) handlers which are always ready
with Transaction().body(m, request=(ready_to_process & ~done)):
precommit = self.dependency_manager.get_dependency(InstructionPrecommitKey())
info = precommit(m, instr.rob_id)
m.d.top_comb += exe_side_fx.eq(info.side_fx)
with m.Switch(instr.csr):
for csr_number, methods in self.regfile.items():
read, write = methods
Expand Down Expand Up @@ -257,14 +259,6 @@ def _():
# CSR instructions are never compressed, PC+4 is always next instruction
return {"pc": instr.pc + self.gen_params.isa.ilen_bytes}

# Generate precommitting signal from precommit
with Transaction().body(m):
precommit = self.dependency_manager.get_dependency(InstructionPrecommitKey())
info = precommit(m)
with m.If(instr.rob_id == info.rob_id):
m.d.comb += precommitting.eq(1)
m.d.comb += exe_side_fx.eq(info.side_fx)

return m


Expand Down
2 changes: 1 addition & 1 deletion coreblocks/func_blocks/fu/common/rs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from collections.abc import Iterable
from typing import Optional
from amaranth import *
from amaranth.lib.coding import PriorityEncoder
from transactron import Method, Transaction, def_method, TModule
from coreblocks.params import GenParams
from coreblocks.arch import OpType
Expand All @@ -11,6 +10,7 @@
from transactron.utils import RecordDict
from transactron.utils import assign
from transactron.utils.assign import AssignType
from transactron.utils.amaranth_ext.coding import PriorityEncoder
from transactron.utils.amaranth_ext.functions import popcount
from transactron.utils.transactron_helpers import make_layout

Expand Down
File renamed without changes.
Loading

0 comments on commit f12a7a1

Please sign in to comment.