Skip to content

Commit

Permalink
Merge branch 'master' into piotro888/riscof
Browse files Browse the repository at this point in the history
  • Loading branch information
piotro888 committed Oct 5, 2023
2 parents dd1b762 + 59dddc5 commit 11a9391
Show file tree
Hide file tree
Showing 20 changed files with 651 additions and 841 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ In the future, we would like to achieve the following goals:

## State of the project

The core is currently incomplete and cannot be readily used in other projects.
We plan to achieve full RV32I support soon and to make the core easily usable in [LiteX](https://github.com/enjoy-digital/litex).
The core currently supports the full RV32I instruction set and several extensions, including M (multiplication and division) and C (compressed instructions).
Interrupts and exceptions are currently not supported.
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.
Expand Down
8 changes: 5 additions & 3 deletions coreblocks/lsu/dummyLsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def elaborate(self, platform):

m.submodules.internal = internal = LSUDummyInternals(self.gen_params, self.bus, current_instr)

result_ready = internal.result_ready
result_ready = internal.result_ready | ((current_instr.exec_fn.op_type == OpType.FENCE) & current_instr.valid)

@def_method(m, self.select, ~reserved)
def _():
Expand Down Expand Up @@ -257,7 +257,9 @@ def _():

@def_method(m, self.precommit)
def _(rob_id: Value):
with m.If(current_instr.valid & (rob_id == current_instr.rob_id)):
with m.If(
current_instr.valid & (rob_id == current_instr.rob_id) & (current_instr.exec_fn.op_type != OpType.FENCE)
):
m.d.comb += internal.execute.eq(1)

return m
Expand All @@ -272,7 +274,7 @@ def get_module(self, gen_params: GenParams) -> FuncBlock:
return unit

def get_optypes(self) -> set[OpType]:
return {OpType.LOAD, OpType.STORE}
return {OpType.LOAD, OpType.STORE, OpType.FENCE}

def get_rs_entry_count(self) -> int:
return 1
5 changes: 3 additions & 2 deletions coreblocks/params/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
__all__ = ["CoreConfiguration", "basic_core_config", "tiny_core_config", "full_core_config", "test_core_config"]

basic_configuration: tuple[BlockComponentParams, ...] = (
RSBlockComponent([ALUComponent(), ShiftUnitComponent(), JumpComponent()], rs_entries=4),
RSBlockComponent([ALUComponent(), ShiftUnitComponent(), JumpComponent(), ExceptionUnitComponent()], rs_entries=4),
LSUBlockComponent(),
)

Expand Down Expand Up @@ -76,7 +76,7 @@ class CoreConfiguration:
icache_sets_bits: int = 7
icache_block_size_bits: int = 5

allow_partial_extensions: bool = True # TODO: Change to False when I extension will be fully supported
allow_partial_extensions: bool = False

_implied_extensions: Extension = Extension(0)

Expand All @@ -94,6 +94,7 @@ def replace(self, **kwargs):
LSUBlockComponent(),
),
rob_entries_bits=6,
allow_partial_extensions=True, # No exception unit
)

# Core configuration with all supported components
Expand Down
70 changes: 55 additions & 15 deletions coreblocks/transactions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,7 @@ def add_transaction(self, transaction: "Transaction"):
self.transactions.append(transaction)

