From 72b45fa7ebefaf0ddc51ae0abd23f22d22b61437 Mon Sep 17 00:00:00 2001 From: rajaXcodes Date: Fri, 25 Apr 2025 10:53:16 +0530 Subject: [PATCH] corrected regime bit generation and offset handling during subtraction --- src/main/scala/PositGenerator.scala | 55 ++++++++++++++++------------- src/test/scala/PositAddSpec.scala | 3 ++ 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/main/scala/PositGenerator.scala b/src/main/scala/PositGenerator.scala index a2eecd8..2ad3b42 100644 --- a/src/main/scala/PositGenerator.scala +++ b/src/main/scala/PositGenerator.scala @@ -1,10 +1,11 @@ package hardposit import chisel3._ -import chisel3.util.{Cat, MuxCase} +import chisel3.util.{Cat, Fill, MuxCase} class PositGenerator(val nbits: Int, val es: Int) extends Module with HasHardPositParams { override val desiredName = s"posit_${nbits}_generator" + val io = IO(new Bundle { val in = Input(new unpackedPosit(nbits, es)) val trailingBits = Input(UInt(trailingBitCount.W)) @@ -15,42 +16,46 @@ class PositGenerator(val nbits: Int, val es: Int) extends Module with HasHardPos val fraction = io.in.fraction(maxFractionBits - 1, 0) val negExp = io.in.exponent < 0.S - val regime = - Mux(negExp, -io.in.exponent(maxExponentBits - 1, es), io.in.exponent(maxExponentBits - 1, es)).asUInt - val exponent = io.in.exponent(if (es > 0) es - 1 else 0, 0) - val offset = - regime - (negExp & regime =/= (nbits - 1).U) + // Regime calculation (robust) + val k = (io.in.exponent >> es).asSInt + val regimeBits = Wire(UInt((nbits - 1).W)) + val regimeLength = Wire(UInt(log2Ceil(nbits).W)) + + when(k >= 0.S) { + regimeBits := Cat(Fill(k.asUInt + 1.U, 1.U(1.W)), 0.U((nbits - 1).W)) >> (nbits.U - (k.asUInt + 2.U)) + regimeLength := k.asUInt + 2.U + } .otherwise { + regimeBits := Cat(1.U(1.W), Fill((-k).asUInt, 0.U(1.W))) >> (nbits.U - ((-k).asUInt + 2.U)) + regimeLength := (-k).asUInt + 2.U + } + + val exponent = if (es > 0) io.in.exponent(es - 1, 0).asUInt else 0.U + val offset = regimeLength val expFrac = if (es > 0) - Cat(Mux(negExp, 1.U(2.W), 2.U(2.W)), exponent, fraction, io.trailingBits).asSInt + Cat(regimeBits, exponent, fraction, io.trailingBits).asSInt else - Cat(Mux(negExp, 1.U(2.W), 2.U(2.W)), fraction, io.trailingBits).asSInt + Cat(regimeBits, fraction, io.trailingBits).asSInt - //u => un ; T => Trimmed ; R => Rounded ; S => Signed + // u => un ; T => Trimmed ; R => Rounded ; S => Signed val uT_uS_posit = (expFrac >> offset)(nbits - 2 + trailingBitCount, 0).asUInt val uR_uS_posit = uT_uS_posit(nbits - 2 + trailingBitCount, trailingBitCount) val stickyBitMask = lowerBitMask(offset)(nbits - 3, 0) - val gr = - uT_uS_posit(trailingBitCount - 1, trailingBitCount - 2) + val gr = uT_uS_posit(trailingBitCount - 1, trailingBitCount - 2) val stickyBit = - io.stickyBit | (expFrac.asUInt & stickyBitMask).orR | { - if (trailingBitCount > 2) uT_uS_posit(trailingBitCount - 3, 0).orR - else false.B - } - val roundingBit = - Mux(uR_uS_posit.andR, false.B, - gr(1) & ~(~uR_uS_posit(0) & gr(1) & ~gr(0) & ~stickyBit)) - val R_uS_posit = uR_uS_posit + roundingBit + io.stickyBit | (expFrac.asUInt & stickyBitMask).orR | + (if (trailingBitCount > 2) uT_uS_posit(trailingBitCount - 3, 0).orR else false.B) - //Underflow Correction - val uFC_R_uS_posit = - Cat(0.U(1.W), R_uS_posit | isZero(R_uS_posit)) + val roundingBit = Mux(uR_uS_posit.andR, false.B, + gr(1) & ~(~uR_uS_posit(0) & gr(1) & ~gr(0) & ~stickyBit)) + val R_uS_posit = uR_uS_posit + roundingBit - val R_S_posit = - Mux(io.in.sign, ~uFC_R_uS_posit + 1.U, uFC_R_uS_posit) + // Underflow Correction + val uFC_R_uS_posit = Cat(0.U(1.W), R_uS_posit | isZero(R_uS_posit)) + val R_S_posit = Mux(io.in.sign, ~uFC_R_uS_posit + 1.U, uFC_R_uS_posit) io.out := Mux(io.in.isNaR, NaR, - Mux((io.in.fraction === 0.U) | io.in.isZero, zero, R_S_posit)) + Mux((io.in.fraction === 0.U) || io.in.isZero, zero, R_S_posit)) } diff --git a/src/test/scala/PositAddSpec.scala b/src/test/scala/PositAddSpec.scala index 2fe8630..f70fc33 100644 --- a/src/test/scala/PositAddSpec.scala +++ b/src/test/scala/PositAddSpec.scala @@ -155,4 +155,7 @@ class PositAddSpec extends AnyFlatSpec with ChiselScalatestTester with Matchers posit_add_test(8, 1, 0x42, 0x54, 0xBA, sub = true) posit_add_test(8, 1, 0xAC, 0xBE, 0xBA, sub = true) } + it should "return posit" in { + posit_add_test(32, 2, 1442843648, 1442840576, 2101346304, sub=true) +} }