| // Copyright 2024 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package common | |
| import chisel3._ | |
| import chisel3.util._ | |
| import chiseltest._ | |
| import org.scalatest.freespec.AnyFreeSpec | |
| import chisel3.experimental.BundleLiterals._ | |
| class Fp32Tester extends Module { | |
| val io = IO(new Bundle { | |
| val in = Input(UInt(32.W)) | |
| val is_zero = Output(Bool()) | |
| val is_inf = Output(Bool()) | |
| val is_nan = Output(Bool()) | |
| }) | |
| val fp = Fp32.fromWord(io.in) | |
| io.is_zero := fp.isZero() | |
| io.is_inf := fp.isInf() | |
| io.is_nan := fp.isNan() | |
| } | |
| class Fp32CvtuTester extends Module { | |
| val io = IO(new Bundle { | |
| val int = Input(UInt(32.W)) | |
| val fp = Output(new Fp32) | |
| }) | |
| io.fp := Fp32.fromInteger(io.int, false.B) | |
| } | |
| class Fp32CvtTester extends Module { | |
| val io = IO(new Bundle { | |
| val int = Input(SInt(32.W)) | |
| val fp = Output(new Fp32) | |
| }) | |
| io.fp := Fp32.fromInteger(io.int.asUInt, true.B) | |
| } | |
| class FpSpec extends AnyFreeSpec with ChiselScalatestTester { | |
| "Zero" in { | |
| test(new Fp32Tester()) { dut => | |
| dut.io.in.poke(0.U) | |
| assert(dut.io.is_zero.peekInt() == 1) | |
| assert(dut.io.is_inf.peekInt() == 0) | |
| assert(dut.io.is_nan.peekInt() == 0) | |
| } | |
| } | |
| "Inf" in { | |
| test(new Fp32Tester()) { dut => | |
| dut.io.in.poke(BigInt( | |
| "0" + "11111111" + "00000000000000000000000", 2)) | |
| assert(dut.io.is_zero.peekInt() == 0) | |
| assert(dut.io.is_inf.peekInt() == 1) | |
| assert(dut.io.is_nan.peekInt() == 0) | |
| dut.io.in.poke(BigInt( | |
| "1" + "11111111" + "00000000000000000000000", 2)) | |
| assert(dut.io.is_zero.peekInt() == 0) | |
| assert(dut.io.is_inf.peekInt() == 1) | |
| assert(dut.io.is_nan.peekInt() == 0) | |
| } | |
| } | |
| "Nan" in { | |
| test(new Fp32Tester()) { dut => | |
| dut.io.in.poke(BigInt( | |
| "0" + "11111111" + "00011000011000111000100", 2)) | |
| assert(dut.io.is_zero.peekInt() == 0) | |
| assert(dut.io.is_inf.peekInt() == 0) | |
| assert(dut.io.is_nan.peekInt() == 1) | |
| dut.io.in.poke(BigInt( | |
| "1" + "11111111" + "00011000011000111000100", 2)) | |
| assert(dut.io.is_zero.peekInt() == 0) | |
| assert(dut.io.is_inf.peekInt() == 0) | |
| assert(dut.io.is_nan.peekInt() == 1) | |
| } | |
| } | |
| "Convert UInt to Float" in { | |
| test(new Fp32CvtuTester) { dut => | |
| for (i <- 0 until 20000000 by 3000) { | |
| dut.io.int.poke(i) | |
| dut.clock.step() | |
| assertResult(i.toFloat) { PeekFloat(dut.io.fp) } | |
| } | |
| } | |
| } | |
| "Convert SInt to Float" in { | |
| test(new Fp32CvtTester) { dut => | |
| for (i <- -20000001 until 20000000 by 3000) { | |
| dut.io.int.poke(i) | |
| dut.clock.step() | |
| assertResult(i.toFloat) { PeekFloat(dut.io.fp) } | |
| } | |
| } | |
| } | |
| } |