fadd working!

master
kaqu 2 years ago
parent f4c5ba0fae
commit 555730c3f5
  1. 11
      debugger/dbgeval.py
  2. 11
      debugger/qt5dbg.py
  3. 211
      libmodules/instruction_decode.py
  4. 26
      libmodules/register_file.py
  5. 25
      software/source/flwstw.c

@ -226,7 +226,16 @@ def disassemble(opcode, pc):
elif op == 0x27: # F-Extension
msg = "fsw {0},{1}({2})".format(f_description[rs2], hex(imm_s), x_description[rs1])
elif op == 0x53: # R-Type (F-Extension)
if f7 == 0x70:
if f7 == 0x00: # fadd
msg = "fadd.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])
elif f3 == 0x01:
msg = "fsgnjn.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])
elif f3 == 0x02:
msg = "fsgnjx.s {0},{1},{2}".format(f_description[rd], f_description[rs1], f_description[rs2])
elif f7 == 0x70:
if f3 == 0x00:
msg = "fmv.x.s {0},{1}".format(x_description[rd], f_description[rs1])
else:

@ -321,10 +321,13 @@ class dbgWindow(QMainWindow):
for i in range(self.MAXLABEL): # Walk f<n> register file
self.wb.regs.risq5ext_b5_wb_reg_no.write(i) # Select register
val = self.wb.regs.risq5ext_b32_wb_freg_value_r.read() # Pick actual register risq5_b32_wb_reg_value_r
p = struct.pack("I",val) # Translate 32-bit value -> decimal float!
dz = struct.unpack("f", p)
self.txtFList[i].setText("{:6f}".format(dz[0]))
p = struct.pack("I",val) # Translate 32-bit value -> decimal float!
try:
dz = struct.unpack("f", p)
self.txtFList[i].setText("{:6f}".format(dz[0]))
except:
self.txtFList[i].setText("?0x{:08X}?".format(val))
pc = self.wb.regs.risq5ext_b32_PC.read()
self.txtPC.setText("0x{:08X}".format(pc))
opcode = self.wb.regs.risq5ext_b32_opcode.read()

