diff --git a/lib/src/modules/conditional.dart b/lib/src/modules/conditional.dart index 306121f81..8c46498f6 100644 --- a/lib/src/modules/conditional.dart +++ b/lib/src/modules/conditional.dart @@ -697,6 +697,17 @@ abstract class Conditional { throw UninitializedSignalException(ssaDriver._ref.name); } + // if these are already connected, just skip it, we're fine already + if (ssaDriver.srcConnection != null && + ssaDriver.srcConnection == mappings[ssaDriver._ref]!) { + continue; + } + + // if these are the same signal, also just skip it + if (ssaDriver == mappings[ssaDriver._ref]!) { + continue; + } + ssaDriver <= mappings[ssaDriver._ref]!; } } diff --git a/test/pipeline_test.dart b/test/pipeline_test.dart index 0c05573ec..0ca43f9ed 100644 --- a/test/pipeline_test.dart +++ b/test/pipeline_test.dart @@ -69,6 +69,44 @@ class RVPipelineModule extends Module { } } +/// Based on a portion of the pipelined integer multiplier from ROHD-HCL +class PipelineWithMultiUseModule extends Module { + PipelineWithMultiUseModule(Logic a, Logic b) { + final clk = SimpleClockGenerator(10).clk; + a = addInput('a', a, width: 8); + b = addInput('b', b, width: 8); + + final mid = Logic(name: 'mid'); + final mid2 = Logic(name: 'mid2'); + + final out = addOutput('out'); + + final pipeline = Pipeline(clk, stages: [ + ...List.generate( + 3, + (row) => (p) { + final columnAdder = []; + final maxIndexA = a.width - 1; + + for (var column = maxIndexA; column >= row; column--) { + final tmpA = + column == maxIndexA || row == 0 ? Const(0) : p.get(a[column]); + final tmpB = p.get(a)[column - row] & p.get(b)[row]; + + columnAdder + ..add(p.get(mid) < tmpA + tmpB) + ..add(p.get(mid2) < tmpA + tmpB); + } + + return columnAdder; + }, + ), + ]); + + out <= pipeline.get(mid); + } +} + void main() { tearDown(() async { await Simulator.reset(); @@ -92,6 +130,21 @@ void main() { SimCompare.checkIverilogVector(pipem, vectors); }); + test('multiuse pipeline', () async { + final pipem = + PipelineWithMultiUseModule(Logic(width: 8), Logic(width: 8)); + await pipem.build(); + + // module is gibberish, just make sure it builds and stuff + final vectors = [ + Vector({'a': 1, 'b': 1}, {}), + Vector({'a': 2, 'b': 1}, {}), + Vector({'a': 2, 'b': 2}, {}), + ]; + await SimCompare.checkFunctionalVector(pipem, vectors); + SimCompare.checkIverilogVector(pipem, vectors); + }); + test('simple pipeline late add', () async { final pipem = SimplePipelineModuleLateAdd(Logic(width: 8)); await pipem.build(); diff --git a/test/ssa_test.dart b/test/ssa_test.dart index b8ef35a46..890c9a119 100644 --- a/test/ssa_test.dart +++ b/test/ssa_test.dart @@ -227,6 +227,29 @@ class SsaNested extends SsaTestModule { int model(int a) => SsaModAssignsOnly(Logic(width: 8)).model(a) + 1; } +class SsaMultiDep extends SsaTestModule { + SsaMultiDep(Logic a) : super(name: 'nested') { + a = addInput('a', a, width: 8); + final x = addOutput('x', width: 8); + final y = addOutput('y', width: 8); + + Combinational.ssa((s) { + final mid = Logic(name: 'mid', width: 8); + + final mid2 = s(mid) + 1; + + return [ + s(mid) < a + 1, + s(x) < mid2 + 1, + s(y) < mid2 + 1, + ]; + }); + } + + @override + int model(int a) => a + 3; +} + void main() { tearDown(() async { await Simulator.reset(); @@ -240,6 +263,7 @@ void main() { SsaChain(aInput), SsaMix(aInput), SsaNested(aInput), + SsaMultiDep(aInput), ]; group('ssa_test_module', () {