fpu decoder async separation

master
kaqu 2 years ago
parent 555730c3f5
commit 475617f9f7
  1. 18
      libmodules/core.py
  2. 204
      libmodules/fpu_decode.py
  3. 217
      libmodules/instruction_decode.py
  4. 0
      risq5_imf.py

@ -20,6 +20,7 @@ from litex.soc.interconnect.csr import *
from libmodules.dramtransfer import DRAMTransfer
from libmodules.register_file import Risq5RegisterFile
from libmodules.instruction_decode import Risq5Decoder
from libmodules.fpu_decode import Risq5FPUDecoder
import libmodules.risq5defs as risq5defs
class Risq5Core(Module, AutoCSR, AutoDoc, ModuleDoc):
@ -208,6 +209,9 @@ class Risq5Core(Module, AutoCSR, AutoDoc, ModuleDoc):
self.LU_CacheValid = Signal() # Indicate loaded LU cache
self.sync += self.b32status.storage[5].eq(self.LU_CacheValid) # Indicate cache status to external world
# Integrate F-Extension decode
self.submodules.fpu_decoder = fpu_decoder = Risq5FPUDecoder(regs=regs)
# Integrate an instruction decoder
self.submodules.decoder = decoder = Risq5Decoder(
regs=regs,
@ -219,7 +223,8 @@ class Risq5Core(Module, AutoCSR, AutoDoc, ModuleDoc):
LU_CacheValid=self.LU_CacheValid,
LUCache=LUCache,
SU_Unit=SU_Unit,
isa_extensions=isa_extensions
isa_extensions=isa_extensions,
fpu_decoder=fpu_decoder
)
#---------------- L1 cache -------------------------------------------------------------
@ -415,14 +420,5 @@ class Risq5Core(Module, AutoCSR, AutoDoc, ModuleDoc):
]
def Risq5Core_testbench(regs):
print("----- RISQ5 core testbench -----")
for i in range(32):
#yield regs.rfx[i].storage.eq(0)
pass
yield
if __name__ == "__main__":
r5c = Risq5Core()
run_simulation(r5c, Risq5Core_testbench(r5c), vcd_name="risq5_core.vcd", clocks={"sys":16})
print("***** Core file is passive ... ;) *****")