@ -34,6 +34,7 @@ class Risq5Decoder(Module):
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.L1Below = Signal(reset_less=True)
self.L1Beyond = Signal(reset_less=True) # Local cache boundaries (only valid w/ branches!)
@ -66,6 +67,7 @@ class Risq5Decoder(Module):
self.DECODE_loaddelay = Signal(32, reset_less=True) # TODO: shorter! Load unit cache data load delay (8-bit: 24 for RAM)
self.opcode_invalid = Signal(reset_less=True)
# M extension: div/divu/rem/remu instruction stores
self.div_a = Signal((33,True), reset_less=True)
self.div_b = Signal((33,True), reset_less=True)
@ -75,7 +77,21 @@ class Risq5Decoder(Module):
self.div_remain = Signal(32, reset_less=True)
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
self.DECODE_state = Signal(9, reset_less=True) # Debugging support
@ -85,7 +101,8 @@ class Risq5Decoder(Module):
#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.fwrite, 0), # F-Extension: Trigger write frd reset
NextValue(self.fadd, 0), # F-Extension: fadd job trigger
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
@ -318,8 +335,14 @@ class Risq5Decoder(Module):
).Elif(regs.op == 0x4F, # R4-Type: fnmadd.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.op == 0x53, # R-Type
If(regs.f7 == 0x00, # fadd.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
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!
).Elif(regs.f7 == 0x04, # fsub.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f7 == 0x08, # fmul.s
@ -328,14 +351,15 @@ class Risq5Decoder(Module):
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f7 == 0x2C, # fsqrt.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f7 == 0x10, # sign injection
If(regs.f3 == 0x00, # fsgnj.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Elif(regs.f3 == 0x01, # fsgnjn.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
).Else( #regs.f3 == 0x02, # fsgnjx.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
)
).Elif(regs.f7 == 0x10, # sign injection/inverted/xor'ed ALL OK!
If(regs.f3 == 0x00, # fsgnj.s rd, rs1, rs2 (copy rs2 sign to rs1 -> rd)
NextValue(regs.frd_wrport.dat_w, Cat(regs.fs1[0:31], regs.fs2[31])),
).Elif(regs.f3 == 0x01, # fsgnjn.s rd, rs1, rs2 (copy negated rs2 sign to rs1 -> rd)
NextValue(regs.frd_wrport.dat_w, Cat(regs.fs1[0:31], ~regs.fs2[31])),
).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
).Elif(regs.f7 == 0x14, # fmin/max
If(regs.f3 == 0x00, # fmin.s
NextValue(self.DECODE_state, 0x0F), # Dummy action
@ -349,7 +373,7 @@ class Risq5Decoder(Module):
NextValue(self.DECODE_state, 0x0F), # Dummy action
)
).Elif(regs.f7 == 0x70, # fmv/fclass
If(regs.f3 == 0x00, # fmv.x.s rd, frs1 (f-reg -> x-reg)
If(regs.f3 == 0x00, # fmv.x.s rd, frs1 (f-reg -> x-reg) OK!
NextValue(regs.rd_wrport.dat_w, regs.fs1),
NextValue(self.write, 1), # Trigger write rd (x-reg)
).Else( #regs.f3 == 0x01, # fclass.s
@ -369,7 +393,7 @@ class Risq5Decoder(Module):
).Else( #regs.rs2 == 0x01, # fcvt.s.wu
NextValue(self.DECODE_state, 0x0F), # Dummy action
)
).Else( # regs.f7 == 0x78, # fmv.s.x frd, rs1 (x-reg -> f-reg)
).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)
)
@ -381,7 +405,7 @@ class Risq5Decoder(Module):
NextValue(regs.pc, regs.pc - 4), # Stick to current instruction (i.e. compensate)!
NextValue(self.L1Reload, 1), # Enforce cache reload
NextValue(self.opcode_invalid, 1), # Set invalid opcode indication
),
),
NextState("DECODE_WRITE") # Make sure rd can be written (if nec.)
)
)
@ -394,7 +418,10 @@ class Risq5Decoder(Module):
NextValue(self.next, 1), # Indicate ready state to ALU
NextState("DECODE_IDLE") # No write!
).Else(
If(self.div_instruction != 0, # M extension divide instruction?
If(self.fadd, # Branch helper: fadd logic engage
NextValue(self.fadd, 0), # Reset fadd job queue trigger (because of NFA reentry later!)
NextState("FADD1")
).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!)
NextValue(self.next, 1), # Next instruction may come now!
@ -609,6 +636,158 @@ class Risq5Decoder(Module):
)
)
#---------------------- 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),
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 -----")