@staticmethod
def _conflict_graph(
method_map: MethodMap, relations: list[Relation]
) -> Tuple[TransactionGraph, TransactionGraph, PriorityOrder]:
def _conflict_graph(method_map: MethodMap) -> Tuple[TransactionGraph, TransactionGraph, PriorityOrder]:
"""_conflict_graph
This function generates the graph of transaction conflicts. Conflicts
Expand Down Expand Up @@ -252,6 +250,12 @@ def add_edge(begin: Transaction, end: Transaction, priority: Priority, conflict:
if transaction1 is not transaction2:
add_edge(transaction1, transaction2, Priority.UNDEFINED, True)

relations = [
Relation(**relation, start=elem)
for elem in method_map.methods_and_transactions
for relation in elem.relations
]

for relation in relations:
start = relation["start"]
end = relation["end"]
Expand Down Expand Up @@ -408,12 +412,7 @@ def elaborate(self, platform):
merge_manager = self._simultaneous()

method_map = MethodMap(self.transactions)
relations = [
Relation(**relation, start=elem)
for elem in method_map.methods_and_transactions
for relation in elem.relations
]
cgr, rgr, porder = TransactionManager._conflict_graph(method_map, relations)
cgr, rgr, porder = TransactionManager._conflict_graph(method_map)

m = Module()
m.submodules.merge_manager = merge_manager
Expand All @@ -434,6 +433,9 @@ def elaborate(self, platform):
if len(method_args[method]) == 1:
m.d.comb += method.data_in.eq(method_args[method][0])
else:
if method.single_caller:
raise RuntimeError(f"Single-caller method '{method.name}' called more than once")

runs = Cat(method_runs[method])
for i in OneHotSwitchDynamic(m, runs):
m.d.comb += method.data_in.eq(method_args[method][i])
Expand All @@ -457,6 +459,25 @@ def visual_graph(self, fragment):

return graph

def debug_signals(self) -> SignalBundle:
method_map = MethodMap(self.transactions)
cgr, _, _ = TransactionManager._conflict_graph(method_map)

def transaction_debug(t: Transaction):
return (
[t.request, t.grant]
+ [m.ready for m in method_map.methods_by_transaction[t]]
+ [t2.grant for t2 in cgr[t]]
)

def method_debug(m: Method):
return [m.ready, m.run, {t.name: transaction_debug(t) for t in method_map.transactions_by_method[m]}]

return {
"transactions": {t.name: transaction_debug(t) for t in method_map.transactions},
"methods": {m.owned_name: method_debug(m) for m in method_map.methods},
}


class TransactionContext:
stack: list[TransactionManager] = []
Expand Down Expand Up @@ -654,6 +675,7 @@ class TransactionBase(Owned):
def_counter: ClassVar[count] = count()
def_order: int
defined: bool = False
name: str

def __init__(self):
self.method_uses: dict[Method, Tuple[ValueLike, ValueLike]] = dict()
Expand Down Expand Up @@ -776,6 +798,13 @@ def peek(cls) -> Optional[Self]:
raise RuntimeError(f"Current body not a {cls.__name__}")
return TransactionBase.stack[-1]

@property
def owned_name(self):
if self.owner is not None and self.owner.__class__.__name__ != self.name:
return f"{self.owner.__class__.__name__}_{self.name}"
else:
return self.name


class Transaction(TransactionBase):
"""Transaction.
Expand Down Expand Up @@ -832,8 +861,8 @@ def __init__(self, *, name: Optional[str] = None, manager: Optional[TransactionM
if manager is None:
manager = TransactionContext.get()
manager.add_transaction(self)
self.request = Signal(name=self.name + "_request")
self.grant = Signal(name=self.name + "_grant")
self.request = Signal(name=self.owned_name + "_request")
self.grant = Signal(name=self.owned_name + "_grant")

@contextmanager
def body(self, m: TModule, *, request: ValueLike = C(1)) -> Iterator["Transaction"]:
Expand Down Expand Up @@ -911,7 +940,13 @@ class Method(TransactionBase):
"""

def __init__(
self, *, name: Optional[str] = None, i: MethodLayout = (), o: MethodLayout = (), nonexclusive: bool = False
self,
*,
name: Optional[str] = None,
i: MethodLayout = (),
o: MethodLayout = (),
nonexclusive: bool = False,
single_caller: bool = False,
):
"""
Parameters
Expand All @@ -930,15 +965,20 @@ def __init__(
transactions in the same clock cycle. If such a situation happens,
the method still is executed only once, and each of the callers
receive its output. Nonexclusive methods cannot have inputs.
single_caller: bool
If true, this method is intended to be called from a single
transaction. An error will be thrown if called from multiple
transactions.
"""
super().__init__()
self.owner, owner_name = get_caller_class_name(default="$method")
self.name = name or tracer.get_var_name(depth=2, default=owner_name)
self.ready = Signal(name=self.name + "_ready")
self.run = Signal(name=self.name + "_run")
self.ready = Signal(name=self.owned_name + "_ready")
self.run = Signal(name=self.owned_name + "_run")
self.data_in = Record(i)
self.data_out = Record(o)
self.nonexclusive = nonexclusive
self.single_caller = single_caller
if nonexclusive:
assert len(self.data_in) == 0

Expand Down Expand Up @@ -1093,7 +1133,7 @@ def __call__(
if arg is None:
arg = kwargs

enable_sig = Signal(name=self.name + "_enable")
enable_sig = Signal(name=self.owned_name + "_enable")
m.d.av_comb += enable_sig.eq(enable)
m.d.top_comb += assign(arg_rec, arg, fields=AssignType.ALL)
TransactionBase.get().use_method(self, arg_rec, enable_sig)
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/transactions/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ def _():


@contextmanager
def condition(m: TModule, *, nonblocking: bool = True, priority: bool = True):
def condition(m: TModule, *, nonblocking: bool = False, priority: bool = True):
"""Conditions using simultaneous transactions.
This context manager allows to easily define conditions utilizing
Expand Down
3 changes: 2 additions & 1 deletion scripts/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def load_regression_tests() -> list[str]:


def run_regressions_with_cocotb(tests: list[str], traces: bool) -> bool:
arglist = ["make", "-C", "test/regression/cocotb", "-f", "test.Makefile"]
cpu_count = len(os.sched_getaffinity(0))
arglist = ["make", "-C", "test/regression/cocotb", "-f", "test.Makefile", f"-j{cpu_count}"]

test_cases = ",".join(tests)
arglist += [f"TESTCASE={test_cases}"]
Expand Down
10 changes: 6 additions & 4 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,15 +188,17 @@ def elaborate(self, platform) -> HasElaborate:

class PysimSimulator(Simulator):
def __init__(self, module: HasElaborate, max_cycles: float = 10e4, add_transaction_module=True, traces_file=None):
super().__init__(TestModule(module, add_transaction_module))
test_module = TestModule(module, add_transaction_module)
tested_module = test_module.tested_module
super().__init__(test_module)

clk_period = 1e-6
self.add_clock(clk_period)

if isinstance(module, HasDebugSignals):
extra_signals = module.debug_signals
if isinstance(tested_module, HasDebugSignals):
extra_signals = tested_module.debug_signals
else:
extra_signals = functools.partial(auto_debug_signals, module)
extra_signals = functools.partial(auto_debug_signals, tested_module)

if traces_file:
traces_dir = "test/__traces__"
Expand Down
Loading

0 comments on commit 11a9391

Please sign in to comment.