Skip to content

Commit

Permalink
extensive fp cleanup, support of Inf/NaN, addition of simple fp multi…
Browse files Browse the repository at this point in the history
…plier
  • Loading branch information
ganewto committed Jan 7, 2025
1 parent ef7002d commit 0b33234
Show file tree
Hide file tree
Showing 28 changed files with 2,083 additions and 669 deletions.
26 changes: 23 additions & 3 deletions doc/components/adder.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ROHD-HCL provides a set of adder modules to get the sum from a pair of Logic. So

- [Ripple Carry Adder](#ripple-carry-adder)
- [Parallel Prefix Adder](#parallel-prefix-adder)
- [One's Complement Adder Subtractor](#ones-complement-adder-subtractor)
- [Ones' Complement Adder Subtractor](#ones-complement-adder-subtractor)
- [Sign Magnitude Adder](#sign-magnitude-adder)
- [Compound Adder](#compound-adder)

Expand Down Expand Up @@ -50,7 +50,7 @@ Here is an example of instantiating a [ParallelPrefixAdder](https://intel.github

## Ones' Complement Adder Subtractor

A ones-complement adder (and subtractor) is useful in efficient arithmetic operations as the
A ones'-complement adder (and subtractor) is useful in efficient arithmetic operations as the
end-around carry can be bypassed and used later.

The [OnesComplementAdder](https://intel.github.io/rohd-hcl/rohd_hcl/OnesComplementAdder-class.html) can take a subtraction command as either a `Logic` `subtractIn` or a boolean `subtract` (the Logic overrides the boolean). If Logic `carry` is provided, the end-around carry is output on `carry` and the value will be one less than expected when `carry` is high. An `adderGen` adder function can be provided that generates your favorite internal adder (such as a parallel prefix adder).
Expand All @@ -76,7 +76,7 @@ Here is an example of instantiating a [OnesComplementAdder](https://intel.githu

## Sign Magnitude Adder

A sign magnitude adder is useful in situations where the sign of the addends is separated from their magnitude (e.g., not 2s complement), such as in floating point multipliers. The [SignMagnitudeAdder](https://intel.github.io/rohd-hcl/rohd_hcl/SignMagnitudeAdder-class.html) inherits from `Adder` but adds the `Logic` inputs for the two operands.
A sign magnitude adder is useful in situations where the sign of the addends is separated from their magnitude (e.g., not twos' complement), such as in floating point multipliers. The [SignMagnitudeAdder](https://intel.github.io/rohd-hcl/rohd_hcl/SignMagnitudeAdder-class.html) inherits from `Adder` but adds the `Logic` inputs for the two operands.

If you can supply the largest magnitude number first, then you can disable a comparator generation inside by declaring the `largestMagnitudeFirst` option as true.

Expand Down Expand Up @@ -137,3 +137,23 @@ final sum1 = rippleCarryAdder.sum1;
final rippleCarryAdder4BitBlock = CarrySelectCompoundAdder(a, b,
widthGen: CarrySelectCompoundAdder.splitSelectAdderAlgorithm4Bit);
```

## Native Adder

As logic synthesis can replace a '+' in RTL with a wide variety of adder architectures on its own, we have a [NativeAdder] wrapper class that allows you to use the native '+' with any component that exposes an [Adder] functor as a parameter:

```dart
// API definition: FloatingPointAdderRound(super.a, super.b,
// {Logic? subtract,
// super.clk,
// super.reset,
// super.enable,
// Adder Function(Logic, Logic, {Logic? carryIn}) adderGen =
// ParallelPrefixAdder.new,
// ParallelPrefix Function(List<Logic>, Logic Function(Logic, Logic))
// ppTree = KoggeStone.new,
// super.name = 'floating_point_adder_round'})
// Instantiate with a NativeAdder as the internal adder
final adder = FloatingPointAdderRound(a, b, adderGen: NativeAdder.new);
```
16 changes: 16 additions & 0 deletions lib/src/arithmetic/adder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,19 @@ class FullAdder extends Adder {
sum <= [carryIn! & (a ^ b) | a & b, (a ^ b) ^ carryIn!].swizzle();
}
}

/// A class which wraps the native '+' operator so that it can be passed
/// into other modules as a parameter for using the native operation.
class NativeAdder extends Adder {
/// The width of input [a] and [b] must be the same.
NativeAdder(super.a, super.b, {super.carryIn, super.name = 'native_adder'}) {
if (a.width != b.width) {
throw RohdHclException('inputs of a and b should have same width.');
}
if (carryIn != null) {
sum <= a.zeroExtend(a.width + 1) + b.zeroExtend(b.width + 1);
} else {
sum <= a.zeroExtend(a.width + 1) + b.zeroExtend(b.width + 1) + carryIn;
}
}
}
2 changes: 1 addition & 1 deletion lib/src/arithmetic/float_to_fixed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class FloatToFixed extends Module {
n = bias + float.mantissa.width - 1;
final outputWidth = m + n + 1;

final jBit = Logic(name: 'jBit')..gets(float.isNormal());
final jBit = Logic(name: 'jBit')..gets(float.isNormal);
final shift = Logic(name: 'shift', width: float.exponent.width)
..gets(
mux(jBit, float.exponent - 1, Const(0, width: float.exponent.width)));
Expand Down
3 changes: 3 additions & 0 deletions lib/src/arithmetic/floating_point/floating_point.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'floating_point_adder.dart';
export 'floating_point_adder_round.dart';
export 'floating_point_adder_simple.dart';
export 'floating_point_multiplier.dart';
export 'floating_point_multiplier_simple.dart';
73 changes: 73 additions & 0 deletions lib/src/arithmetic/floating_point/floating_point_adder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (C) 2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// floating_point_adder.dart
// An abstract base class defining the API for floating-point adders.
//
// 2025 January 3
// Author: Desmond A Kirkpatrick <[email protected]

import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';

/// An abstract API for floating point adders.
abstract class FloatingPointAdder extends Module {
/// Width of the output exponent field.
final int exponentWidth;

/// Width of the output mantissa field.
final int mantissaWidth;

/// The [clk]: if a valid clock signal is passed in, a pipestage is added to
/// the adder to help optimize frequency.
Logic? clk;

/// Optional [reset], used only if a [clk] is not null to reset the pipeline
/// flops.
Logic? reset;

/// Optional [enable], used only if a [clk] is not null to enable the pipeline
/// flops.
Logic? enable;

/// The first addend [ia], named this way to allow for a local variable 'a'.
@protected
late final FloatingPoint ia;

/// The second addend [ib], named this way to allow for a local variable 'b'.
@protected
late final FloatingPoint ib;

/// getter for the computed [FloatingPoint] output.
late final FloatingPoint sum =
FloatingPoint(exponentWidth: exponentWidth, mantissaWidth: mantissaWidth)
..gets(output('sum'));

/// Add two floating point numbers [a] and [b], returning result in [sum].
/// - [clk], [reset], [enable] are optional inputs to control a pipestage
/// (only inserted if [clk] is provided).
FloatingPointAdder(FloatingPoint a, FloatingPoint b,
{this.clk, this.reset, this.enable, super.name = 'floating_point_adder'})
: exponentWidth = a.exponent.width,
mantissaWidth = a.mantissa.width,
super() {
if (b.exponent.width != exponentWidth ||
b.mantissa.width != mantissaWidth) {
throw RohdHclException('FloatingPoint widths must match');
}
if (clk != null) {
clk = addInput('clk', clk!);
}
if (reset != null) {
reset = addInput('reset', reset!);
}
if (enable != null) {
enable = addInput('enable', enable!);
}
ia = a.clone()..gets(addInput('a', a, width: a.width));
ib = b.clone()..gets(addInput('b', b, width: b.width));

// addOutput('sum', width: exponentWidth + mantissaWidth + 1);
}
}
Loading

0 comments on commit 0b33234

Please sign in to comment.