Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/components/fixed_point.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Fixed-point binary representation of numbers is useful several applications incl

## FixedPointValue

A [FixedPointValue](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPointValue-class.html) represents a signed or unsigned fixed-point value following the Q notation (Qm.n format) as introduced by [Texas Instruments](https://www.ti.com/lit/ug/spru565b/spru565b.pdf). It comprises an optional sign, integer part and/or a fractional part. [FixedPointValue](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPointValue-class.html)s can be constructed from individual fields or from a Dart [double](https://api.dart.dev/stable/3.6.0/dart-core/double-class.html), converted to Dart [double](https://api.dart.dev/stable/3.6.0/dart-core/double-class.html), can be compared and can be operated on (+, -, *, /).
A [FixedPointValue](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPointValue-class.html) represents a signed or unsigned fixed-point value following the Q notation (Qm.n format) as introduced by [Texas Instruments](https://www.ti.com/lit/ug/spru565b/spru565b.pdf). It comprises an optional sign, integer part and/or a fractional part. [FixedPointValue](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPointValue-class.html)s can be constructed from individual fields or from a Dart [double](https://api.dart.dev/stable/3.6.0/dart-core/double-class.html), converted to Dart [double](https://api.dart.dev/stable/3.6.0/dart-core/double-class.html), can be compared and can be operated on (+, -, *, /). A `FixedPointValuePopulator` can be used to construct `FixedPointValue` using different kinds of converters.

## FixedPoint

The [FixedPoint](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPoint-class.html) type is an extension of [Logic](https://intel.github.io/rohd/rohd/Logic-class.html) with additional attributes (signed or unsigned, integer width and fraction width). This type is provided to simplify the design of fixed-point arithmetic blocks.
The [FixedPoint](https://intel.github.io/rohd-hcl/rohd_hcl/FixedPoint-class.html) type is an extension of [LogicStructure](https://intel.github.io/rohd/rohd/LogicStructure-class.html) with additional attributes (signed or unsigned, integer width and fraction width). This type is provided to simplify the design of fixed-point arithmetic blocks.

## FixedToFloat

Expand Down
28 changes: 20 additions & 8 deletions lib/src/arithmetic/fixed_sqrt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,26 @@ class FixedPointSqrt extends FixedPointSqrtBase {
throw RohdHclException('Signed values not supported');
}

Logic solution =
FixedPoint(signed: a.signed, name: 'solution', m: a.m + 1, n: a.n + 1);
Logic remainder =
FixedPoint(signed: a.signed, name: 'remainder', m: a.m + 1, n: a.n + 1);
Logic subtractionValue =
FixedPoint(signed: a.signed, name: 'subValue', m: a.m + 1, n: a.n + 1);
Logic aLoc =
FixedPoint(signed: a.signed, name: 'aLoc', m: a.m + 1, n: a.n + 1);
Logic solution = FixedPoint(
signed: a.signed,
name: 'solution',
mWidth: a.integerWidth + 1,
nWidth: a.fractionWidth + 1);
Logic remainder = FixedPoint(
signed: a.signed,
name: 'remainder',
mWidth: a.integerWidth + 1,
nWidth: a.fractionWidth + 1);
Logic subtractionValue = FixedPoint(
signed: a.signed,
name: 'subValue',
mWidth: a.integerWidth + 1,
nWidth: a.fractionWidth + 1);
Logic aLoc = FixedPoint(
signed: a.signed,
name: 'aLoc',
mWidth: a.integerWidth + 1,
nWidth: a.fractionWidth + 1);

solution = Const(0, width: aLoc.width).named('solution');
remainder = Const(0, width: aLoc.width).named('remainder');
Expand Down
8 changes: 5 additions & 3 deletions lib/src/arithmetic/fixed_to_float.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class FixedToFloat extends Module {
final bias = float.floatingPointValue.bias;
final eMax = pow(2, float.exponent.width) - 2;
final iWidth = (1 +
max(log2Ceil(fixed.n),
max(log2Ceil(fixed.fractionWidth),
max(log2Ceil(fixed.width), float.exponent.width)))
.toInt();

Expand All @@ -82,7 +82,7 @@ class FixedToFloat extends Module {
..gets(mux(_convertedFloat.sign, fixed, fixed));
}

final maxShift = fixed.width - fixed.n + bias - 2;
final maxShift = fixed.width - fixed.fractionWidth + bias - 2;

final jBit = Logic(name: 'jBit', width: iWidth);
Logic estimatedJBit;
Expand Down Expand Up @@ -166,7 +166,9 @@ class FixedToFloat extends Module {
// Calculate biased exponent
final eRaw = mux(
absValueShifted[-1],
(Const(bias + fixed.width - fixed.n - 1, width: iWidth) - jBit)
(Const(bias + fixed.width - fixed.fractionWidth - 1,
width: iWidth) -
jBit)
.named('eShift'),
Const(0, width: iWidth))
.named('eRaw');
Expand Down
6 changes: 3 additions & 3 deletions lib/src/arithmetic/float_to_fixed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class FloatToFixed extends Module {
Logic? get overflow => tryOutput('overflow');

/// Internal representation of the output port
late final FixedPoint _fixed = FixedPoint(signed: true, m: m, n: n);
late final FixedPoint _fixed = FixedPoint(mWidth: m, nWidth: n);

/// Output fixed point port
late final FixedPoint fixed = _fixed.clone()..gets(output('fixed'));
Expand Down Expand Up @@ -151,10 +151,10 @@ class Float8ToFixed extends Module {
Logic get fixed => output('fixed');

/// Getter for Q23.9
FixedPoint get q23p9 => FixedPoint.of(fixed, signed: true, m: 23, n: 9);
FixedPoint get q23p9 => FixedPoint.of(fixed, mWidth: 23, nWidth: 9);

/// Getter for Q16.16
FixedPoint get q16p16 => FixedPoint.of(fixed, signed: true, m: 16, n: 16);
FixedPoint get q16p16 => FixedPoint.of(fixed, mWidth: 16, nWidth: 16);

/// Constructor
Float8ToFixed(Logic float, Logic mode, {super.name = 'Float8ToFixed'}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class FloatingPointSqrtSimple<FpType extends FloatingPoint>
final isExpOdd = deBiasExp[0];

// use fixed sqrt unit
final aFixed = FixedPoint(signed: false, m: 3, n: a.mantissa.width);
final aFixed =
FixedPoint(signed: false, mWidth: 3, nWidth: a.mantissa.width);
aFixed <=
[Const(1, width: 3), a.mantissa.getRange(0)].swizzle().named('aFixed');

Expand Down
100 changes: 67 additions & 33 deletions lib/src/arithmetic/signals/fixed_point_logic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,92 @@
// 2024 October 24
// Author: Soner Yaldiz <[email protected]>

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

/// A representation of (un)signed fixed-point logic following
/// Q notation (Qm.n format) as introduced by
/// (Texas Instruments)[https://www.ti.com/lit/ug/spru565b/spru565b.pdf].
class FixedPoint extends Logic {
/// [signed] indicates whether the representation is signed.
class FixedPoint extends LogicStructure {
/// The integer part of the fixed-point number.
Logic integer;

/// The fractional part of the fixed-point number.
Logic fraction;

/// Return true if signed
final bool signed;

/// [m] is the number of bits reserved for the integer part.
final int m;
/// [integerWidth] is the number of bits reserved for the integer part.
int get integerWidth => integer.width - (signed ? 1 : 0);

/// [n] is the number of bits reserved for the fractional part.
final int n;
/// [fractionWidth] is the number of bits reserved for the fractional part.
int get fractionWidth => fraction.width;

static int _fixedPointWidth(bool s, int a, int b) => s ? 1 + a + b : a + b;
/// Utility to keep track of the Logic structure name by attaching it
/// to the Logic signal name in the output Verilog.
static String _nameJoin(String? structName, String signalName) {
if (structName == null) {
return signalName;
}
return '${structName}_$signalName';
}

/// Constructs a [FixedPoint] signal.
FixedPoint(
{required this.signed,
required this.m,
required this.n,
super.name,
super.naming})
: super(width: _fixedPointWidth(signed, m, n)) {
if ((m < 0) | (n < 0)) {
throw RohdHclException('m and n must be non-negative');
}
if (max(m, n) == 0) {
throw RohdHclException('either m or n must be greater than zero');
}
}
{required int mWidth,
required int nWidth,
bool signed = true,
String? name})
: this._(
Logic(
width: mWidth + (signed ? 1 : 0),
name: _nameJoin(name, 'integer'),
naming: Naming.mergeable),
Logic(
width: nWidth,
name: _nameJoin(name, 'fraction'),
naming: Naming.mergeable),
signed,
name: name);

/// [FixedPoint] internal constructor.
FixedPoint._(this.integer, this.fraction, this.signed, {super.name})
: super([fraction, integer]);

/// Retrieve the [FixedPointValue] of this [FixedPoint] logical signal.
FixedPointValue get fixedPointValue =>
FixedPointValue(value: value, signed: signed, m: m, n: n);
FixedPointValue get fixedPointValue => valuePopulator().ofFixedPoint(this);

/// A [FixedPointValuePopulator] for values associated with this
/// [FloatingPoint] type.
@mustBeOverridden
FixedPointValuePopulator valuePopulator() => FixedPointValue.populator(
mWidth: integerWidth, nWidth: fractionWidth, signed: signed);

/// Clone for I/O ports.
@override
FixedPoint clone({String? name}) => FixedPoint(signed: signed, m: m, n: n);
FixedPoint clone({String? name}) =>
FixedPoint(signed: signed, mWidth: integerWidth, nWidth: fractionWidth);

/// Cast logic to fixed point
FixedPoint.of(Logic signal,
{required this.signed, required this.m, required this.n})
: super(width: _fixedPointWidth(signed, m, n)) {
this <= signal;
}
{required int mWidth, required int nWidth, bool signed = true})
: this._(signal.slice(nWidth + (signed ? mWidth : mWidth - 1), nWidth),
signal.slice(nWidth - 1, 0), signed,
name: signal.name);

@override
void put(dynamic val, {bool fill = false}) {
if (val is FixedPointValue) {
if ((signed != val.signed) | (m != val.m) | (n != val.n)) {
throw RohdHclException('Value is not compatible with signal.');
if ((signed != val.signed) |
(integerWidth != val.integerWidth) |
(fractionWidth != val.fractionWidth)) {
throw RohdHclException('Value is not compatible with signal. '
'Expected: signed=$signed, mWidth=$integerWidth, '
'nWidth=$fractionWidth. '
'Got: signed=${val.signed}, mWidth=${val.integerWidth}, '
'nWidth=${val.fractionWidth}.');
}
super.put(val.value);
} else {
Expand All @@ -74,7 +105,9 @@ class FixedPoint extends Logic {
if (other is! FixedPoint) {
throw RohdHclException('Input must be fixed point signal.');
}
if ((signed != other.signed) | (m != other.m) | (n != other.n)) {
if ((signed != other.signed) |
(integerWidth != other.integerWidth) |
(fractionWidth != other.fractionWidth)) {
throw RohdHclException('Inputs are not comparable.');
}
}
Expand Down Expand Up @@ -127,7 +160,8 @@ class FixedPoint extends Logic {
Logic _multiply(dynamic other) {
_verifyCompatible(other);
final product = Multiply(this, other).out;
return FixedPoint.of(product, signed: false, m: 2 * m, n: 2 * n);
return FixedPoint.of(product,
signed: false, mWidth: 2 * integerWidth, nWidth: 2 * fractionWidth);
}

/// Greater-than.
Expand All @@ -138,7 +172,7 @@ class FixedPoint extends Logic {
@override
Logic operator >=(dynamic other) => gte(other);

/// multiply
/// multiply: TODO(desmonddak): this needs tests
@override
Logic operator *(dynamic other) => _multiply(other);

Expand Down
Loading