Skip to content

Fixes: 204 #220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
84b36e4
* Added IndexGate and tests to fix issue#153
akshay-wankhede Sep 28, 2022
d27233c
Merge branch 'intel:main' into main
akshay-wankhede Sep 28, 2022
f56281e
* Fixed: throw exception when input is neither int nor Logic
akshay-wankhede Oct 5, 2022
e3d2495
* Fixed: comments, input names, made input signals private
akshay-wankhede Oct 5, 2022
bae42e8
* Fixed: index Logic by int/Logic tests
akshay-wankhede Oct 5, 2022
e0ddcc2
Merge branch 'main' into main
akshay-wankhede Oct 12, 2022
8fab660
* Updated: doc comments
akshay-wankhede Oct 12, 2022
c70ad07
* Fixed: formatting
akshay-wankhede Oct 12, 2022
2b860c0
*FIXED: lint
akshay-wankhede Oct 17, 2022
406af22
Merge branch 'main' into main
akshay-wankhede Oct 17, 2022
0696e81
* Fixed: formatting
akshay-wankhede Oct 18, 2022
3932d25
* Fixed: cascade methods
akshay-wankhede Oct 31, 2022
34a1122
* Fixed: operator[] return slice when input is an int
akshay-wankhede Oct 31, 2022
d09205a
* Fixed: lint
akshay-wankhede Oct 31, 2022
3f04dfe
* Fixed: doc comment
akshay-wankhede Nov 1, 2022
e6b853b
* Fixed: doc comments
akshay-wankhede Nov 1, 2022
39c05f3
Merge branch 'main' of https://github.com/intel/rohd
akshay-wankhede Nov 18, 2022
dd2e521
Merge branch 'main' of https://github.com/intel/rohd
akshay-wankhede Dec 6, 2022
1d62e76
* Added: single bit indexing tests
akshay-wankhede Dec 7, 2022
147bed0
* Fixed: test fails to delete temp dir before the simulator run returns
akshay-wankhede Dec 7, 2022
3c81f57
* Fixed: return $x instead of $x[0], in case the signal widht is 1; i…
akshay-wankhede Dec 7, 2022
a24ab5b
* Fixed: return $x instead of $x[0], in case the signal widht is 1; i…
akshay-wankhede Dec 7, 2022
dd911b1
* Refactored and corrected index out of bounds tests
akshay-wankhede Dec 8, 2022
018ca9d
* Fixed: out of bounds tests
akshay-wankhede Dec 9, 2022
067a22e
* During simulation: return LogicValue.x for an out of bounds index
akshay-wankhede Dec 9, 2022
598c5a6
* Fixed: doc comments and exception when bus width is > 1
akshay-wankhede Dec 9, 2022
76623c9
* Fixed: slice ignores indexes if widht == 1 and doc comments
akshay-wankhede Dec 9, 2022
c8e6e29
* Fixed: doc comments
akshay-wankhede Dec 19, 2022
7685eb6
* Added: test for [-1] indexed 1 bit signal
akshay-wankhede Dec 20, 2022
33f06ac
* Fixed: slice validation
akshay-wankhede Dec 20, 2022
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
12 changes: 11 additions & 1 deletion lib/src/logic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,10 @@ class Logic {
/// nextVal <= val[-9]; // Error!: allowed values [-8, 7]
/// nextVal <= val[8]; // Error!: allowed values [-8, 7]
/// ```
///
/// Note: When, indexed by a Logic value, out-of-bounds will always return an
/// invalid (LogicValue.x) value. This behavior is differs in simulation as
/// compared to the generated SystemVerilog. In the generated SystemVerilog,
/// [index] will be ignored, and the logic is returned as-is.
Logic operator [](dynamic index) {
if (index is Logic) {
return IndexGate(this, index).selection;
Expand All @@ -631,6 +634,7 @@ class Logic {
/// value will be reversed relative to the original signal.
/// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends)
///
///
/// ```dart
/// Logic nextVal = addOutput('nextVal', width: width);
/// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110"
Expand All @@ -648,6 +652,12 @@ class Logic {
(startIndex < 0) ? width + startIndex : startIndex;
final modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex;

if (width == 1 &&
modifiedEndIndex == 0 &&
modifiedEndIndex == modifiedStartIndex) {
return this;
}

// Create a new bus subset
return BusSubset(this, modifiedStartIndex, modifiedEndIndex).subset;
}
Expand Down
12 changes: 12 additions & 0 deletions lib/src/modules/bus.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class BusSubset extends Module with InlineSystemVerilog {

/// Constructs a [Module] that accesses a subset from [bus] which ranges
/// from [startIndex] to [endIndex] (inclusive of both).
/// When, [bus] has a width of '1', [startIndex] and [endIndex] are ignored
/// in the generated SystemVerilog.
BusSubset(Logic bus, this.startIndex, this.endIndex,
{super.name = 'bussubset'}) {
// If a converted index value is still -ve then it's an Index out of bounds
Expand Down Expand Up @@ -79,6 +81,11 @@ class BusSubset extends Module with InlineSystemVerilog {

/// Executes the functional behavior of this gate.
void _execute() {
if (original.width == 1) {
subset.put(original.value);
return;
}

if (endIndex < startIndex) {
subset.put(original.value.getRange(endIndex, startIndex + 1).reversed);
} else {
Expand All @@ -93,6 +100,11 @@ class BusSubset extends Module with InlineSystemVerilog {
}
final a = inputs[_original]!;

// When, input width is 1, ignore startIndex and endIndex
if (original.width == 1) {
return a;
}

// SystemVerilog doesn't allow reverse-order select to reverse a bus,
// so do it manually
if (startIndex > endIndex) {
Expand Down
14 changes: 11 additions & 3 deletions lib/src/modules/gates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -676,9 +676,11 @@ class IndexGate extends Module with InlineSystemVerilog {
/// Constructs a two-input bit index gate for an abitrary custom functional
/// implementation.
///
/// The bit [index] will be indexed as an output.
/// The signal will be indexed by [index] as an output.
/// [Module] is in-lined as SystemVerilog, it will use original[index], where
/// target is index's int value
/// When, the [original] has width '1', [index] is ignored in the generated
/// SystemVerilog.
IndexGate(Logic original, Logic index) : super() {
_originalName = 'original_${original.name}';
_indexName = Module.unpreferredName('index_${index.name}');
Expand All @@ -705,9 +707,10 @@ class IndexGate extends Module with InlineSystemVerilog {

/// Executes the functional behavior of this gate.
void _execute() {
if (_index.hasValidValue()) {
if (_index.hasValidValue() && _index.value.toInt() < _original.width) {
final indexVal = _index.value.toInt();
selection.put(_original.value.getRange(indexVal, indexVal + 1));
final outputValue = _original.value.getRange(indexVal, indexVal + 1);
selection.put(outputValue);
} else {
selection.put(LogicValue.x);
}
Expand All @@ -720,6 +723,11 @@ class IndexGate extends Module with InlineSystemVerilog {
}

final target = inputs[_originalName]!;

if (_original.width == 1) {
return target;
}

final idx = inputs[_indexName]!;
return '$target[$idx]';
}
Expand Down
1 change: 1 addition & 0 deletions test/config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void main() async {
final vcdContents = await File(temporaryDumpPath(dumpName)).readAsString();
expect(vcdContents, contains(version));

await Simulator.run();
deleteTemporaryDump(dumpName);
});
}
64 changes: 61 additions & 3 deletions test/gate_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -430,31 +430,89 @@ void main() {
expect(simResult, equals(true));
});

test('Index Logic by Logic test', () async {
test('Index Logic(8bit) by Logic test', () async {
final gtm = IndexGateTestModule(Logic(width: 8), Logic(width: 8));
await gtm.build();
final vectors = [
Vector({'original': 14, 'index': 0}, {'index_output': 0}),
Vector({'original': 14, 'index': 2}, {'index_output': 1}),
Vector({'original': 14, 'index': LogicValue.x},
{'index_output': LogicValue.x}),
Vector({'original': 14, 'index': 9}, {'index_output': LogicValue.x})
];
await SimCompare.checkFunctionalVector(gtm, vectors);
final simResult = SimCompare.iverilogVector(
gtm.generateSynth(), gtm.runtimeType.toString(), vectors,
signalToWidthMap: {'original': 8, 'index': 8});
expect(simResult, equals(true));
});

test('Index Logic(1bit) by Logic test', () async {
final gtm = IndexGateTestModule(Logic(), Logic(width: 8));
await gtm.build();
final vectors = [
Vector({'original': LogicValue.x, 'index': LogicValue.x},
{'index_output': LogicValue.x}),
Vector({'original': LogicValue.x, 'index': 0},
{'index_output': LogicValue.x})
{'index_output': LogicValue.x}),
Vector({'original': LogicValue.one, 'index': 0},
{'index_output': LogicValue.one}),
Vector({'original': LogicValue.zero, 'index': 0},
{'index_output': LogicValue.zero})
];
await SimCompare.checkFunctionalVector(gtm, vectors);
final simResult = SimCompare.iverilogVector(
gtm.generateSynth(), gtm.runtimeType.toString(), vectors,
signalToWidthMap: {'original': 8, 'index': 8});
signalToWidthMap: {'original': 1, 'index': 8, 'index_output': 1});
expect(simResult, equals(true));
});

test('Index Logic by an Integer test', () {
final testLogic = Logic(width: 8)..put(14);
final testLogicOne = Logic()..put(LogicValue.one);
final testLogicZero = Logic()..put(LogicValue.zero);
final testLogicInvalid = Logic()..put(LogicValue.x);

expect(testLogic[0].value.toInt(), 0);
expect(testLogic[2].value.toInt(), 1);

expect(testLogicOne[0].value.toInt(), 1);
expect(testLogicZero[0].value.toInt(), 0);
expect(testLogicInvalid[0].value, LogicValue.x);

expect(testLogicOne[-1].value.toInt(), 1);
expect(testLogicZero[-1].value.toInt(), 0);
expect(testLogicInvalid[-1].value, LogicValue.x);

expect(() => testLogic[10], throwsException);
expect(() => testLogicOne[1], throwsException);
expect(() => testLogicZero[1], throwsException);
expect(() => testLogicInvalid[1], throwsException);
});

test('index Logic(1bit) by Logic index out of bounds test', () {
final testLogicOne = Logic()..put(LogicValue.one);
final testLogicZero = Logic()..put(LogicValue.zero);
final invalidIndex = Logic(width: 8)..put(1);

expect(testLogicOne[invalidIndex].value, equals(LogicValue.x));
expect(testLogicZero[invalidIndex].value, equals(LogicValue.x));
});

test('slice 1 bit wide Logic test', () {
final testLogic = Logic(width: 8)..put(14);
final testLogicOne = Logic()..put(LogicValue.one);
final testLogicZero = Logic()..put(LogicValue.zero);
final testLogicInvalid = Logic()..put(LogicValue.x);

expect(testLogicOne.slice(0, 0), equals(testLogicOne));
expect(testLogicZero.slice(0, 0), equals(testLogicZero));
expect(testLogicInvalid.slice(0, 0), equals(testLogicInvalid));

expect(() => testLogic.slice(0, 10), throwsException);
expect(() => testLogicOne.slice(0, 1), throwsException);
expect(() => testLogicZero.slice(0, 1), throwsException);
expect(() => testLogicInvalid.slice(0, 1), throwsException);
});

test('Index Logic by does not accept input other than int or Logic', () {
Expand Down