From 292bf2d72269cb098f16a77a87e2d847f5ec7294 Mon Sep 17 00:00:00 2001 From: Madhanika Jayasimha Date: Fri, 5 Apr 2024 14:17:29 -0700 Subject: [PATCH 1/4] Avoid Module creation for Constant Gate scenarios --- lib/src/signals/logic.dart | 52 ++++++++++++++++-- test/gate_test.dart | 105 +++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 3 deletions(-) diff --git a/lib/src/signals/logic.dart b/lib/src/signals/logic.dart index 8c468f254..8de96bafc 100644 --- a/lib/src/signals/logic.dart +++ b/lib/src/signals/logic.dart @@ -319,13 +319,59 @@ class Logic { void operator <=(Logic other) => gets(other); /// Logical bitwise NOT. - Logic operator ~() => NotGate(this).out; + Logic operator ~() { + if (this is Const) { + if (value.isValid) { + if (value == LogicValue.of(0, width: width)) { + return Const(LogicValue.filled(width, LogicValue.one)); + } else if (value == LogicValue.filled(width, LogicValue.one)) { + return Const(LogicValue.of(0, width: width)); + } + } else { + return Const(LogicValue.x, width: width); + } + } + return NotGate(this).out; + } /// Logical bitwise AND. - Logic operator &(Logic other) => And2Gate(this, other).out; + Logic operator &(Logic other) { + if (this is Const || other is Const) { + if (value.isValid && other.value.isValid) { + if (value == LogicValue.of(0, width: width) || + other.value == LogicValue.of(0, width: width)) { + return Const(LogicValue.of(0, width: width)); + } else if (value == LogicValue.filled(width, LogicValue.one)) { + return other; + } else if (other.value == LogicValue.filled(width, LogicValue.one)) { + return this; + } + } else { + return Const(LogicValue.x, width: width); + } + } + return And2Gate(this, other).out; + } /// Logical bitwise OR. - Logic operator |(Logic other) => Or2Gate(this, other).out; + Logic operator |(Logic other) { + if (this is Const || other is Const) { + if (value.isValid && other.value.isValid) { + if (value == LogicValue.filled(width, LogicValue.one) || + other.value == LogicValue.filled(width, LogicValue.one)) { + return Const(LogicValue.filled(width, LogicValue.one)); + } else if (value == LogicValue.of(LogicValue.zero, width: width)) { + return other; + } else if (other.value == + LogicValue.of(LogicValue.zero, width: width)) { + return this; + } + } else { + return Const(LogicValue.x, width: width); + } + } + return Or2Gate(this, other).out; + } /// Logical bitwise XOR. Logic operator ^(Logic other) => Xor2Gate(this, other).out; diff --git a/test/gate_test.dart b/test/gate_test.dart index 117783848..057c96a5d 100644 --- a/test/gate_test.dart +++ b/test/gate_test.dart @@ -7,6 +7,8 @@ // 2021 May 7 // Author: Max Korbel +import 'dart:math'; + import 'package:rohd/rohd.dart'; import 'package:rohd/src/utilities/simcompare.dart'; import 'package:test/test.dart'; @@ -353,6 +355,109 @@ void main() { }); }); + group('Const input Gate test', () { + test('NotGate single bit Constant input', () async { + final a = Logic(); + final b = Const(LogicValue.zero, width: 1); + final c = Const(LogicValue.x, width: 1); + final d = Const(LogicValue.one, width: 1); + a.put(LogicValue.one); + + final result = ~b; + expect(result, isA()); + expect(result.value, equals(LogicValue.one)); + + final result2 = ~c; + expect(result2, isA()); + expect(result2.value, equals(LogicValue.x)); + + final result3 = ~d; + expect(result3, isA()); + expect(result3.value, equals(LogicValue.zero)); + }); + + test('NotGate Multi bit Constant input', () async { + final b = Const(bin('1111'), width: 4); + final c = Const(bin('0100'), width: 4); + final result = ~b; + + expect(result, isA()); + expect(result.value, equals(LogicValue.of(LogicValue.zero, width: 4))); + + final result2 = ~c; + expect(result2, isA()); + expect(result2.value, equals(LogicValue.of(11, width: 4))); + }); + + test('And2Gate Single bit Constant input', () async { + final a = Logic(); + final b = Const(LogicValue.zero, width: 1); + final c = Const(LogicValue.x, width: 1); + final d = Const(LogicValue.one, width: 1); + a.put(LogicValue.one); + + final result = a & b; + expect(result, isA()); + expect(result.value, equals(LogicValue.zero)); + + final result2 = a & c; + expect(result2, isA()); + expect(result2.value, equals(LogicValue.x)); + + final result3 = a & d; + expect(result3, isA()); + expect(result3.value, equals(a.value)); + }); + + test('And2Gate Multi bit Constant input', () async { + final a = Const(LogicValue.of(LogicValue.zero, width: 4)); + final b = Const(bin('1111'), width: 4); + final c = Const(bin('0100'), width: 4); + final result = a & c; + + expect(result, isA()); + expect(result.value, equals(LogicValue.of(LogicValue.zero, width: 4))); + + final result2 = b & c; + expect(result2, isA()); + expect(result2.value, equals(c.value)); + }); + + test('OR2Gate Single bit Constant input', () async { + final a = Logic(); + final b = Const(LogicValue.zero, width: 1); + final c = Const(LogicValue.x, width: 1); + final d = Const(LogicValue.one, width: 1); + a.put(LogicValue.one); + + final result = a | b; + expect(result, isA()); + expect(result.value, equals(a.value)); + + final result2 = a | c; + expect(result2, isA()); + expect(result2.value, equals(LogicValue.x)); + + final result3 = a | d; + expect(result3, isA()); + expect(result3.value, equals(LogicValue.one)); + }); + + test('OR2Gate Multi bit Constant input', () async { + final a = Const(LogicValue.of(LogicValue.zero, width: 4)); + final b = Const(bin('1111'), width: 4); + final c = Const(bin('0100'), width: 4); + final result = a | c; + + expect(result, isA()); + expect(result.value, equals(c.value)); + + final result2 = b | c; + expect(result2, isA()); + expect(result2.value, equals(LogicValue.filled(4, LogicValue.one))); + }); + }); + group('simcompare', () { test('NotGate single bit', () async { final gtm = GateTestModule(Logic(), Logic()); From 81734f2c8c26e1db7b42605af3b1e4578fef3ac3 Mon Sep 17 00:00:00 2001 From: Madhanika Jayasimha Date: Fri, 5 Apr 2024 14:51:40 -0700 Subject: [PATCH 2/4] Removed extra import --- test/gate_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/gate_test.dart b/test/gate_test.dart index 057c96a5d..3665164ec 100644 --- a/test/gate_test.dart +++ b/test/gate_test.dart @@ -7,8 +7,6 @@ // 2021 May 7 // Author: Max Korbel -import 'dart:math'; - import 'package:rohd/rohd.dart'; import 'package:rohd/src/utilities/simcompare.dart'; import 'package:test/test.dart'; From efa4b95b70167520182a07412830b9b4b44915cc Mon Sep 17 00:00:00 2001 From: Madhanika Jayasimha Date: Mon, 8 Apr 2024 16:37:03 -0700 Subject: [PATCH 3/4] Added changes based on comments --- lib/src/signals/logic.dart | 62 +++++++++-------------- test/gate_test.dart | 100 ++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 86 deletions(-) diff --git a/lib/src/signals/logic.dart b/lib/src/signals/logic.dart index 8de96bafc..60e19a912 100644 --- a/lib/src/signals/logic.dart +++ b/lib/src/signals/logic.dart @@ -319,35 +319,21 @@ class Logic { void operator <=(Logic other) => gets(other); /// Logical bitwise NOT. - Logic operator ~() { - if (this is Const) { - if (value.isValid) { - if (value == LogicValue.of(0, width: width)) { - return Const(LogicValue.filled(width, LogicValue.one)); - } else if (value == LogicValue.filled(width, LogicValue.one)) { - return Const(LogicValue.of(0, width: width)); - } - } else { - return Const(LogicValue.x, width: width); - } - } - return NotGate(this).out; - } + Logic operator ~() => this is Const ? Const(~value) : NotGate(this).out; /// Logical bitwise AND. Logic operator &(Logic other) { - if (this is Const || other is Const) { - if (value.isValid && other.value.isValid) { - if (value == LogicValue.of(0, width: width) || - other.value == LogicValue.of(0, width: width)) { - return Const(LogicValue.of(0, width: width)); - } else if (value == LogicValue.filled(width, LogicValue.one)) { - return other; - } else if (other.value == LogicValue.filled(width, LogicValue.one)) { - return this; - } - } else { - return Const(LogicValue.x, width: width); + if (this is Const && + other is Const && + value.isValid && + other.value.isValid) { + if (value == LogicValue.of(0, width: width) || + other.value == LogicValue.of(0, width: width)) { + return Const(LogicValue.of(0, width: width)); + } else if (value == LogicValue.filled(width, LogicValue.one)) { + return other; + } else if (other.value == LogicValue.filled(width, LogicValue.one)) { + return this; } } return And2Gate(this, other).out; @@ -355,19 +341,17 @@ class Logic { /// Logical bitwise OR. Logic operator |(Logic other) { - if (this is Const || other is Const) { - if (value.isValid && other.value.isValid) { - if (value == LogicValue.filled(width, LogicValue.one) || - other.value == LogicValue.filled(width, LogicValue.one)) { - return Const(LogicValue.filled(width, LogicValue.one)); - } else if (value == LogicValue.of(LogicValue.zero, width: width)) { - return other; - } else if (other.value == - LogicValue.of(LogicValue.zero, width: width)) { - return this; - } - } else { - return Const(LogicValue.x, width: width); + if (this is Const && + other is Const && + value.isValid && + other.value.isValid) { + if (value == LogicValue.filled(width, LogicValue.one) || + other.value == LogicValue.filled(width, LogicValue.one)) { + return Const(LogicValue.filled(width, LogicValue.one)); + } else if (value == LogicValue.of(LogicValue.zero, width: width)) { + return other; + } else if (other.value == LogicValue.of(LogicValue.zero, width: width)) { + return this; } } return Or2Gate(this, other).out; diff --git a/test/gate_test.dart b/test/gate_test.dart index 3665164ec..b58b7cd27 100644 --- a/test/gate_test.dart +++ b/test/gate_test.dart @@ -361,30 +361,25 @@ void main() { final d = Const(LogicValue.one, width: 1); a.put(LogicValue.one); - final result = ~b; - expect(result, isA()); - expect(result.value, equals(LogicValue.one)); + expect(~b, isA()); + expect((~b).value, equals(LogicValue.one)); - final result2 = ~c; - expect(result2, isA()); - expect(result2.value, equals(LogicValue.x)); + expect(~c, isA()); + expect((~c).value, equals(LogicValue.x)); - final result3 = ~d; - expect(result3, isA()); - expect(result3.value, equals(LogicValue.zero)); + expect(~d, isA()); + expect((~d).value, equals(LogicValue.zero)); }); test('NotGate Multi bit Constant input', () async { final b = Const(bin('1111'), width: 4); final c = Const(bin('0100'), width: 4); - final result = ~b; - expect(result, isA()); - expect(result.value, equals(LogicValue.of(LogicValue.zero, width: 4))); + expect(~b, isA()); + expect((~b).value, equals(LogicValue.of(LogicValue.zero, width: 4))); - final result2 = ~c; - expect(result2, isA()); - expect(result2.value, equals(LogicValue.of(11, width: 4))); + expect(~c, isA()); + expect((~c).value, equals(LogicValue.of(11, width: 4))); }); test('And2Gate Single bit Constant input', () async { @@ -394,31 +389,42 @@ void main() { final d = Const(LogicValue.one, width: 1); a.put(LogicValue.one); - final result = a & b; - expect(result, isA()); - expect(result.value, equals(LogicValue.zero)); + expect(a & b, isA()); + expect((a & b).value, equals(LogicValue.zero)); - final result2 = a & c; - expect(result2, isA()); - expect(result2.value, equals(LogicValue.x)); + expect(a & c, isA()); + expect((a & c).value, equals(LogicValue.x)); - final result3 = a & d; - expect(result3, isA()); - expect(result3.value, equals(a.value)); + expect(b & c, isA()); + expect((b & c).value, equals(LogicValue.zero)); + + expect(a & d, isA()); + expect((a & d).value, equals(a.value)); + + expect(b & d, isA()); + expect((b & d).value, equals(LogicValue.zero)); }); test('And2Gate Multi bit Constant input', () async { final a = Const(LogicValue.of(LogicValue.zero, width: 4)); - final b = Const(bin('1111'), width: 4); - final c = Const(bin('0100'), width: 4); - final result = a & c; + final b = Const('1111', width: 4); + final c = Const('0100', width: 4); + final d = Const(1, width: 32, fill: true); + final e = Const('10110', width: 32); + final z = Const('11111', width: 5); + final y = Const(LogicValue.of('11x01', width: 5)); - expect(result, isA()); - expect(result.value, equals(LogicValue.of(LogicValue.zero, width: 4))); + expect(a & c, isA()); + expect((a & c).value, equals(LogicValue.of(LogicValue.zero, width: 4))); - final result2 = b & c; - expect(result2, isA()); - expect(result2.value, equals(c.value)); + expect(b & c, isA()); + expect((b & c).value, equals(c.value)); + + expect(d & e, isA()); + expect((d & e).value, equals(LogicValue.of('10110', width: 32))); + + expect(y & z, isA()); + expect((y & z).value, equals(LogicValue.of('11x01', width: 5))); }); test('OR2Gate Single bit Constant input', () async { @@ -426,33 +432,33 @@ void main() { final b = Const(LogicValue.zero, width: 1); final c = Const(LogicValue.x, width: 1); final d = Const(LogicValue.one, width: 1); + final z = Const('11111', width: 5); + final y = Const(LogicValue.of('11x01', width: 5)); a.put(LogicValue.one); - final result = a | b; - expect(result, isA()); - expect(result.value, equals(a.value)); + expect(a | b, isA()); + expect((a | b).value, equals(a.value)); + + expect(a | c, isA()); + expect((a | c).value, equals(LogicValue.one)); - final result2 = a | c; - expect(result2, isA()); - expect(result2.value, equals(LogicValue.x)); + expect(a | d, isA()); + expect((a | d).value, equals(LogicValue.one)); - final result3 = a | d; - expect(result3, isA()); - expect(result3.value, equals(LogicValue.one)); + expect(y | z, isA()); + expect((y | z).value, equals(LogicValue.of('11111', width: 5))); }); test('OR2Gate Multi bit Constant input', () async { final a = Const(LogicValue.of(LogicValue.zero, width: 4)); final b = Const(bin('1111'), width: 4); final c = Const(bin('0100'), width: 4); - final result = a | c; - expect(result, isA()); - expect(result.value, equals(c.value)); + expect(a | c, isA()); + expect((a | c).value, equals(c.value)); - final result2 = b | c; - expect(result2, isA()); - expect(result2.value, equals(LogicValue.filled(4, LogicValue.one))); + expect(b | c, isA()); + expect((b | c).value, equals(LogicValue.filled(4, LogicValue.one))); }); }); From 8e7789b0927f8d40c5dcf64468f3e4b2667eabe1 Mon Sep 17 00:00:00 2001 From: Madhanika Jayasimha Date: Tue, 9 Jul 2024 12:13:51 -0700 Subject: [PATCH 4/4] Added fixes based on feedback --- lib/src/signals/logic.dart | 58 ++++++++++++++-------- test/gate_test.dart | 98 ++++++++++++++++++-------------------- 2 files changed, 83 insertions(+), 73 deletions(-) diff --git a/lib/src/signals/logic.dart b/lib/src/signals/logic.dart index 272a37ffb..9420de2f3 100644 --- a/lib/src/signals/logic.dart +++ b/lib/src/signals/logic.dart @@ -387,17 +387,25 @@ class Logic { /// Logical bitwise AND. Logic operator &(Logic other) { - if (this is Const && - other is Const && - value.isValid && - other.value.isValid) { - if (value == LogicValue.of(0, width: width) || - other.value == LogicValue.of(0, width: width)) { - return Const(LogicValue.of(0, width: width)); - } else if (value == LogicValue.filled(width, LogicValue.one)) { - return other; - } else if (other.value == LogicValue.filled(width, LogicValue.one)) { - return this; + if (this is Const && other is Const) { + return Const((this as Const).value & other.value); + } + Const? constOperand; + Logic? otherOperand; + + if (this is Const && value.isValid) { + constOperand = Const(this); + } else if (other is Const && other.value.isValid) { + constOperand = other; + otherOperand = this; + } + + if (constOperand != null) { + if (constOperand.value == LogicValue.filled(width, LogicValue.zero)) { + return Const(LogicValue.filled(width, LogicValue.zero)); + } else if (constOperand.value == + LogicValue.filled(width, LogicValue.one)) { + return otherOperand!; } } return And2Gate(this, other).out; @@ -405,17 +413,25 @@ class Logic { /// Logical bitwise OR. Logic operator |(Logic other) { - if (this is Const && - other is Const && - value.isValid && - other.value.isValid) { - if (value == LogicValue.filled(width, LogicValue.one) || - other.value == LogicValue.filled(width, LogicValue.one)) { + if (this is Const && other is Const) { + return Const((this as Const).value | other.value); + } + Const? constOperand; + Logic? otherOperand; + + if (this is Const && value.isValid) { + constOperand = Const(this); + } else if (other is Const && other.value.isValid) { + constOperand = other; + otherOperand = this; + } + + if (constOperand != null) { + if (constOperand.value == LogicValue.filled(width, LogicValue.one)) { return Const(LogicValue.filled(width, LogicValue.one)); - } else if (value == LogicValue.of(LogicValue.zero, width: width)) { - return other; - } else if (other.value == LogicValue.of(LogicValue.zero, width: width)) { - return this; + } else if (constOperand.value == + LogicValue.filled(width, LogicValue.zero)) { + return otherOperand!; } } return Or2Gate(this, other).out; diff --git a/test/gate_test.dart b/test/gate_test.dart index b58b7cd27..d405f0ff8 100644 --- a/test/gate_test.dart +++ b/test/gate_test.dart @@ -355,76 +355,70 @@ void main() { group('Const input Gate test', () { test('NotGate single bit Constant input', () async { - final a = Logic(); - final b = Const(LogicValue.zero, width: 1); - final c = Const(LogicValue.x, width: 1); - final d = Const(LogicValue.one, width: 1); - a.put(LogicValue.one); + final normalLogic = Logic(); + final const0 = Const(LogicValue.zero, width: 1); + final constX = Const(LogicValue.x, width: 1); + final const1 = Const(LogicValue.one, width: 1); + normalLogic.put(LogicValue.one); - expect(~b, isA()); - expect((~b).value, equals(LogicValue.one)); + expect(~const0, isA()); + expect((~const0).value, equals(LogicValue.one)); - expect(~c, isA()); - expect((~c).value, equals(LogicValue.x)); + expect(~constX, isA()); + expect((~constX).value, equals(LogicValue.x)); - expect(~d, isA()); - expect((~d).value, equals(LogicValue.zero)); + expect(~const1, isA()); + expect((~const1).value, equals(LogicValue.zero)); }); test('NotGate Multi bit Constant input', () async { - final b = Const(bin('1111'), width: 4); - final c = Const(bin('0100'), width: 4); + final const1 = Const(bin('1111'), width: 4); + final const4 = Const(bin('0100'), width: 4); - expect(~b, isA()); - expect((~b).value, equals(LogicValue.of(LogicValue.zero, width: 4))); + expect(~const1, isA()); + expect((~const1).value, equals(LogicValue.of(LogicValue.zero, width: 4))); - expect(~c, isA()); - expect((~c).value, equals(LogicValue.of(11, width: 4))); + expect(~const4, isA()); + expect((~const4).value, equals(LogicValue.of(11, width: 4))); }); test('And2Gate Single bit Constant input', () async { - final a = Logic(); - final b = Const(LogicValue.zero, width: 1); - final c = Const(LogicValue.x, width: 1); - final d = Const(LogicValue.one, width: 1); - a.put(LogicValue.one); - - expect(a & b, isA()); - expect((a & b).value, equals(LogicValue.zero)); - - expect(a & c, isA()); - expect((a & c).value, equals(LogicValue.x)); - - expect(b & c, isA()); - expect((b & c).value, equals(LogicValue.zero)); - - expect(a & d, isA()); - expect((a & d).value, equals(a.value)); - - expect(b & d, isA()); - expect((b & d).value, equals(LogicValue.zero)); + final normalLogic = Logic(); + final const0 = Const(LogicValue.zero); + final logicX = Logic(); + final const1 = Const(LogicValue.one); + normalLogic.put(LogicValue.one); + logicX.put(LogicValue.x); + + expect(normalLogic & const0, isA()); + expect((normalLogic & const0).value, equals(LogicValue.zero)); + expect(logicX & const0, isA()); + expect((logicX & const0).value, equals(LogicValue.zero)); + expect(normalLogic & const1, isA()); + expect((normalLogic & const1).value, equals(normalLogic.value)); + expect(normalLogic & logicX, isA()); + expect((normalLogic & logicX).value, equals(LogicValue.x)); + expect(const0 & const1, isA()); }); test('And2Gate Multi bit Constant input', () async { - final a = Const(LogicValue.of(LogicValue.zero, width: 4)); - final b = Const('1111', width: 4); - final c = Const('0100', width: 4); - final d = Const(1, width: 32, fill: true); - final e = Const('10110', width: 32); - final z = Const('11111', width: 5); - final y = Const(LogicValue.of('11x01', width: 5)); + final const1 = Const(bin('1111'), width: 4); + final const4 = Const(bin('0100'), width: 4); + final logic0 = Logic(width: 4)..put(LogicValue.zero); + final logic1 = Logic(width: 4)..put(LogicValue.one); + final logicX = Logic(width: 4)..put(LogicValue.x); - expect(a & c, isA()); - expect((a & c).value, equals(LogicValue.of(LogicValue.zero, width: 4))); + expect(const1 & const4, isA()); + expect((const1 & const4).value, equals(LogicValue.of('0100', width: 4))); - expect(b & c, isA()); - expect((b & c).value, equals(c.value)); + expect(logic0 & const1, isA()); + expect((logic0 & const1).value, equals(LogicValue.of('0000', width: 4))); - expect(d & e, isA()); - expect((d & e).value, equals(LogicValue.of('10110', width: 32))); + expect(logic1 & const1, isA()); + expect((logic1 & const1).value, equals(LogicValue.of('0001', width: 4))); - expect(y & z, isA()); - expect((y & z).value, equals(LogicValue.of('11x01', width: 5))); + expect(logicX & const1, isA()); + expect((logicX & const1).value, equals(LogicValue.of('xxxx', width: 4))); }); test('OR2Gate Single bit Constant input', () async {