Skip to content

Commit

Permalink
Merge branch 'master' into piotro/fix-no-icache
Browse files Browse the repository at this point in the history
  • Loading branch information
tilk authored Nov 12, 2024
2 parents 7b74c2e + 34565a3 commit f16f57a
Show file tree
Hide file tree
Showing 17 changed files with 1,073 additions and 82 deletions.
17 changes: 12 additions & 5 deletions coreblocks/backend/retirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,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 @@ -228,9 +233,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
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
Empty file.
38 changes: 38 additions & 0 deletions coreblocks/func_blocks/fu/fpu/fpu_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from amaranth.lib import enum


class RoundingModes(enum.Enum):
ROUND_UP = 3
ROUND_DOWN = 2
ROUND_ZERO = 1
ROUND_NEAREST_EVEN = 0
ROUND_NEAREST_AWAY = 4


class Errors(enum.IntFlag):
INVALID_OPERATION = enum.auto()
DIVISION_BY_ZERO = enum.auto()
OVERFLOW = enum.auto()
UNDERFLOW = enum.auto()
INEXACT = enum.auto()


class FPUParams:
"""FPU parameters
Parameters
----------
sig_width: int
Width of significand, including implicit bit
exp_width: int
Width of exponent
"""

def __init__(
self,
*,
sig_width: int = 24,
exp_width: int = 8,
):
self.sig_width = sig_width
self.exp_width = exp_width
176 changes: 176 additions & 0 deletions coreblocks/func_blocks/fu/fpu/fpu_error_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
from amaranth import *
from transactron import TModule, Method, def_method
from coreblocks.func_blocks.fu.fpu.fpu_common import (
RoundingModes,
FPUParams,
Errors,
)


class FPUErrorMethodLayout:
"""FPU error checking module layouts for methods
Parameters
----------
fpu_params: FPUParams
FPU parameters
"""

def __init__(self, *, fpu_params: FPUParams):
"""
input_inf is a flag that comes from previous stage.
Its purpose is to indicate that the infinity on input
is a result of infinity arithmetic and not a result of overflow
"""
self.error_in_layout = [
("sign", 1),
("sig", fpu_params.sig_width),
("exp", fpu_params.exp_width),
("rounding_mode", RoundingModes),
("inexact", 1),
("invalid_operation", 1),
("division_by_zero", 1),
("input_inf", 1),
]
self.error_out_layout = [
("sign", 1),
("sig", fpu_params.sig_width),
("exp", fpu_params.exp_width),
("errors", Errors),
]


class FPUErrorModule(Elaboratable):
"""FPU error checking module
Parameters
----------
fpu_params: FPUParams
FPU rounding module parameters
Attributes
----------
error_checking_request: Method
Transactional method for initiating error checking of a floating point number.
Takes 'error_in_layout' as argument
Returns final number and errors as 'error_out_layout'
"""

def __init__(self, *, fpu_params: FPUParams):

self.fpu_errors_params = fpu_params
self.method_layouts = FPUErrorMethodLayout(fpu_params=self.fpu_errors_params)
self.error_checking_request = Method(
i=self.method_layouts.error_in_layout,
o=self.method_layouts.error_out_layout,
)

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

max_exp = C(
2 ** (self.fpu_errors_params.exp_width) - 1,
unsigned(self.fpu_errors_params.exp_width),
)
max_normal_exp = C(
2 ** (self.fpu_errors_params.exp_width) - 2,
unsigned(self.fpu_errors_params.exp_width),
)
max_sig = C(
2 ** (self.fpu_errors_params.sig_width) - 1,
unsigned(self.fpu_errors_params.sig_width),
)

overflow = Signal()
underflow = Signal()
inexact = Signal()
tininess = Signal()

final_exp = Signal(self.fpu_errors_params.exp_width)
final_sig = Signal(self.fpu_errors_params.sig_width)
final_sign = Signal()
final_errors = Signal(5)

@def_method(m, self.error_checking_request)
def _(arg):
is_nan = arg.invalid_operation | ((arg.exp == max_exp) & (arg.sig.any()))
is_inf = arg.division_by_zero | arg.input_inf
input_not_special = ~(is_nan) & ~(is_inf)
m.d.av_comb += overflow.eq(input_not_special & (arg.exp == max_exp))
m.d.av_comb += tininess.eq((arg.exp == 0) & (~arg.sig[-1]))
m.d.av_comb += inexact.eq(overflow | (input_not_special & arg.inexact))
m.d.av_comb += underflow.eq(tininess & inexact)

with m.If(is_nan | is_inf):

m.d.av_comb += final_exp.eq(arg.exp)
m.d.av_comb += final_sig.eq(arg.sig)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Elif(overflow):

with m.Switch(arg.rounding_mode):
with m.Case(RoundingModes.ROUND_NEAREST_AWAY, RoundingModes.ROUND_NEAREST_EVEN):

m.d.av_comb += final_exp.eq(max_exp)
m.d.av_comb += final_sig.eq(0)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Case(RoundingModes.ROUND_ZERO):

m.d.av_comb += final_exp.eq(max_normal_exp)
m.d.av_comb += final_sig.eq(max_sig)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Case(RoundingModes.ROUND_DOWN):

with m.If(arg.sign):

m.d.av_comb += final_exp.eq(max_exp)
m.d.av_comb += final_sig.eq(0)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Else():

m.d.av_comb += final_exp.eq(max_normal_exp)
m.d.av_comb += final_sig.eq(max_sig)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Case(RoundingModes.ROUND_UP):

with m.If(arg.sign):

m.d.av_comb += final_exp.eq(max_normal_exp)
m.d.av_comb += final_sig.eq(max_sig)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Else():

m.d.av_comb += final_exp.eq(max_exp)
m.d.av_comb += final_sig.eq(0)
m.d.av_comb += final_sign.eq(arg.sign)

with m.Else():
with m.If((arg.exp == 0) & (arg.sig[-1] == 1)):
m.d.av_comb += final_exp.eq(1)
with m.Else():
m.d.av_comb += final_exp.eq(arg.exp)
m.d.av_comb += final_sig.eq(arg.sig)
m.d.av_comb += final_sign.eq(arg.sign)

m.d.av_comb += final_errors.eq(
Mux(arg.invalid_operation, Errors.INVALID_OPERATION, 0)
| Mux(arg.division_by_zero, Errors.DIVISION_BY_ZERO, 0)
| Mux(overflow, Errors.OVERFLOW, 0)
| Mux(underflow, Errors.UNDERFLOW, 0)
| Mux(inexact, Errors.INEXACT, 0)
)

return {
"exp": final_exp,
"sig": final_sig,
"sign": final_sign,
"errors": final_errors,
}

return m
Loading

0 comments on commit f16f57a

Please sign in to comment.