Repository: intel/rohd (dart)

Issue:
toRadixString should work for radix:10 even if the Logic is X or Z
### Describe the bug

If you have a Logic that has not been set yet, and you use toRadixString(radix:10)  (an alternative to .toInt(), with more features to support different radices and separators), the code throws due to the Z value.

### To Reproduce

Create a Logic:   final l = Logic();
Print it:    print (l.value.toRadixString(radix:10));

This will throw.

### Expected behavior

We should see the value printed out in radix form with X or Z.  With radix10, this is challenging as bitfields don't line up.
But the number of actual digits can be printed as X or Z.   Like 10'dZZZZ for a 4-digit or 11-bit Logic.

### Actual behavior

We see a throw on unassigned Logic.

### Additional: Dart SDK info

_No response_

### Additional: pubspec.yaml

_No response_

### Additional: Context

_No response_

Pull request:
<!-- Please make sure you check out the contribution guidelines before submitting a pull request! -->

## Description & Motivation

Bug fix to enable LogicValue.toRadixString(radix:10) to return a string with X or Z instead of throwing.

## Related Issue(s)

#542 

## Testing

Tests added with X and Z in their bit values, tested to ensure a string with appropriate X or Z is returned.

## Backwards-compatibility

> Is this a breaking change that will not be backwards-compatible? If yes, how so?

No.  Throwing was not an expected behavior.

## Documentation

> Does the change require any updates to documentation? If so, where? Are they included?

we don't have documentation on toRadixString except in code.  This will have to be included as we add more extensive documentation to the user guide:  best ways of printing LogicValue for debug.

Patch:
diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart
index cc6f456f6..cc9ce8c90 100644
--- a/lib/src/values/logic_value.dart
+++ b/lib/src/values/logic_value.dart
@@ -665,11 +665,14 @@ abstract class LogicValue implements Comparable<LogicValue> {
       final radixString =
           toBigInt().toUnsigned(width).toRadixString(radix).toUpperCase();
       reversedStr = _reverse(radixString);
-    } else {
-      if (radix == 10) {
-        throw LogicValueConversionException(
-            'Cannot support decimal strings with invalid bits');
+    } else if (radix == 10) {
+      final span = (width * math.log(2) / math.log(radix)).floor();
+      if (toRadixString().contains(RegExp('[xX]'))) {
+        reversedStr = 'X' * span;
+      } else {
+        reversedStr = 'Z' * span;
       }
+    } else {
       final span = (math.log(radix) / math.log(2)).ceil();
       final extendedStr =
           LogicValue.of(this, width: span * (width / span).ceil());
@@ -800,23 +803,14 @@ abstract class LogicValue implements Comparable<LogicValue> {
             if (RegExp('[xXzZ]').hasMatch(leadChar)) {
               shorter = span - 1;
             } else {
-              if (radix == 10) {
-                shorter = binaryLength -
-                    BigInt.parse(compressedStr, radix: 10)
-                        .toRadixString(2)
-                        .length;
-              } else {
-                shorter = span -
-                    BigInt.parse(leadChar, radix: radix)
-                        .toRadixString(2)
-                        .length;
-              }
+              shorter = span -
+                  BigInt.parse(leadChar, radix: radix).toRadixString(2).length;
             }
           } else {
             shorter = 0;
           }
         }
-        if (binaryLength - shorter > specifiedLength) {
+        if ((radix != 10) & (binaryLength - shorter > specifiedLength)) {
           throw LogicValueConstructionException(
               'ofRadixString: cannot represent '
               '$compressedStr in $specifiedLength');


Test patch:
diff --git a/test/logic_value_test.dart b/test/logic_value_test.dart
index c8f94be3f..9f19111c3 100644
--- a/test/logic_value_test.dart
+++ b/test/logic_value_test.dart
@@ -2140,6 +2140,25 @@ void main() {
             LogicValue.ofRadixString(lv.toRadixString(radix: i)), equals(lv));
       }
     });
+    test('radixString decimal case', () {
+      {
+        final lv = LogicValue.ofRadixString("12'bzz_zzz1_1011");
+        final ds = lv.toRadixString(radix: 10);
+        final dlv = LogicValue.ofRadixString(ds);
+        final ds2 = dlv.toRadixString(radix: 10);
+        expect(ds, equals(ds2));
+        expect(ds, equals("12'dZZZ"));
+      }
+      {
+        final lv = LogicValue.ofRadixString("12'bzz_zzx1_1011");
+        final ds = lv.toRadixString(radix: 10);
+        final dlv = LogicValue.ofRadixString(ds);
+        final ds2 = dlv.toRadixString(radix: 10);
+        expect(ds, equals(ds2));
+        expect(ds, equals("12'dXXX"));
+      }
+    });
+
     test('radixString small leading radix character', () {
       final lv = LogicValue.ofRadixString("10'b10_1010_0111");
       expect(lv.toRadixString(radix: 4), equals("10'q2_2213"));