From 5fe52007ec9235709329a594857cbdaff2496680 Mon Sep 17 00:00:00 2001 From: Aisha <87562264+aishasalim@users.noreply.github.com> Date: Tue, 21 Jul 2026 18:20:47 -0500 Subject: [PATCH] Return the original signal when replicating by 1 `Logic.replicate(1)` built a `ReplicationOp`, which emits a redundant `{1{...}}` in the generated SystemVerilog: assign rep1 = {1{a}}; Replicating once is a no-op, so return the signal directly instead. The generated output becomes: assign rep1 = a; `signExtend` already routes through `replicate`, so it inherits the same benefit: sign-extending a 1-bit signal to width 1, or any signal to its existing width, no longer emits a replication. Validation of non-positive multipliers is unaffected; those still reach `ReplicationOp` and throw `InvalidMultiplierException`. Adds tests for the returned signal identity and for the absence of `{1{` in generated SystemVerilog. The existing "multiply by 1" test only checked simulated values, which pass either way. Fixes #522 --- lib/src/signals/logic.dart | 8 ++++++++ test/replication_test.dart | 30 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/src/signals/logic.dart b/lib/src/signals/logic.dart index aca0e5b7c..f964d320a 100644 --- a/lib/src/signals/logic.dart +++ b/lib/src/signals/logic.dart @@ -962,8 +962,16 @@ class Logic { /// The input [multiplier] cannot be negative or 0; an exception will be /// thrown, otherwise. /// + /// If [multiplier] is 1, then this signal is returned directly, since + /// replicating once is a no-op and would otherwise generate a redundant + /// `1{...}` in the output SystemVerilog. + /// /// If [isNet], then the result will also be a net. Logic replicate(int multiplier) { + if (multiplier == 1) { + return this; + } + if (isNet) { // many SV simulators don't support replication of nets return List.generate(multiplier, (i) => this).swizzle(); diff --git a/test/replication_test.dart b/test/replication_test.dart index 79296a395..892dbf6c7 100644 --- a/test/replication_test.dart +++ b/test/replication_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Intel Corporation +// Copyright (C) 2023-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // replication_test.dart @@ -21,6 +21,13 @@ class ReplicationOpModule extends Module { } } +class SignExtendModule extends Module { + SignExtendModule(Logic a, int newWidth) { + a = addInput('a', a, width: a.width); + addOutput('b', width: newWidth) <= a.signExtend(newWidth); + } +} + void main() { group('Logic', () { tearDown(Simulator.reset); @@ -52,6 +59,27 @@ void main() { ], 1, originalWidth: 4); }); + test('multiply by 1 returns the original signal', () { + final a = Logic(width: 4); + expect(identical(a.replicate(1), a), isTrue); + }); + + test('multiply by 1 generates no replication in SystemVerilog', () async { + final mod = ReplicationOpModule(Logic(width: 4), 1); + await mod.build(); + final sv = mod.generateSynth(); + expect(sv, contains('assign b = a;')); + expect(sv, isNot(contains('{1{'))); + }); + + test('signExtend of a 1-bit signal by 1 generates no replication', + () async { + final mod = SignExtendModule(Logic(), 1); + await mod.build(); + final sv = mod.generateSynth(); + expect(sv, isNot(contains('{1{'))); + }); + test('multiply by 2 replicates the input signal twice', () async { await replicateVectors([ Vector({'a': 0}, {'b': 0}),