@ -0,0 +1,204 @@
#!/usr/bin/env python3
#
# fpu_decode.py
#
# Risq5 F-Extension decoder
#
# History:
# --------
# 31.03.21/KQ Initial version
#
from migen import *
from migen.fhdl.specials import Memory
from litex.soc.interconnect.csr import *
from litex.soc.integration.doc import AutoDoc, ModuleDoc
from libmodules.register_file import Risq5RegisterFile
import libmodules.risq5defs as risq5defs
class Risq5FPUDecoder(Module):
"""
Risq5 FPU instruction decoder
"""
def __init__(self, regs=None):
assert isinstance(regs, Risq5RegisterFile)
self.fadd = Signal() # F-Extension: fadd job trigger
self.fready = Signal() # Indicate ready
self.fwrite = Signal() # F-Extension: Do a write to a float register
# Calculation support variables
self.sign1 = Signal() # Sign of floats
self.sign2 = Signal()
self.sign3 = Signal()
self.e1 = Signal((8,True), reset_less=True) # Signed exponents!
self.e2 = Signal((8,True), reset_less=True)
self.e3 = Signal((8,True), reset_less=True)
self.m1 = Signal((23+1+3,False), reset_less=True) # Unsigned mantissas! TODO: Verify sign!
self.m2 = Signal((24+1+3,False), reset_less=True) # 23 bits + 1bit (1.xx = 0x800000)
self.m3 = Signal((25+1+3,True), reset_less=True) # + Sign + R(0)/Guard & Sticky bits
self.s_bit = Signal() # Sticky bit (for rounding control)
self.branch1 = Signal() # Branch helpers
self.branch2 = Signal()
FPU_fsm = FSM(reset_state="FPU_IDLE") # FSM starts idling ...
self.submodules += FPU_fsm
self.FPU_state = Signal(9, reset_less=True) # Debugging support
FPU_fsm.act("FPU_IDLE",
NextValue(self.FPU_state, 0),
If(self.fadd & ~self.fready, # Triggers set & ready flag reset externally!
NextValue(self.sign1, regs.fs1[31]),
NextValue(self.sign2, regs.fs2[31]),
NextValue(self.e1, regs.fs1[23:31] - 127),
NextValue(self.e2, regs.fs2[23:31] - 127),
NextValue(self.m1, Cat(0,0,0, regs.fs1[0:23], 1, 0)), # | 0x00800000 + R/G/S bits
NextValue(self.m2, Cat(0,0,0, regs.fs2[0:23], 1, 0)), # | 0x00800000 + R/G/S bits
NextState("FADD1")
)
)
FPU_fsm.act("FADD1",
NextValue(self.FPU_state, 1),
# 1. Verify valid ranges 1st!
If((((regs.fs1 & 0x7FFFFFFF) == 0x7FFFFFFF) | ((regs.fs2 & 0x7FFFFFFF) == 0x7FFFFFFF))
| ((self.sign1 ^ self.sign2) & ((self.e1 == -1) & (self.e2 == -1))),
NextValue(regs.fcs, regs.fcs | 0x10), # NV: Invalid operation
NextValue(regs.frd_wrport.dat_w, 0x7FFFFFFF), # NAN
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Elif(self.e1 == -1, # Infinity
NextValue(regs.fcs, regs.fcs | 0x04), # OF: Overflow
NextValue(regs.frd_wrport.dat_w, regs.fs1), # Return infinity
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Elif(self.e2 == -1, # Infinity
NextValue(regs.fcs, regs.fcs | 0x04), # OF: Overflow
NextValue(regs.frd_wrport.dat_w, regs.fs2), # Return infinity
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Else( # Ok, valid floats supplied ...
NextValue(self.s_bit, 0),
NextValue(self.branch1, 0), # Reset helpers
NextValue(self.branch2, 0),
NextState("FADD2")
)
)
FPU_fsm.act("FADD2",
NextValue(self.FPU_state, 2),
# 2. Compare exponents: The higher one will be taken, the lower one adjusted
If(self.e1 < self.e2,
If(self.m1[0], NextValue(self.s_bit, 1)), # Keep shifted out bits (ORed sticky bit)
NextValue(self.m1, self.m1 >> 1),
NextValue(self.e1, self.e1 + 1),
NextValue(self.branch1, 1),
).Elif(self.e1 > self.e2,
If(self.m2[0], NextValue(self.s_bit, 1)), # Keep shifted out bits (ORed sticky bit)
NextValue(self.m2, self.m2 >> 1),
NextValue(self.e2, self.e2 + 1),
NextValue(self.branch2, 1),
).Else(
If(self.branch1, NextValue(self.m1, self.m1 | self.s_bit)), # Add sticky bit (if any)
If(self.branch2, NextValue(self.m2, self.m2 | self.s_bit)),
NextState("FADD3")
)
)
FPU_fsm.act("FADD3",
NextValue(self.FPU_state, 3),
# 3. Add mantissas (as both are of same base now)
If(~self.sign1 & ~self.sign2, # Negotiate sign -> ADD/SUB
NextValue(self.m3, self.m1 + self.m2)
).Else(
If(self.sign1 & ~self.sign2,
NextValue(self.m3, self.m2 - self.m1)
).Else(
If(~self.sign1 & self.sign2,
NextValue(self.m3, self.m1 - self.m2)
).Else(
NextValue(self.m3, -(self.m1 + self.m2))
)
)
),
NextState("FADD4")
)
FPU_fsm.act("FADD4",
NextValue(self.FPU_state, 4),
# 4. Retrieve sign & unsigned absolute value
If(self.m3 < 0,
NextValue(self.sign3, 1), # Pull sign
NextValue(self.m3, -self.m3) # Absolute value pick
).Else( # m3 positive anyway
NextValue(self.sign3, 0), # Remember ...
),
NextValue(self.e3, self.e1), # Starter value (e1/e2 are the same by now ...)
NextState("FADD5")
)
FPU_fsm.act("FADD5",
NextValue(self.FPU_state, 5),
# 5. Rounding to nearest/even (FCS_FRM=0x00)
If(self.m3[0:3] == 0x7, # Remainder (all set?): REMAINDER(0) + GUARD(MSB) + STICKYBIT (ORed rest)
NextValue(self.s_bit, 1) # Indicate rounding
).Else(
NextValue(self.s_bit, 0), # Reset otherwise
),
NextValue(self.m3, self.m3 >> 3), # Remove R/G/S bits
NextState("FADD6")
)
FPU_fsm.act("FADD6",
NextValue(self.FPU_state, 6),
# 6. Normalization of result: Overflow
If(self.m3[24], # & 0x01000000,
NextValue(self.m3, self.m3 >> 1), # Adjust mantissa & increment exponent
NextValue(self.e3, self.e3 + 1)
).Else(
NextState("FADD7")
)
)
FPU_fsm.act("FADD7",
# 7. Normalization: Result
NextValue(self.FPU_state, 7),
If(~self.m3[23], # & 0x00800000),
NextValue(self.m3, self.m3 << 1), # Subtraction normalization
NextValue(self.e3, self.e3 - 1)
).Else(
If(self.s_bit, # Do we need rounding?!
NextValue(self.m3, self.m3 + self.s_bit),
NextState("FADD8") # Adjust possible overflow ...
).Else( # Nope, all ready
NextState("FADD9")
)
)
)
FPU_fsm.act("FADD8",
NextValue(self.FPU_state, 8),
If(self.m3[24], # & 0x01000000, # Overflow?
NextValue(self.m3, self.m3 >> 1), # Adjust mantissa & increment exponent
NextValue(self.e3, self.e3 + 1)
),
NextState("FADD9")
)
FPU_fsm.act("FADD9",
NextValue(self.FPU_state, 9),
# 6. Build the actual resulting float
NextValue(regs.frd_wrport.dat_w, Cat(self.m3[0:23], self.e3+127, self.sign3)),
If((self.m3[0:23] != 0) | ((self.e3+127) != 0), # Not zero?
If(self.e3+127 == 1, # FLT_MIN range
NextValue(regs.fcs, regs.fcs | 0x02), # UF: Underflow
If(regs.fcs[5:8] == 0x01, # RTZ rounding
NextValue(regs.frd_wrport.dat_w, 0), # FLT_MIN -> Round to zero -> 0.0!
)
)
),
NextValue(self.fwrite, 1), # Write required
NextValue(self.fready, 1), # Indicate ready to main decoder
NextState("FPU_IDLE")
) # End of fadd.s processing
if __name__ == "__main__":
print("***** Register file is passive ... ;) *****")

@ -16,14 +16,19 @@ from litex.soc.interconnect.csr import *
from litex.soc.integration.doc import AutoDoc, ModuleDoc
from libmodules.register_file import Risq5RegisterFile
from libmodules.fpu_decode import Risq5FPUDecoder
import libmodules.risq5defs as risq5defs
class Risq5Decoder(Module):
"""
Risq5 instruction decode phase logic
"""
def __init__(self, regs=None, modereg=None, statusreg=None, L1CacheOffset=None, L1CacheSize=32, LU_CacheWait=24, LU_CacheValid=None, LUCache=None, SU_Unit=None, isa_extensions=0x40000100):
def __init__(self, regs=None, modereg=None, statusreg=None, L1CacheOffset=None, L1CacheSize=32,
LU_CacheWait=24, LU_CacheValid=None, LUCache=None, SU_Unit=None,
isa_extensions=0x40000100, fpu_decoder=None
):
assert isinstance(regs, Risq5RegisterFile)
assert isinstance(fpu_decoder, Risq5FPUDecoder)
self.start = Signal() # Start decoding signal
self.next = Signal() # Signal readyness ...
@ -32,9 +37,7 @@ class Risq5Decoder(Module):
self.LUByteID = Signal(3, reset_less=True) # Uneven adressing remainder (0..3=byte, 4..5=halfword, 6=word)
self.SUStore = Signal() # Signal SU to store a value
self.SUByteID = Signal(3, reset_less=True) # Uneven adressing remainder (0..3=byte, 4..5=halfword, 6=not used/direct write)
self.write = Signal() # Do a write (local register)
self.fwrite = Signal() # F-Extension: Do a write to a float register
self.fadd = Signal() # F-Extension: fadd job trigger
self.write = Signal() # Do a write (local register)
self.L1Below = Signal(reset_less=True)
self.L1Beyond = Signal(reset_less=True) # Local cache boundaries (only valid w/ branches!)
@ -78,19 +81,6 @@ class Risq5Decoder(Module):
self.div_result = Signal(32, reset_less=True)
self.div_multiple = Signal(32, reset_less=True)
# F extension:
self.sign1 = Signal() # Sign of floats
self.sign2 = Signal()
self.sign3 = Signal()
self.e1 = Signal((8,True), reset_less=True) # Signed exponents!
self.e2 = Signal((8,True), reset_less=True)
self.e3 = Signal((8,True), reset_less=True)
self.m1 = Signal((23+1+3,False), reset_less=True) # Unsigned mantissas! TODO: Verify sign!
self.m2 = Signal((24+1+3,False), reset_less=True) # 23 bits + 1bit (1.xx = 0x800000)
self.m3 = Signal((25+1+3,True), reset_less=True) # + Sign + R(0)/Guard & Sticky bits
self.s_bit = Signal() # Sticky bit (for rounding control)
self.branch1 = Signal() # Branch helpers
self.branch2 = Signal()
DECODE_fsm = FSM(reset_state="DECODE_IDLE") # FSM starts idling ...
self.submodules += DECODE_fsm
@ -100,9 +90,10 @@ class Risq5Decoder(Module):
If(self.start, # Do the job when triggered
#NextValue(self.next, 0), # Indicate not yet there ... -> Reset @ top level!
NextValue(self.start, 0), # Once!
NextValue(self.write, 0), # Trigger write rd reset
NextValue(self.fwrite, 0), # F-Extension: Trigger write frd reset
NextValue(self.fadd, 0), # F-Extension: fadd job trigger
NextValue(self.write, 0), # Trigger write rd reset
NextValue(fpu_decoder.fadd, 0), # F-Extension: fadd job trigger
NextValue(fpu_decoder.fready, 0), # F-Extension: Clear ready indication
NextValue(fpu_decoder.fwrite, 0), # F-Extension: Trigger write frd reset
NextValue(self.SUStore, 0), # Trigger store rs2 reset
NextValue(self.opcode_invalid, 0), # Reset invalid opcode indication
NextValue(self.div_instruction, 0), # M extension divide instruction special
@ -336,13 +327,7 @@ class Risq5Decoder(Module):
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.op == 0x53, # R-Type
If(regs.f7 == 0x00, # fadd.s frd, frs1, frs2
NextValue(self.sign1, regs.fs1[31]),
NextValue(self.sign2, regs.fs2[31]),
NextValue(self.e1, regs.fs1[23:31] - 127),
NextValue(self.e2, regs.fs2[23:31] - 127),
NextValue(self.m1, Cat(0,0,0, regs.fs1[0:23], 1, 0)), # | 0x00800000 + R/G/S bits
NextValue(self.m2, Cat(0,0,0, regs.fs2[0:23], 1, 0)), # | 0x00800000 + R/G/S bits
NextValue(self.fadd, 1), # Indicate eval. queue!
NextValue(fpu_decoder.fadd, 1), # Indicate eval. queue!
).Elif(regs.f7 == 0x04, # fsub.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f7 == 0x08, # fmul.s
@ -359,7 +344,7 @@ class Risq5Decoder(Module):
).Else( #regs.f3 == 0x02, # fsgnjx.s rd, rs1, rs2 (copy xor sign bits rs1/rs2 -> rd)
NextValue(regs.frd_wrport.dat_w, Cat(regs.fs1[0:31], (regs.fs1[31] ^ regs.fs2[31]))),
),
NextValue(self.fwrite, 1), # Trigger write frd
NextValue(fpu_decoder.fwrite, 1), # Trigger write frd
).Elif(regs.f7 == 0x14, # fmin/max
If(regs.f3 == 0x00, # fmin.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
@ -395,7 +380,7 @@ class Risq5Decoder(Module):
)
).Else( # regs.f7 == 0x78, # fmv.s.x frd, rs1 (x-reg -> f-reg) FIXME: Not working?
NextValue(regs.frd_wrport.dat_w, regs.xs1u),
NextValue(self.fwrite, 1), # Trigger write frd (f-reg)
NextValue(fpu_decoder.fwrite, 1), # Trigger write frd (f-reg)
)
# TODO: Maybe RISC-V extensions ...
@ -418,9 +403,8 @@ class Risq5Decoder(Module):
NextValue(self.next, 1), # Indicate ready state to ALU
NextState("DECODE_IDLE") # No write!
).Else(
If(self.fadd, # Branch helper: fadd logic engage
NextValue(self.fadd, 0), # Reset fadd job queue trigger (because of NFA reentry later!)
NextState("FADD1")
If(fpu_decoder.fadd, # Branch helper: fadd logic engage (req. reset within FPU_WAIT)
NextState("FPU_WAIT")
).Elif(self.div_instruction != 0, # M extension divide instruction?
If(regs.xs2s == 0x0, # RISC-V: Doesn't raise exception div/0!
NextValue(statusreg.storage[12], 1), # Indicate division by zero (TODO: Remove later!)
@ -462,7 +446,7 @@ class Risq5Decoder(Module):
).Else( # No load no more ...
If(self.write & (regs.rd != 0), # Do NOT write to X0 (never! period!)
NextValue(regs.rd_wrport.we, 1), # Write value enable (delayed)
).Elif(self.fwrite, # F-Extension: frd write
).Elif(fpu_decoder.fwrite, # F-Extension: frd write
NextValue(regs.frd_wrport.we, 1), # Write float value enable (delayed)
),
NextState("DECODE_READY") # Have register write being processed before continuing ...
@ -470,7 +454,7 @@ class Risq5Decoder(Module):
)
)
DECODE_fsm.act("DECODE_READY",
If(self.fwrite, # F-Extension write to frd?
If(fpu_decoder.fwrite, # F-Extension write to frd?
NextValue(regs.frd_wrport.we, 0), # Kill float WE enable!
).Else( # Normal write to rd!
NextValue(regs.rd_wrport.we, 0), # Kill WE enable!
@ -543,7 +527,7 @@ class Risq5Decoder(Module):
)
),
If(regs.op == 0x07, # F-Extension: flw ->frd
NextValue(self.fwrite, 1)
NextValue(fpu_decoder.fwrite, 1)
).Else( # lb/lh/lw ->rd
NextValue(self.write, 1), # Indicate WRITE (rd) validity (now ready!)
),
@ -604,7 +588,7 @@ class Risq5Decoder(Module):
).Else( # Loop exit
NextState("DECODE_DIV3")
)
)
)
DECODE_fsm.act("DECODE_DIV3",
If(self.div_multiple != 0, # Loop until ...
If(self.div_remain >= self.div_scaled_divisor,
@ -635,163 +619,14 @@ class Risq5Decoder(Module):
NextState("DECODE_WRITE")
)
)
#---------------------- F-Extension -----------------------------------------------------
"""
DECODE_fsm.act("FADD1",
If(regs.xs2u == 1,
NextValue(regs.rd_wrport.dat_w, self.e1),
).Elif(regs.xs2u == 2,
NextValue(regs.rd_wrport.dat_w, self.e2),
).Elif(regs.xs2u == 3,
NextValue(regs.rd_wrport.dat_w, self.m1),
).Else(
NextValue(regs.rd_wrport.dat_w, self.m2),
),
NextValue(self.write, 1), # rd! for test ...
NextValue(self.fwrite, 0), # Whiles't testing!
NextState("DECODE_WRITE")
)
"""
DECODE_fsm.act("FADD1",
NextValue(self.DECODE_state, 3),
# 1. Verify valid ranges 1st!
If((((regs.fs1 & 0x7FFFFFFF) == 0x7FFFFFFF) | ((regs.fs2 & 0x7FFFFFFF) == 0x7FFFFFFF))
| ((self.sign1 ^ self.sign2) & ((self.e1 == -1) & (self.e2 == -1))),
NextValue(regs.fcs, regs.fcs | 0x10), # NV: Invalid operation
NextValue(regs.frd_wrport.dat_w, 0x7FFFFFFF), # NAN
NextValue(self.fwrite, 1),
# F-Extension: Wait for FPU ready signals
DECODE_fsm.act("FPU_WAIT",
If(fpu_decoder.fready, # Wait for FPU decoder ready flag
NextValue(fpu_decoder.fadd, 0), # Reset fadd job queue trigger (because of NFA reentry later!)
NextState("DECODE_WRITE")
).Elif(self.e1 == -1, # Infinity
NextValue(regs.fcs, regs.fcs | 0x04), # OF: Overflow
NextValue(regs.frd_wrport.dat_w, regs.fs1), # Return infinity
NextValue(self.fwrite, 1),
NextState("DECODE_WRITE")
).Elif(self.e2 == -1, # Infinity
NextValue(regs.fcs, regs.fcs | 0x04), # OF: Overflow
NextValue(regs.frd_wrport.dat_w, regs.fs2), # Return infinity
NextValue(self.fwrite, 1),
NextState("DECODE_WRITE")
).Else( # Ok, valid floats supplied ...
NextValue(self.s_bit, 0),
NextValue(self.branch1, 0), # Reset helpers
NextValue(self.branch2, 0),
NextState("FADD2")
)
)
DECODE_fsm.act("FADD2",
NextValue(self.DECODE_state, 4),
# 2. Compare exponents: The higher one will be taken, the lower one adjusted
If(self.e1 < self.e2,
If(self.m1[0], NextValue(self.s_bit, 1)), # Keep shifted out bits (ORed sticky bit)
NextValue(self.m1, self.m1 >> 1),
NextValue(self.e1, self.e1 + 1),
NextValue(self.branch1, 1),
).Elif(self.e1 > self.e2,
If(self.m2[0], NextValue(self.s_bit, 1)), # Keep shifted out bits (ORed sticky bit)
NextValue(self.m2, self.m2 >> 1),
NextValue(self.e2, self.e2 + 1),
NextValue(self.branch2, 1),
).Else(
If(self.branch1, NextValue(self.m1, self.m1 | self.s_bit)), # Add sticky bit (if any)
If(self.branch2, NextValue(self.m2, self.m2 | self.s_bit)),
NextState("FADD3")
)
)
DECODE_fsm.act("FADD3",
NextValue(self.DECODE_state, 5),
# 3. Add mantissas (as both are of same base now)
If(~self.sign1 & ~self.sign2, # Negotiate sign -> ADD/SUB
NextValue(self.m3, self.m1 + self.m2)
).Else(
If(self.sign1 & ~self.sign2,
NextValue(self.m3, self.m2 - self.m1)
).Else(
If(~self.sign1 & self.sign2,
NextValue(self.m3, self.m1 - self.m2)
).Else(
NextValue(self.m3, -(self.m1 + self.m2))
)
)
),
NextState("FADD4")
)
DECODE_fsm.act("FADD4",
NextValue(self.DECODE_state, 6),
# 4. Retrieve sign & unsigned absolute value
If(self.m3 < 0,
NextValue(self.sign3, 1), # Pull sign
NextValue(self.m3, -self.m3) # Absolute value pick
).Else( # m3 positive anyway
NextValue(self.sign3, 0), # Remember ...
),
NextValue(self.e3, self.e1), # Starter value (e1/e2 are the same by now ...)
NextState("FADD5")
)
DECODE_fsm.act("FADD5",
NextValue(self.DECODE_state, 7),
# 5. Rounding to nearest/even (FCS_FRM=0x00)
If(self.m3[0:3] == 0x7, # Remainder (all set?): REMAINDER(0) + GUARD(MSB) + STICKYBIT (ORed rest)
NextValue(self.s_bit, 1) # Indicate rounding
).Else(
NextValue(self.s_bit, 0), # Reset otherwise
),
NextValue(self.m3, self.m3 >> 3), # Remove R/G/S bits
NextState("FADD6")
)
DECODE_fsm.act("FADD6",
NextValue(self.DECODE_state, 8),
# 6. Normalization of result: Overflow
If(self.m3[24], # & 0x01000000,
NextValue(self.m3, self.m3 >> 1), # Adjust mantissa & increment exponent
NextValue(self.e3, self.e3 + 1)
).Else(
NextState("FADD7")
)
)
DECODE_fsm.act("FADD7",
# 7. Normalization: Result
NextValue(self.DECODE_state, 9),
If(~self.m3[23], # & 0x00800000),
NextValue(self.m3, self.m3 << 1), # Subtraction normalization
NextValue(self.e3, self.e3 - 1)
).Else(
If(self.s_bit, # Do we need rounding?!
NextValue(self.m3, self.m3 + self.s_bit),
NextState("FADD8") # Adjust possible overflow ...
).Else( # Nope, all ready
NextState("FADD9")
)
)
)
DECODE_fsm.act("FADD8",
NextValue(self.DECODE_state, 10),
If(self.m3[24], # & 0x01000000, # Overflow?
NextValue(self.m3, self.m3 >> 1), # Adjust mantissa & increment exponent
NextValue(self.e3, self.e3 + 1)
),
NextState("FADD9")
)
DECODE_fsm.act("FADD9",
NextValue(self.DECODE_state, 11),
# 6. Build the actual resulting float
NextValue(regs.frd_wrport.dat_w, Cat(self.m3[0:23], self.e3+127, self.sign3)),
If((self.m3[0:23] != 0) | ((self.e3+127) != 0), # Not zero?
If(self.e3+127 == 1, # FLT_MIN range
NextValue(regs.fcs, regs.fcs | 0x02), # UF: Underflow
If(regs.fcs[5:8] == 0x01, # RTZ rounding
NextValue(regs.frd_wrport.dat_w, 0), # FLT_MIN -> Round to zero -> 0.0!
)
)
),
NextValue(self.fwrite, 1),
NextState("DECODE_WRITE")
)
)
def Risq5Decoder_testbench(r5d):
print("----- RISQ5 decoder testbench -----")
if __name__ == "__main__":
r5d = Risq5Decoder()
run_simulation(r5d, Risq5Decoder_testbench(r5d, vcd_name="instruction_decode.vcd", clocks={"sys":16}))
print("***** Instruction decoder file is passive ... ;) *****")
Loading…
Cancel
Save