@@ -141,7 +141,10 @@ abstract class _TwoInputBitwiseGate extends Module with InlineSystemVerilog {
141
141
late final Logic _in1 = input (_in1Name);
142
142
143
143
/// The output of this gate.
144
- late final Logic out = output (_outName);
144
+ late final Logic out = _outputSvWidthExpansion
145
+ // this is sub-optimal, but it's tricky to make special SV for it
146
+ ? BusSubset (output (_outName), 0 , width - 1 ).subset
147
+ : output (_outName);
145
148
146
149
/// The output of this gate.
147
150
///
@@ -155,6 +158,13 @@ abstract class _TwoInputBitwiseGate extends Module with InlineSystemVerilog {
155
158
/// The `String` representing the operation to perform in generated code.
156
159
final String _opStr;
157
160
161
+ /// The width of the inputs and outputs for this operation.
162
+ final int width;
163
+
164
+ /// If true, then the output generated SystemVerilog may have a larger width
165
+ /// than the inputs, which should be considered in generated verilog.
166
+ final bool _outputSvWidthExpansion;
167
+
158
168
/// Constructs a two-input bitwise gate for an abitrary custom functional
159
169
/// implementation.
160
170
///
@@ -163,22 +173,23 @@ abstract class _TwoInputBitwiseGate extends Module with InlineSystemVerilog {
163
173
/// String between the two input signal names (e.g. if [_opStr] was "&",
164
174
/// generated SystemVerilog may look like "a & b").
165
175
_TwoInputBitwiseGate (this ._op, this ._opStr, Logic in0, dynamic in1,
166
- {String name = 'gate2' })
167
- : super (name: name) {
176
+ {String name = 'gate2' , bool outputSvWidthExpansion = false })
177
+ : width = in0.width,
178
+ _outputSvWidthExpansion = outputSvWidthExpansion,
179
+ super (name: name) {
168
180
if (in1 is Logic && in0.width != in1.width) {
169
- throw Exception ('Input widths must match,'
170
- ' but found $in0 and $in1 with different widths.' );
181
+ throw PortWidthMismatchException .equalWidth (in0, in1);
171
182
}
172
183
173
- final in1Logic = in1 is Logic ? in1 : Const (in1, width: in0. width);
184
+ final in1Logic = in1 is Logic ? in1 : Const (in1, width: width);
174
185
175
186
_in0Name = Module .unpreferredName ('in0_${in0 .name }' );
176
187
_in1Name = Module .unpreferredName ('in1_${in1Logic .name }' );
177
188
_outName = Module .unpreferredName ('${in0 .name }_${name }_${in1Logic .name }' );
178
189
179
- addInput (_in0Name, in0, width: in0. width);
180
- addInput (_in1Name, in1Logic, width: in1Logic. width);
181
- addOutput (_outName, width: in0. width);
190
+ addInput (_in0Name, in0, width: width);
191
+ addInput (_in1Name, in1Logic, width: width);
192
+ addOutput (_outName, width: width + (_outputSvWidthExpansion ? 1 : 0 ) );
182
193
183
194
_setup ();
184
195
}
@@ -315,7 +326,7 @@ class _ShiftGate extends Module with InlineSystemVerilog {
315
326
late final String _inName;
316
327
317
328
/// Name for the shift amount input port of this module.
318
- late final String _shiftAmountName;
329
+ late String _shiftAmountName;
319
330
320
331
/// Name for the output port of this module.
321
332
late final String _outName;
@@ -338,6 +349,13 @@ class _ShiftGate extends Module with InlineSystemVerilog {
338
349
/// Whether or not this gate operates on a signed number.
339
350
final bool signed;
340
351
352
+ /// The width of the output for this operation.
353
+ final int width;
354
+
355
+ /// If true, then the output generated SystemVerilog may have a larger width
356
+ /// than the inputs, which should be considered in generated verilog.
357
+ final bool _outputSvWidthExpansion;
358
+
341
359
/// Constructs a two-input shift gate for an abitrary custom functional
342
360
/// implementation.
343
361
///
@@ -346,21 +364,34 @@ class _ShiftGate extends Module with InlineSystemVerilog {
346
364
/// String between the two input signal names (e.g. if [_opStr] was ">>",
347
365
/// generated SystemVerilog may look like "a >> b").
348
366
_ShiftGate (this ._op, this ._opStr, Logic in_, dynamic shiftAmount,
349
- {String name = 'gate2' , this .signed = false })
350
- : super (name: name) {
367
+ {String name = 'gate2' ,
368
+ this .signed = false ,
369
+ bool outputSvWidthExpansion = false })
370
+ : width = in_.width,
371
+ _outputSvWidthExpansion = outputSvWidthExpansion,
372
+ super (name: name) {
351
373
final shiftAmountLogic = shiftAmount is Logic
352
374
? shiftAmount
353
- : Const (LogicValue .ofInferWidth (shiftAmount));
375
+ : Const (_outputSvWidthExpansion
376
+ ? LogicValue .of (shiftAmount, width: width)
377
+ : LogicValue .ofInferWidth (shiftAmount));
354
378
355
379
_inName = Module .unpreferredName ('in_${in_ .name }' );
356
- _shiftAmountName =
357
- Module .unpreferredName ('shiftAmount_${shiftAmountLogic .name }' );
380
+
381
+ _shiftAmountName = 'shiftAmount_${shiftAmountLogic .name }' ;
382
+ if (! _outputSvWidthExpansion) {
383
+ // if we have width expansion, then we want to avoid any constants as
384
+ // the shift amount since that gets complicated...
385
+ // so as a proxy for now, just always shove a shiftAmount here
386
+ _shiftAmountName = Module .unpreferredName (_shiftAmountName);
387
+ }
388
+
358
389
_outName =
359
390
Module .unpreferredName ('${in_ .name }_${name }_${shiftAmountLogic .name }' );
360
391
361
392
addInput (_inName, in_, width: in_.width);
362
393
addInput (_shiftAmountName, shiftAmountLogic, width: shiftAmountLogic.width);
363
- addOutput (_outName, width: in_. width);
394
+ addOutput (_outName, width: width);
364
395
365
396
_setup ();
366
397
}
@@ -437,7 +468,8 @@ class Add extends _TwoInputBitwiseGate {
437
468
///
438
469
/// [in1] can be either a [Logic] or [int] .
439
470
Add (Logic in0, dynamic in1, {String name = 'add' })
440
- : super ((a, b) => a + b, '+' , in0, in1, name: name);
471
+ : super ((a, b) => a + b, '+' , in0, in1,
472
+ name: name, outputSvWidthExpansion: true );
441
473
}
442
474
443
475
/// A two-input subtraction module.
@@ -574,7 +606,8 @@ class ARShift extends _ShiftGate {
574
606
class LShift extends _ShiftGate {
575
607
/// Calculates the value of [in_] shifted left by [shiftAmount] .
576
608
LShift (Logic in_, dynamic shiftAmount, {String name = 'lshift' })
577
- : super ((a, shamt) => a << shamt, '<<' , in_, shiftAmount, name: name);
609
+ : super ((a, shamt) => a << shamt, '<<' , in_, shiftAmount,
610
+ name: name, outputSvWidthExpansion: true );
578
611
}
579
612
580
613
/// Performs a multiplexer/ternary operation.
0 commit comments