fdiv ready, fsub 0-1 yields -4?

master
kaqu 2 years ago
parent 3c0d732020
commit 372802ffd3
  1. 2
      debugger/dbgeval.py
  2. 97
      libmodules/fpu_decode.py
  3. 5
      libmodules/instruction_decode.py
  4. 1
      software/source/flwstw.c

@ -232,6 +232,8 @@ def disassemble(opcode, pc):
msg = "fsub.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])
elif f7 == 0x08: # fmul
msg = "fmul.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])
elif f7 == 0x0C: # fdiv
msg = "fdiv.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])
elif f7 == 0x10: # sign injection/inverted/xor'ed
if f3 == 0x00:
msg = "fsgnj.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])

@ -29,6 +29,7 @@ class Risq5FPUDecoder(Module):
self.fadd = Signal()
self.fsub = Signal()
self.fmul = Signal()
self.fdiv = Signal()
self.fready = Signal() # Indicate ready
self.fwrite = Signal() # F-Extension: Do a write to a float register
@ -46,6 +47,7 @@ class Risq5FPUDecoder(Module):
self.s_bit = Signal() # Sticky bit (for rounding control)
self.branch1 = Signal() # Branch helpers
self.branch2 = Signal()
self.i = Signal(5) # Loop counter, range 0..31
FPU_fsm = FSM(reset_state="FPU_IDLE") # FSM starts idling ...
self.submodules += FPU_fsm
@ -61,21 +63,25 @@ class Risq5FPUDecoder(Module):
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")
).Elif(self.fmul & ~self.fready, # Triggers set & ready flag reset externally!
).Elif((self.fmul | self.fdiv) & ~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(regs.fs1[0:23], 1, 0)), # | 0x00800000
NextValue(self.m2, Cat(regs.fs2[0:23], 1, 0)), # | 0x00800000
NextState("FMUL1")
If(self.fmul, # Multiplication
NextState("FMUL1"),
).Else( # Division
NextState("FDIV1")
)
)
)
FPU_fsm.act("FADD1",
NextValue(self.FPU_state, 1),
# 1. Verify valid ranges 1st!
If((((regs.fs1 & 0x7FFFFFFF) == 0x7FFFFFFF) | ((regs.fs2 & 0x7FFFFFFF) == 0x7FFFFFFF))
If(((regs.fs1[0:31] == 0x7FFFFFFF) | (regs.fs2[0:31] == 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
@ -94,6 +100,20 @@ class Risq5FPUDecoder(Module):
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Elif(regs.fs1[0:31] == 0, # Nothing to add? (w/o sign!)
If(self.fsub, # Subtract yields negative result!
NextValue(regs.frd_wrport.dat_w, -regs.fs2), # Ready!
).Else( # Straight add
NextValue(regs.frd_wrport.dat_w, regs.fs2), # Ready!
),
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Elif(regs.fs2[0:31] == 0, # Nothing to add? (w/o sign!)
NextValue(regs.frd_wrport.dat_w, regs.fs1), # Ready!
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
@ -215,7 +235,7 @@ class Risq5FPUDecoder(Module):
FPU_fsm.act("FMUL1",
NextValue(self.FPU_state, 1),
# 0. Verify valid ranges 1st!
If(((regs.fs1 & 0x7FFFFFFF) == 0x7FFFFFFF) | ((regs.fs2 & 0x7FFFFFFF) == 0x7FFFFFFF),
If((regs.fs1[0:31] == 0x7FFFFFFF) | (regs.fs2[0:31] == 0x7FFFFFFF),
NextValue(regs.fcs, regs.fcs | 0x10), # NV: Invalid operation
NextValue(regs.frd_wrport.dat_w, 0x7FFFFFFF), # NAN
NextValue(self.fwrite, 1),
@ -232,7 +252,12 @@ class Risq5FPUDecoder(Module):
NextValue(regs.frd_wrport.dat_w, regs.fs2), # Return infinity
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
NextState("FPU_IDLE")
).Elif((regs.fs1[0:31] == 0) | (regs.fs2[0:31] == 0), # Nothing to multiply? (w/o sign!)
NextValue(regs.frd_wrport.dat_w, 0), # Result will be zero ...
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Else( # Ok, valid floats supplied ...
NextValue(self.sign3, self.sign1 ^ self.sign2), # 1. Calculate result sign
NextValue(self.e3, self.e1 + self.e2), # 2. Calculate resulting exponent (add!)
@ -285,6 +310,68 @@ class Risq5FPUDecoder(Module):
NextState("FRESULT")
) # End of fmul.s processing
FPU_fsm.act("FDIV1",
NextValue(self.FPU_state, 1),
# 0. Verify valid ranges 1st!
If((regs.fs1[0:31] == 0x7FFFFFFF) | (regs.fs2[0:31] == 0x7FFFFFFF) | ((regs.fs1[0:31] == 0) & (regs.fs2[0:31] == 0)),
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")
).Elif(regs.fs2 == 0, # Division by zero?
NextValue(regs.fcs, regs.fcs | 0x08), # DZ: Division by zero
If(self.sign3,
NextValue(regs.frd_wrport.dat_w, 0xFF800000), # - Infinity
).Else(
NextValue(regs.frd_wrport.dat_w, 0x7F800000), # + Infinity
),
NextValue(self.fwrite, 1),
NextValue(self.fready, 1),
NextState("FPU_IDLE")
).Else( # Ok, valid floats supplied ...
NextValue(self.sign3, self.sign1 ^ self.sign2), # 1. Calculate result sign
NextValue(self.e3, self.e1 - self.e2), # 2. Calculate resulting exponent (subtract!)
NextValue(self.m3, 0), # 3. Significant preparation
NextValue(self.i, 0), # Loop counter
NextState("FDIV2")
)
)
FPU_fsm.act("FDIV2",
If(self.i < 24,
NextValue(self.FPU_state, 2),
If(self.m1 < self.m2,
NextValue(self.m3, self.m3 << 1), # Append a zero
NextValue(self.m1, self.m1 << 1),
).Else( # Append a one
NextValue(self.m3, (self.m3 << 1) | 1),
NextValue(self.m1, (self.m1 - self.m2) << 1),
),
NextValue(self.i, self.i + 1)
).Else( # Loop exceeded
# 4. Normalization
NextValue(self.FPU_state, 3),
If(~self.m3[23], # & 0x00800000
NextValue(self.m3, self.m3 << 1), # Subtraction normalization
NextValue(self.e3, self.e3 - 1),
).Else(
NextState("FRESULT")
)
)
) # End of fdiv.s processing
if __name__ == "__main__":
print("***** Register file is passive ... ;) *****")

@ -335,7 +335,7 @@ class Risq5Decoder(Module):
).Elif(regs.f7 == 0x08, # fmul.s
NextValue(fpu_decoder.fmul, 1), # Post fmul.s indication
).Elif(regs.f7 == 0x0C, # fdiv.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
NextValue(fpu_decoder.fdiv, 1), # Post fdiv.s indication
).Elif(regs.f7 == 0x2C, # fsqrt.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f7 == 0x10, # sign injection/inverted/xor'ed ALL OK!
@ -405,7 +405,7 @@ class Risq5Decoder(Module):
NextValue(self.next, 1), # Indicate ready state to ALU
NextState("DECODE_IDLE") # No write!
).Else(
If(fpu_decoder.fadd | fpu_decoder.fsub | fpu_decoder.fmul, # FPU logic engaging?
If(fpu_decoder.fadd | fpu_decoder.fsub | fpu_decoder.fmul | fpu_decoder.fdiv, # FPU logic engaging?
NextState("FPU_WAIT") # Reset request within FPU_WAIT!
).Elif(self.div_instruction != 0, # M extension divide instruction?
If(regs.xs2s == 0x0, # RISC-V: Doesn't raise exception div/0!
@ -627,6 +627,7 @@ class Risq5Decoder(Module):
NextValue(fpu_decoder.fadd, 0), # Reset job queue triggers (because of NFA reentry later!)
NextValue(fpu_decoder.fsub, 0),
NextValue(fpu_decoder.fmul, 0),
NextValue(fpu_decoder.fdiv, 0),
NextState("DECODE_WRITE")
)
)

@ -8,6 +8,7 @@ static void start(void)
repeat: fadd.s f2,f0,f1 # f2 = f0 + f1 \n\
fsub.s f2,f0,f1 # f2 = f0 - f1 \n\
fmul.s f2,f0,f1 # f2 = f0 * f1 \n\
fdiv.s f2,f0,f1 # f2 = f0 / f1 \n\
j repeat # Loop ... \n\
lw x3,0(sp) # Load float from stack (test) \n\
lw x3,4(sp) # Load float from stack (test) \n\

Loading…
Cancel
Save