@ -45,16 +45,23 @@ class Risq5RegisterFile(Module):
self.comb += [ # Opcode relay
# Common parts
self.op.eq(self.opcode[0:7]),
self.rd.eq(self.opcode[7:12]),
self.rd.eq(self.opcode[7:7+CPUREGADDRESSBITS]), # 12]),
self.f3.eq(self.opcode[12:15]),
self.rs1.eq(self.opcode[15:20]),
self.rs2.eq(self.opcode[20:25]),
self.rs1.eq(self.opcode[15:15+CPUREGADDRESSBITS]), # 20]),
self.rs2.eq(self.opcode[20:20+CPUREGADDRESSBITS]), # 25]),
# R-type
self.f7.eq(self.opcode[25:32]),
# I-type immediate (12 bits)
self.imm_i.eq(self.opcode[20:32]),
# S-type immediate (12 bits)
self.imm_s.eq(Cat(self.rd, self.f7)), # Concatenate bits from lower to higher bits
]
# S-type immediate (12 bits)
if CPUREGADDRESSBITS == 2:
self.comb += self.imm_s.eq(Cat(self.rd, 0,0,0, self.f7)), # Concatenate bits from lower to higher bits
else:
self.comb += self.imm_s.eq(Cat(self.rd, self.f7)), # Concatenate bits from lower to higher bits
self.comb += [ # Opcode relay
# B-type immediate (12 bits << 1 )
self.imm_b.eq(Cat(0, self.opcode[8:12], self.opcode[25:31], self.opcode[7], self.opcode[31])),
# U-type immediate (20 bits)
@ -128,6 +135,7 @@ class Risq5RegisterFile(Module):
# -------------------------- F extension ---------------------------------------------------
# Risq5 floating point unit (FPU extension)
# Instruction decode, 32 bit opcode parts --------------------------------------------------
self.fcs = Signal(32) # Float countrol & status register
self.frd = Signal(CPUREGADDRESSBITS, reset_less=True) # [11:7] Destination register
#self.rm = Signal(3, reset_less=True) # [14:12] Instruction type modifier
self.frs1 = Signal(CPUREGADDRESSBITS, reset_less=True) # [19:15] source register #1
@ -137,10 +145,10 @@ class Risq5RegisterFile(Module):
self.fwrite_ext_index = Signal(CPUREGADDRESSBITS, reset_less=True) # External write access (index)
self.comb += [ # Opcode relay: f-reg adressing
self.frd.eq(self.opcode[7:12]), # Write f-reg pointer
self.frs1.eq(self.opcode[15:20]), # Read f-reg pointer
self.frs2.eq(self.opcode[20:25]),
self.frs3.eq(self.opcode[27:32])
self.frd.eq(self.opcode[7:7+CPUREGADDRESSBITS]), # 12]), # Write f-reg pointer
self.frs1.eq(self.opcode[15:15+CPUREGADDRESSBITS]), # 20]), # Read f-reg pointer
self.frs2.eq(self.opcode[20:20+CPUREGADDRESSBITS]), # 25]),
self.frs3.eq(self.opcode[27:27+CPUREGADDRESSBITS]), # 32])
]
fregs = Memory(WORDSIZE, CPUREGS) #32) # 32-bit, 32 elements -> f0 .. f31

@ -5,11 +5,34 @@ static void start(void)
auipc ra,0 # Store current pc \n\
lui sp,%hi(0x40192000) # Setup stack pointer \n\
addi sp,sp,%lo(0x40192000) # s.a. \n\
repeat: fadd.s f2,f0,f1 # f2 = f0 + f1 (x1=Select/x2=rc) \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\
nop \n\
lui x3, %hi(0x01040000) # Load \n\
fmv.x.s x3,f0 # f0 -> x3 \n\
sw x3,0(sp) # Store to memory \n\
lui x3, %hi(0x3F800000) # Load \n\
sw x3,4(sp) # Store to memory \n\
lui x3, %hi(0x40000000) # Load \n\
sw x3,8(sp) # Store to memory \n\
lui x3, %hi(0x40600000) # Load \n\
sw x3,12(sp) # Store to memory \n\
nop \n\
flw f0,0(sp) # Load ft0 \n\
lw x3, 0(sp) \n\
flw f1,4(sp) # ... \n\
lw x3, 4(sp) \n\
flw f2,8(sp) # ... \n\
lw x3, 8(sp) \n\
flw f3,12(sp) # ... \n\
lw x3, 12(sp) \n\
nop \n\
fmv.s.x f0,x3 # x3 -> f0 \n\
fmv.s f1,f0 # Actually: fsgnj.s rd,rs,rs \n\
fneg.s f2,f1 # Actually: fsgnjn.s rd,rs,rs \n\
fabs.s f3,f2 # Actually: fsgnjx.s rd,rs,rs \n\
fmv.x.s x3,f3 # f3 -> x3 \n\
sw x3,0(sp) # Save to stack \n\
flw f0,0(sp) # Load float from stack \n\
nop # ... \n\

Loading…
Cancel
Save