[SV] Introduce SV for op (#4879)

This introduces SV for operation e.g.:
```mlir
    sv.for %i = %c0_i2 to %c-1_i2 step %c1_i2 : i2 {
      %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
      %index = sv.array_index_inout %_RANDOM[%i] : !hw.inout<uarray<3xi32>>, i2
      sv.bpassign %index, %RANDOM : i32
    }
```
which corresponds to:
```verilog
 for (logic [1:0] i = 2'h0; i < 2'h3; i = i + 2'h1) begin
    _RANDOM[i] = `RANDOM;
 end
```

The `sv.for` operation in System Verilog defines a for statement that requires
three SSA operands: `lowerBounds`, `upperBound`, and `step`. It functions
similarly to `scf.for`, where the loop iterates the induction variable from
`lowerBound` to `upperBound` with a step size of `step`, i.e:

```
 for (logic ... indVar = lowerBound; indVar < upperBound; indVar += step) begin
  end
```

It's important to note that since we are using a bit precise type instead of a Verilog
`integer` type, users must be cautious about potential overflow. For example, if
you wish to iterate over all 2-bit values, you must use a 3-bit value as the
induction variable type.
This commit is contained in:
Hideto Ueno 2023-04-10 14:52:18 +09:00 committed by GitHub
parent 909c6dbb21
commit 7b8f3c2a43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 435 additions and 229 deletions

View File

@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpAsmInterface.td"
/// Ensure symbol is one of the hw module.* types
def isModuleSymbol : AttrConstraint<
@ -748,3 +749,50 @@ def ReadMemOp : SVOp<"readmem", [ProceduralOp]> {
let assemblyFormat =
"$dest `,` $filename `,` $base attr-dict `:` qualified(type($dest))";
}
def ForOp : SVOp<"for", [SingleBlock, NoTerminator, ProceduralOp,
ProceduralRegion, OpAsmOpInterface,
AllTypesMatch<["lowerBound", "upperBound", "step"]>]> {
let summary = "System verilog for loop";
let description = [{
The `sv.for` operation in System Verilog defines a for statement that requires
three SSA operands: `lowerBounds`, `upperBound`, and `step`. It functions
similarly to `scf.for`, where the loop iterates the induction variable from
`lowerBound` to `upperBound` with a step size of `step`, i.e:
```
for (logic ... indVar = lowerBound; indVar < upperBound; indVar += step) begin
end
```
It's important to note that since we are using a bit precise type instead of a Verilog
`integer` type, users must be cautious about potential overflow. For example, if
you wish to iterate over all 2-bit values, you must use a 3-bit value as the
induction variable type.
}];
let regions = (region SizedRegion<1>:$body);
let arguments = (ins HWIntegerType:$lowerBound,
HWIntegerType:$upperBound,
HWIntegerType:$step,
DefaultValuedAttr<StrAttr, "{}">:$inductionVarName);
let results = (outs);
let builders = [
OpBuilder<(ins "Value":$lowerBound, "Value":$upperBound,
"Value":$step, "StringRef":$inductionVarName,
"llvm::function_ref<void(BlockArgument)>": $thenCtor)>,
OpBuilder<(ins "int64_t":$lowerBound, "int64_t":$upperBound,
"int64_t":$step, "IntegerType": $type,
"StringRef":$inductionVarName,
"llvm::function_ref<void(BlockArgument)>": $thenCtor)>
];
let hasCustomAssemblyFormat = 1;
let hasCanonicalizeMethod = 1;
let extraClassDeclaration = [{
Block* getBodyBlock() { return &getBody().front(); }
Value getInductionVar() { return getBodyBlock()->getArgument(0); }
void getAsmBlockArgumentNames(mlir::Region &region,
mlir::OpAsmSetValueNameFn setNameFn);
}];
}

View File

@ -57,6 +57,8 @@ public:
ReadMemOp,
// Generate statements
GenerateOp, GenerateCaseOp,
// For statements
ForOp,
// Sampled value functiions
SampledOp>([&](auto expr) -> ResultType {
return thisCast->visitSV(expr, args...);
@ -165,6 +167,9 @@ public:
HANDLE(GenerateOp, Unhandled);
HANDLE(GenerateCaseOp, Unhandled);
// For loop.
HANDLE(ForOp, Unhandled);
// Sampled Value Functions
HANDLE(SampledOp, Unhandled);
#undef HANDLE

View File

@ -813,9 +813,13 @@ StringRef getVerilogValueName(Value val) {
if (auto *op = val.getDefiningOp())
return getSymOpName(op);
if (auto port = val.dyn_cast<BlockArgument>())
if (auto port = val.dyn_cast<BlockArgument>()) {
// If the value is defined by for op, use its associated verilog name.
if (auto forOp = dyn_cast<ForOp>(port.getParentBlock()->getParentOp()))
return forOp->getAttrOfType<StringAttr>("hw.verilogName");
return getPortVerilogName(port.getParentBlock()->getParentOp(),
port.getArgNumber());
}
assert(false && "unhandled value");
return {};
}
@ -2989,6 +2993,8 @@ private:
LogicalResult visitSV(GenerateOp op);
LogicalResult visitSV(GenerateCaseOp op);
LogicalResult visitSV(ForOp op);
void emitAssertionLabel(Operation *op, StringRef opName);
void emitAssertionMessage(StringAttr message, ValueRange args,
SmallPtrSetImpl<Operation *> &ops,
@ -3541,6 +3547,30 @@ LogicalResult StmtEmitter::visitSV(GenerateCaseOp op) {
return success();
}
LogicalResult StmtEmitter::visitSV(ForOp op) {
emitSVAttributes(op);
llvm::SmallPtrSet<Operation *, 8> ops;
startStatement();
auto inductionVarName = op->getAttrOfType<StringAttr>("hw.verilogName");
ps << "for (" << PP::ibox2 << "logic ";
ps.invokeWithStringOS([&](auto &os) {
emitter.emitTypeDims(op.getInductionVar().getType(), op.getLoc(), os);
});
ps << PP::nbsp << inductionVarName << " = ";
emitExpression(op.getLowerBound(), ops);
ps << "; " << PPExtString(inductionVarName) << " < ";
emitExpression(op.getUpperBound(), ops);
ps << "; " << PPExtString(inductionVarName) << " += ";
emitExpression(op.getStep(), ops);
ps << PP::end << ") begin";
setPendingNewline();
emitStatementBlock(op.getBody().getBlocks().front());
startStatement();
ps << "end";
emitLocationInfoAndNewLine(ops);
return success();
}
/// Emit the `<label>:` portion of an immediate or concurrent verification
/// operation. If a label has been stored for the operation through
/// `addLegalName` in the pre-pass, that label is used. Otherwise, if the

View File

@ -175,6 +175,8 @@ static void legalizeModuleLocalNames(HWModuleOp module,
// Otherwise, get a verilog name via `getSymOpName`.
nameEntries.emplace_back(
op, StringAttr::get(op->getContext(), getSymOpName(op)));
} else if (auto forOp = dyn_cast<ForOp>(op)) {
nameEntries.emplace_back(op, forOp.getInductionVarNameAttr());
} else if (isa<AssertOp, AssumeOp, CoverOp, AssertConcurrentOp,
AssumeConcurrentOp, CoverConcurrentOp>(op)) {
// Notice and renamify the labels on verification statements.

View File

@ -373,8 +373,7 @@ static bool rewriteSideEffectingExpr(Operation *op) {
// Check to see if this is already rewritten.
if (op->hasOneUse()) {
if (auto assign = dyn_cast<BPAssignOp>(*op->user_begin()))
if (isa_and_nonnull<RegOp, LogicOp>(assign.getDest().getDefiningOp()))
return false;
return false;
}
// Otherwise, we have to transform it. Insert a reg at the top level, make
@ -423,9 +422,15 @@ static bool hoistNonSideEffectExpr(Operation *op) {
// the top level of the module. We can tell this quite efficiently by
// looking for ops in a procedural region - because procedural regions
// live in graph regions but not visa-versa.
if (BlockArgument block = operand.dyn_cast<BlockArgument>()) {
// References to ports are always ok.
if (isa<hw::HWModuleOp>(block.getParentBlock()->getParentOp()))
return false;
cantHoist = true;
return true;
}
Operation *operandOp = operand.getDefiningOp();
if (!operandOp) // References to ports are always ok.
return false;
if (operandOp->getParentOp()->hasTrait<ProceduralRegion>()) {
cantHoist |= operandOp->getBlock() == op->getBlock();

View File

@ -20,6 +20,7 @@
#include "circt/Support/CustomDirectiveImpl.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/PatternMatch.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@ -976,6 +977,111 @@ void OrderedOutputOp::build(OpBuilder &builder, OperationState &result,
body();
}
//===----------------------------------------------------------------------===//
// ForOp
//===----------------------------------------------------------------------===//
void ForOp::build(OpBuilder &builder, OperationState &result,
int64_t lowerBound, int64_t upperBound, int64_t step,
IntegerType type, StringRef name,
llvm::function_ref<void(BlockArgument)> body) {
auto lb = builder.create<hw::ConstantOp>(result.location, type, lowerBound);
auto ub = builder.create<hw::ConstantOp>(result.location, type, upperBound);
auto st = builder.create<hw::ConstantOp>(result.location, type, step);
build(builder, result, lb, ub, st, name, body);
}
void ForOp::build(OpBuilder &builder, OperationState &result, Value lowerBound,
Value upperBound, Value step, StringRef name,
llvm::function_ref<void(BlockArgument)> body) {
OpBuilder::InsertionGuard guard(builder);
build(builder, result, lowerBound, upperBound, step, name);
auto *region = result.regions.front().get();
builder.createBlock(region);
BlockArgument blockArgument =
region->addArgument(lowerBound.getType(), result.location);
if (body)
body(blockArgument);
}
void ForOp::getAsmBlockArgumentNames(mlir::Region &region,
mlir::OpAsmSetValueNameFn setNameFn) {
auto *block = &region.front();
setNameFn(block->getArgument(0), getInductionVarNameAttr());
}
ParseResult ForOp::parse(OpAsmParser &parser, OperationState &result) {
auto &builder = parser.getBuilder();
Type type;
OpAsmParser::Argument inductionVariable;
OpAsmParser::UnresolvedOperand lb, ub, step;
// Parse the optional initial iteration arguments.
SmallVector<OpAsmParser::Argument, 4> regionArgs;
// Parse the induction variable followed by '='.
if (parser.parseOperand(inductionVariable.ssaName) || parser.parseEqual() ||
// Parse loop bounds.
parser.parseOperand(lb) || parser.parseKeyword("to") ||
parser.parseOperand(ub) || parser.parseKeyword("step") ||
parser.parseOperand(step) || parser.parseColon() ||
parser.parseType(type))
return failure();
regionArgs.push_back(inductionVariable);
// Resolve input operands.
regionArgs.front().type = type;
if (parser.resolveOperand(lb, type, result.operands) ||
parser.resolveOperand(ub, type, result.operands) ||
parser.resolveOperand(step, type, result.operands))
return failure();
// Parse the body region.
Region *body = result.addRegion();
if (parser.parseRegion(*body, regionArgs))
return failure();
// Parse the optional attribute list.
if (parser.parseOptionalAttrDict(result.attributes))
return failure();
if (!inductionVariable.ssaName.name.empty()) {
if (!isdigit(inductionVariable.ssaName.name[1]))
// Retrive from its SSA name.
result.attributes.append(
{builder.getStringAttr("inductionVarName"),
builder.getStringAttr(inductionVariable.ssaName.name.drop_front())});
}
return success();
}
void ForOp::print(OpAsmPrinter &p) {
p << " " << getInductionVar() << " = " << getLowerBound() << " to "
<< getUpperBound() << " step " << getStep();
p << " : " << getInductionVar().getType() << ' ';
p.printRegion(getRegion(),
/*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/false);
p.printOptionalAttrDict((*this)->getAttrs(), {"inductionVarName"});
}
LogicalResult ForOp::canonicalize(ForOp op, PatternRewriter &rewriter) {
APInt lb, ub, step;
if (matchPattern(op.getLowerBound(), mlir::m_ConstantInt(&lb)) &&
matchPattern(op.getUpperBound(), mlir::m_ConstantInt(&ub)) &&
matchPattern(op.getStep(), mlir::m_ConstantInt(&step)) &&
lb + step == ub) {
// Unroll the loop if it's executed only once.
op.getInductionVar().replaceAllUsesWith(op.getLowerBound());
replaceOpWithRegion(rewriter, op, op.getBodyRegion());
rewriter.eraseOp(op);
return success();
}
return failure();
}
//===----------------------------------------------------------------------===//
// Assignment statements
//===----------------------------------------------------------------------===//

View File

@ -542,25 +542,8 @@ void HWMemSimImpl::generateMemory(HWModuleOp op, FirMemory mem) {
return;
constexpr unsigned randomWidth = 32;
sv::RegOp randomMemReg;
b.create<sv::IfDefOp>("SYNTHESIS", std::function<void()>(), [&]() {
sv::RegOp randReg;
StringRef initvar;
// Declare variables for use by memory randomization logic.
if (!disableMemRandomization || !mem.initFilename.empty()) {
b.create<sv::IfDefOp>("RANDOMIZE_MEM_INIT", [&]() {
initvar = moduleNamespace.newName("initvar");
b.create<sv::VerbatimOp>("integer " + Twine(initvar) + ";\n");
randomMemReg = b.create<sv::RegOp>(
b.getIntegerType(llvm::divideCeil(mem.dataWidth, randomWidth) *
randomWidth),
b.getStringAttr("_RANDOM_MEM"),
b.getStringAttr(moduleNamespace.newName("_RANDOM_MEM")));
});
}
// Declare variables for use by register randomization logic.
SmallVector<sv::RegOp> randRegs;
if (!disableRegRandomization) {
b.create<sv::IfDefOp>("RANDOMIZE_REG_INIT", [&]() {
@ -576,36 +559,55 @@ void HWMemSimImpl::generateMemory(HWModuleOp op, FirMemory mem) {
}
});
}
auto randomMemReg = b.create<sv::RegOp>(
b.getIntegerType(llvm::divideCeil(mem.dataWidth, randomWidth) *
randomWidth),
b.getStringAttr("_RANDOM_MEM"));
b.create<sv::InitialOp>([&]() {
b.create<sv::VerbatimOp>("`INIT_RANDOM_PROLOG_");
// Memory randomization logic. The entire memory is randomized.
if (!disableMemRandomization) {
b.create<sv::IfDefProceduralOp>("RANDOMIZE_MEM_INIT", [&]() {
std::string verbatimForLoop;
llvm::raw_string_ostream s(verbatimForLoop);
s << "for (" << initvar << " = 0; " << initvar << " < " << mem.depth
<< "; " << initvar << " = " << initvar << " + 1) begin\n"
<< " {{0}} = ";
auto repetitionCount = llvm::divideCeil(mem.dataWidth, randomWidth);
if (repetitionCount > 1)
s << "{";
for (size_t i = 0; i != repetitionCount; ++i) {
if (i > 0)
s << ", ";
s << "{`RANDOM}";
}
if (repetitionCount > 1)
s << "}";
s << ";\n";
s << " Memory[" << initvar << "] = "
<< "{{0}}[" << mem.dataWidth - 1 << ":" << 0 << "];\n"
<< "end";
b.create<sv::VerbatimOp>(
verbatimForLoop, ValueRange{},
b.getArrayAttr({hw::InnerRefAttr::get(
op.getNameAttr(), randomMemReg.getInnerSymAttr())}));
auto outerLoopIndVarType =
b.getIntegerType(llvm::Log2_64_Ceil(mem.depth + 1));
auto innerUpperBoundWidth = randomMemReg.getType()
.getElementType()
.cast<IntegerType>()
.getWidth();
auto innerLoopIndVarType =
b.getIntegerType(llvm::Log2_64_Ceil(innerUpperBoundWidth + 1));
// Construct the following nested for loops:
// ```
// for (int i = 0; i < mem.depth; i++) begin
// for (int j = 0; j < randomMeg.size; j += 32)
// randomMem[j+31:j] = `RANDOM
// Memory[i] = randomMem[mem.dataWidth - 1: 0];
// ```
b.create<sv::ForOp>(
0, mem.depth, 1, outerLoopIndVarType, "i",
[&](BlockArgument outerIndVar) {
b.create<sv::ForOp>(
0, innerUpperBoundWidth, randomWidth, innerLoopIndVarType,
"j", [&](BlockArgument innerIndVar) {
auto rhs = b.create<sv::MacroRefExprSEOp>(
b.getIntegerType(randomWidth), "RANDOM");
auto lhs = b.create<sv::IndexedPartSelectInOutOp>(
randomMemReg, innerIndVar, randomWidth, false);
b.create<sv::BPAssignOp>(lhs, rhs);
});
Value iterValue = outerIndVar;
// Truncate the induction variable if necessary.
if (!outerIndVar.getType().isInteger(
llvm::Log2_64_Ceil(mem.depth)))
iterValue = b.create<comb::ExtractOp>(
iterValue, 0, llvm::Log2_64_Ceil(mem.depth));
auto lhs = b.create<sv::ArrayIndexInOutOp>(reg, iterValue);
auto rhs = b.createOrFold<comb::ExtractOp>(
b.create<sv::ReadInOutOp>(randomMemReg), 0, mem.dataWidth);
b.create<sv::BPAssignOp>(lhs, rhs);
});
});
}

View File

@ -267,13 +267,40 @@ void FirRegLower::lower() {
builder.create<sv::IfDefProceduralOp>(randInitRef, [&] {
// Create randomization vector
SmallVector<Value> randValues;
for (uint64_t x = 0; x < (maxBit + 31) / 32; ++x) {
auto lhs = builder.create<sv::LogicOp>(
loc, builder.getIntegerType(32),
"_RANDOM_" + llvm::utostr(x));
auto rhs = builder.create<sv::MacroRefExprSEOp>(
loc, builder.getIntegerType(32), "RANDOM");
builder.create<sv::BPAssignOp>(loc, lhs, rhs);
auto numRandomCalls = (maxBit + 31) / 32;
auto logic = builder.create<sv::LogicOp>(
loc,
hw::UnpackedArrayType::get(builder.getIntegerType(32),
numRandomCalls),
"_RANDOM");
// Indvar's width must be equal to `ceil(log2(numRandomCalls +
// 1))` to avoid overflow.
auto inducionVariableWidth =
llvm::Log2_64_Ceil(numRandomCalls + 1);
auto arrayIndexWith = llvm::Log2_64_Ceil(numRandomCalls);
auto lb = getOrCreateConstant(
loc, APInt::getZero(inducionVariableWidth));
auto ub = getOrCreateConstant(
loc, APInt(inducionVariableWidth, numRandomCalls));
auto step =
getOrCreateConstant(loc, APInt(inducionVariableWidth, 1));
auto forLoop = builder.create<sv::ForOp>(
loc, lb, ub, step, "i", [&](BlockArgument iter) {
auto rhs = builder.create<sv::MacroRefExprSEOp>(
loc, builder.getIntegerType(32), "RANDOM");
Value iterValue = iter;
if (!iter.getType().isInteger(arrayIndexWith))
iterValue = builder.create<comb::ExtractOp>(
loc, iterValue, 0, arrayIndexWith);
auto lhs = builder.create<sv::ArrayIndexInOutOp>(
loc, logic, iterValue);
builder.create<sv::BPAssignOp>(loc, lhs, rhs);
});
builder.setInsertionPointAfter(forLoop);
for (uint64_t x = 0; x < numRandomCalls; ++x) {
auto lhs = builder.create<sv::ArrayIndexInOutOp>(
loc, logic,
getOrCreateConstant(loc, APInt(arrayIndexWith, x)));
randValues.push_back(lhs.getResult());
}
@ -282,6 +309,7 @@ void FirRegLower::lower() {
initialize(builder, svReg, randValues);
});
}
if (!asyncResets.empty()) {
// If the register is async reset, we need to insert extra
// initialization in post-randomization so that we can set the

View File

@ -1732,6 +1732,25 @@ hw.module @ConditionalComments() {
} // CHECK-NEXT: `endif // not def BAR
}
// CHECK-LABEL: module ForStatement
hw.module @ForStatement(%a: i5) -> () {
%_RANDOM = sv.logic : !hw.inout<uarray<3xi32>>
sv.initial {
%c-2_i2 = hw.constant -2 : i2
%c1_i2 = hw.constant 1 : i2
%c-1_i2 = hw.constant -1 : i2
%c0_i2 = hw.constant 0 : i2
// CHECK: for (logic [1:0] i = 2'h0; i < 2'h3; i += 2'h1) begin
// CHECK-NEXT: _RANDOM[i] = `RANDOM;
// CHECK-NEXT: end
sv.for %i = %c0_i2 to %c-1_i2 step %c1_i2 : i2 {
%RANDOM = sv.macro.ref.se< "RANDOM"> : i32
%index = sv.array_index_inout %_RANDOM[%i] : !hw.inout<uarray<3xi32>>, i2
sv.bpassign %index, %RANDOM : i32
}
}
}
// CHECK-LABEL: module intrinsic
hw.module @intrinsic(%clk: i1) -> (io1: i1, io2: i1, io3: i1, io4: i5) {

View File

@ -112,21 +112,23 @@ hw.module.generated @FIRRTLMem_1_1_1_16_10_0_1_0_0, @FIRRTLMem(%ro_addr_0: i4, %
//CHECK-NEXT: }
//CHECK-NEXT: sv.ifdef "SYNTHESIS" {
//CHECK-NEXT: } else {
//CHECK-NEXT: sv.ifdef "RANDOMIZE_MEM_INIT" {
//CHECK-NEXT: sv.verbatim "integer [[INITVAR:.+]];\0A"
//CHECK-NEXT: %[[RANDOM_MEM:.+]] = sv.reg sym @[[_RANDOM_MEM:.+]] : !hw.inout<i32>
//CHECK-NEXT: }
//CHECK-NEXT: sv.ifdef "RANDOMIZE_REG_INIT" {
//CHECK-NEXT: }
//CHECK-NEXT: %_RANDOM_MEM = sv.reg : !hw.inout<i32>
//CHECK-NEXT: sv.initial {
//CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
//CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_MEM_INIT" {
//CHECK-NEXT: sv.verbatim "for ([[INITVAR]] = 0; [[INITVAR]] < 10; [[INITVAR]] = [[INITVAR]] + 1) begin\0A
//CHECK-SAME{LITERAL}: {{0}} = {`RANDOM};\0A
//CHECK-SAME: Memory[[[INITVAR]]] =
//CHECK-SAME{LITERAL}: {{0}}[15:0];\0A
//CHECK-SAME: end"
//CHECK-SAME: {symbols = [#hw.innerNameRef<@FIRRTLMem_1_1_1_16_10_0_1_0_0::@[[_RANDOM_MEM]]>]}
//CHECK: sv.for %i = %c0_i4 to %c-6_i4 step %c1_i4 : i4 {
//CHECK: sv.for %j = %c0_i6 to %c-32_i6 step %c-32_i6_2 : i6 {
//CHECK: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
//CHECK: %[[PART_SELECT:.+]] = sv.indexed_part_select_inout %_RANDOM_MEM[%j : 32] : !hw.inout<i32>, i6
//CHECK: sv.bpassign %[[PART_SELECT]], %RANDOM : i32
//CHECK: }
//CHECK: %[[MEM_INDEX:.+]] = sv.array_index_inout %Memory[%i] : !hw.inout<uarray<10xi16>>, i4
//CHECK: %[[READ:.+]] = sv.read_inout %_RANDOM_MEM : !hw.inout<i32>
//CHECK: %[[EXTRACT:.+]] = comb.extract %[[READ]] from 0 : (i32) -> i16
//CHECK: sv.bpassign %[[MEM_INDEX]], %[[EXTRACT]] : i16
//CHECK: }
//CHECK-NEXT: }
//CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
//CHECK-NEXT: }
@ -294,7 +296,9 @@ hw.module.generated @PR2769, @FIRRTLMem(%ro_addr_0: i4, %ro_en_0: i1, %ro_clock_
// COMMON-LABEL: hw.module @RandomizeWeirdWidths
// CHECK: sv.ifdef.procedural "RANDOMIZE_MEM_INIT"
// CHECK-NEXT{LITERAL}: sv.verbatim "for (initvar = 0; initvar < 10; initvar = initvar + 1) begin\0A {{0}} = {{`RANDOM}, {`RANDOM}, {`RANDOM}, {`RANDOM}, {`RANDOM}};\0A Memory[initvar] = {{0}}[144:0];\0Aend"
// CHECK: %[[INOUT:.+]] = sv.array_index_inout %Memory[%i]
// CHECK: %[[EXTRACT:.+]] = comb.extract %{{.+}} from 0 : (i160) -> i145
// CHECK-NEXT: sv.bpassign %[[INOUT]], %[[EXTRACT]] : i145
hw.module.generated @RandomizeWeirdWidths, @FIRRTLMem(%ro_addr_0: i4, %ro_en_0: i1, %ro_clock_0: i1,%rw_addr_0: i4, %rw_en_0: i1, %rw_clock_0: i1, %rw_wmode_0: i1, %rw_wdata_0: i145, %wo_addr_0: i4, %wo_en_0: i1, %wo_clock_0: i1, %wo_data_0: i145) -> (ro_data_0: i145, rw_rdata_0: i145) attributes {depth = 10 : i64, numReadPorts = 1 : ui32, numReadWritePorts = 1 : ui32, numWritePorts = 1 : ui32, readLatency = 2 : ui32, readUnderWrite = 0 : ui32, width = 145 : ui32, writeClockIDs = [], writeLatency = 4 : ui32, writeUnderWrite = 0 : i32, initFilename = "", initIsBinary = false, initIsInline = false}
// COMMON-LABEL: hw.module @ReadWriteWithHighReadLatency

View File

@ -72,46 +72,37 @@ hw.module @lowering(%clk: i1, %rst: i1, %in: i32) -> (a: i32, b: i32, c: i32, d:
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM_0 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_0, %RANDOM : i32
// CHECK-NEXT: %_RANDOM_1 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_0 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_1, %RANDOM_0 : i32
// CHECK-NEXT: %_RANDOM_2 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_1 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_2, %RANDOM_1 : i32
// CHECK-NEXT: %_RANDOM_3 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_2 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_3, %RANDOM_2 : i32
// CHECK-NEXT: %_RANDOM_4 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_3 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_4, %RANDOM_3 : i32
// CHECK-NEXT: %_RANDOM_5 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_4 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_5, %RANDOM_4 : i32
// CHECK-NEXT: %_RANDOM_6 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_5 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_6, %RANDOM_5 : i32
// CHECK-NEXT: %_RANDOM_7 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_6 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_7, %RANDOM_6 : i32
// CHECK-NEXT: %8 = sv.read_inout %_RANDOM_0 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rA, %8 : i32
// CHECK-NEXT: %9 = sv.read_inout %_RANDOM_1 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rB, %9 : i32
// CHECK-NEXT: %10 = sv.read_inout %_RANDOM_2 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rC, %10 : i32
// CHECK-NEXT: %11 = sv.read_inout %_RANDOM_3 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rD, %11 : i32
// CHECK-NEXT: %12 = sv.read_inout %_RANDOM_4 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rE, %12 : i32
// CHECK-NEXT: %13 = sv.read_inout %_RANDOM_5 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rF, %13 : i32
// CHECK-NEXT: %14 = sv.read_inout %_RANDOM_6 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rAnamed, %14 : i32
// CHECK-NEXT: %15 = sv.read_inout %_RANDOM_7 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rNoSym, %15 : i32
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<8xi32>>
// CHECK-NEXT: sv.for %i = %c0_i4 to %c-8_i4 step %c1_i4 : i4 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %24 = comb.extract %i from 0 : (i4) -> i3
// CHECK-NEXT: %25 = sv.array_index_inout %_RANDOM[%24] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: sv.bpassign %25, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %8 = sv.array_index_inout %_RANDOM[%c0_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %9 = sv.array_index_inout %_RANDOM[%c1_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %10 = sv.array_index_inout %_RANDOM[%c2_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %11 = sv.array_index_inout %_RANDOM[%c3_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %12 = sv.array_index_inout %_RANDOM[%c-4_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %13 = sv.array_index_inout %_RANDOM[%c-3_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %14 = sv.array_index_inout %_RANDOM[%c-2_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %15 = sv.array_index_inout %_RANDOM[%c-1_i3] : !hw.inout<uarray<8xi32>>, i3
// CHECK-NEXT: %16 = sv.read_inout %8 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rA, %16 : i32
// CHECK-NEXT: %17 = sv.read_inout %9 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rB, %17 : i32
// CHECK-NEXT: %18 = sv.read_inout %10 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rC, %18 : i32
// CHECK-NEXT: %19 = sv.read_inout %11 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rD, %19 : i32
// CHECK-NEXT: %20 = sv.read_inout %12 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rE, %20 : i32
// CHECK-NEXT: %21 = sv.read_inout %13 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rF, %21 : i32
// CHECK-NEXT: %22 = sv.read_inout %14 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rAnamed, %22 : i32
// CHECK-NEXT: %23 = sv.read_inout %15 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %rNoSym, %23 : i32
// CHECK-NEXT: }
// CHECK-NEXT: sv.if %rst {
// CHECK-NEXT: sv.bpassign %rC, %c0_i32 : i32
@ -161,14 +152,19 @@ hw.module private @UninitReg1(%clock: i1, %reset: i1, %cond: i1, %value: i2) {
// CHECK-NEXT: sv.ifdef.procedural "INIT_RANDOM_PROLOG_" {
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM_0 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_0, %RANDOM : i32
// CHECK-NEXT: %3 = sv.read_inout %_RANDOM_0 : !hw.inout<i32>
// CHECK-NEXT: %4 = comb.extract %3 from 0 : (i32) -> i2
// CHECK-NEXT: sv.bpassign %count, %4 : i2
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<1xi32>>
// CHECK: sv.for %i = %{{false.*}} to %{{true.*}} step %{{true.*}} : i1 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %6 = comb.extract %i from 0 : (i1) -> i0
// CHECK-NEXT: %7 = sv.array_index_inout %_RANDOM[%6] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: sv.bpassign %7, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %3 = sv.array_index_inout %_RANDOM[%c0_i0] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: %4 = sv.read_inout %3 : !hw.inout<i32>
// CHECK-NEXT: %5 = comb.extract %4 from 0 : (i32) -> i2
// CHECK-NEXT: sv.bpassign %count, %5 : i2
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {
// CHECK-NEXT: sv.verbatim "`FIRRTL_AFTER_INITIAL"
@ -267,21 +263,21 @@ hw.module private @InitReg1(%clock: i1, %reset: i1, %io_d: i32, %io_en: i1) -> (
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM_0 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_0, %RANDOM : i32
// CHECK-NEXT: %_RANDOM_1 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_0 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_1, %RANDOM_0 : i32
// CHECK-NEXT: %_RANDOM_2 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_1 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_2, %RANDOM_1 : i32
// CHECK-NEXT: %8 = sv.read_inout %_RANDOM_0 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg, %8 : i32
// CHECK-NEXT: %9 = sv.read_inout %_RANDOM_1 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg2, %9 : i32
// CHECK-NEXT: %10 = sv.read_inout %_RANDOM_2 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg3, %10 : i32
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<3xi32>>
// CHECK-NEXT: sv.for %i = %c0_i2 to %c-1_i2 step %c1_i2 : i2 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %14 = sv.array_index_inout %_RANDOM[%i] : !hw.inout<uarray<3xi32>>, i2
// CHECK-NEXT: sv.bpassign %14, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %8 = sv.array_index_inout %_RANDOM[%c0_i2] : !hw.inout<uarray<3xi32>>, i2
// CHECK-NEXT: %9 = sv.array_index_inout %_RANDOM[%c1_i2] : !hw.inout<uarray<3xi32>>, i2
// CHECK-NEXT: %10 = sv.array_index_inout %_RANDOM[%c-2_i2] : !hw.inout<uarray<3xi32>>, i2
// CHECK-NEXT: %11 = sv.read_inout %8 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg, %11 : i32
// CHECK-NEXT: %12 = sv.read_inout %9 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg2, %12 : i32
// CHECK-NEXT: %13 = sv.read_inout %10 : !hw.inout<i32>
// CHECK-NEXT: sv.bpassign %reg3, %13 : i32
// CHECK-NEXT: }
// COMMON-NEXT: sv.if %reset {
// COMMON-NEXT: sv.bpassign %reg, %c0_i32 : i32
@ -315,18 +311,21 @@ hw.module private @UninitReg42(%clock: i1, %reset: i1, %cond: i1, %value: i42) {
// CHECK-NEXT: sv.ifdef.procedural "INIT_RANDOM_PROLOG_" {
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM_0 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_0, %RANDOM : i32
// CHECK-NEXT: %_RANDOM_1 = sv.logic : !hw.inout<i32>
// CHECK-NEXT: %RANDOM_0 = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: sv.bpassign %_RANDOM_1, %RANDOM_0 : i32
// CHECK-NEXT: %3 = sv.read_inout %_RANDOM_0 : !hw.inout<i32>
// CHECK-NEXT: %4 = sv.read_inout %_RANDOM_1 : !hw.inout<i32>
// CHECK-NEXT: %5 = comb.extract %4 from 0 : (i32) -> i10
// CHECK-NEXT: %6 = comb.concat %3, %5 : i32, i10
// CHECK-NEXT: sv.bpassign %count, %6 : i42
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<2xi32>>
// CHECK-NEXT: sv.for %i = %c0_i2 to %c-2_i2 step %c1_i2 : i2 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %9 = comb.extract %i from 0 : (i2) -> i1
// CHECK-NEXT: %10 = sv.array_index_inout %_RANDOM[%9] : !hw.inout<uarray<2xi32>>, i1
// CHECK-NEXT: sv.bpassign %10, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %3 = sv.array_index_inout %_RANDOM[%false] : !hw.inout<uarray<2xi32>>, i1
// CHECK-NEXT: %4 = sv.array_index_inout %_RANDOM[%true] : !hw.inout<uarray<2xi32>>, i1
// CHECK-NEXT: %5 = sv.read_inout %3 : !hw.inout<i32>
// CHECK-NEXT: %6 = sv.read_inout %4 : !hw.inout<i32>
// CHECK-NEXT: %7 = comb.extract %6 from 0 : (i32) -> i10
// CHECK-NEXT: %8 = comb.concat %5, %7 : i32, i10
// CHECK-NEXT: sv.bpassign %count, %8 : i42
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {
@ -338,53 +337,6 @@ hw.module private @UninitReg42(%clock: i1, %reset: i1, %cond: i1, %value: i42) {
hw.output
}
// COMMON-LABEL: hw.module private @regInitRandomReuse
hw.module private @regInitRandomReuse(%clock: i1, %a: i1) -> (o1: i2, o2: i4, o3: i32, o4: i100) {
%c0_i99 = hw.constant 0 : i99
%c0_i31 = hw.constant 0 : i31
%c0_i3 = hw.constant 0 : i3
%false = hw.constant false
%r1 = seq.firreg %0 clock %clock sym @__r1__ : i2
%r2 = seq.firreg %1 clock %clock sym @__r2__ : i4
%r3 = seq.firreg %2 clock %clock sym @__r3__ : i32
%r4 = seq.firreg %3 clock %clock sym @__r4__ : i100
%0 = comb.concat %false, %a : i1, i1
%1 = comb.concat %c0_i3, %a : i3, i1
%2 = comb.concat %c0_i31, %a : i31, i1
%3 = comb.concat %c0_i99, %a : i99, i1
// CHECK: %r1 = sv.reg sym @[[r1_sym:[_A-Za-z0-9]+]]
// CHECK: %r2 = sv.reg sym @[[r2_sym:[_A-Za-z0-9]+]]
// CHECK: %r3 = sv.reg sym @[[r3_sym:[_A-Za-z0-9]+]]
// CHECK: %r4 = sv.reg sym @[[r4_sym:[_A-Za-z0-9]+]]
// CHECK: sv.ifdef "SYNTHESIS" {
// CHECK-NEXT: } else {
// CHECK-NEXT: sv.ordered {
// CHECK-NEXT: sv.ifdef "FIRRTL_BEFORE_INITIAL" {
// CHECK-NEXT: sv.verbatim "`FIRRTL_BEFORE_INITIAL"
// CHECK-NEXT: }
// CHECK-NEXT: sv.initial {
// CHECK-NEXT: sv.ifdef.procedural "INIT_RANDOM_PROLOG_" {
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK: %9 = comb.extract %8 from 0 : (i32) -> i2
// CHECK: %11 = comb.extract %10 from 2 : (i32) -> i4
// CHECK: %13 = comb.extract %12 from 6 : (i32) -> i26
// CHECK: %15 = comb.extract %14 from 0 : (i32) -> i6
// CHECK: %16 = comb.concat %13, %15 : i26, i6
// CHECK: %18 = comb.extract %17 from 6 : (i32) -> i26
// CHECK: %22 = comb.extract %21 from 0 : (i32) -> i10
// CHECK: %23 = comb.concat %18, %19, %20, %22 : i26, i32, i32, i10
// CHECK: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {
// CHECK-NEXT: sv.verbatim "`FIRRTL_AFTER_INITIAL"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
hw.output %r1, %r2, %r3, %r4 : i2, i4, i32, i100
}
// COMMON-LABEL: hw.module private @init1DVector
hw.module private @init1DVector(%clock: i1, %a: !hw.array<2xi1>) -> (b: !hw.array<2xi1>) {
%r = seq.firreg %a clock %clock sym @__r__ : !hw.array<2xi1>
@ -407,14 +359,23 @@ hw.module private @init1DVector(%clock: i1, %a: !hw.array<2xi1>) -> (b: !hw.arra
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK: %1 = sv.read_inout %_RANDOM_0 : !hw.inout<i32>
// CHECK-NEXT: %2 = comb.extract %1 from 0 : (i32) -> i2
// CHECK-NEXT: %3 = sv.array_index_inout %r[%false] : !hw.inout<array<2xi1>>, i1
// CHECK-NEXT: %4 = comb.extract %2 from 1 : (i2) -> i1
// CHECK-NEXT: sv.bpassign %3, %4 : i1
// CHECK-NEXT: %5 = sv.array_index_inout %r[%true] : !hw.inout<array<2xi1>>, i1
// CHECK-NEXT: %6 = comb.extract %2 from 0 : (i2) -> i1
// CHECK-NEXT: sv.bpassign %5, %6 : i1
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<1xi32>>
// CHECK-NEXT: sv.for %i = %false to %true step %true : i1 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %8 = comb.extract %i from 0 : (i1) -> i0
// CHECK-NEXT: %9 = sv.array_index_inout %_RANDOM[%8] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: sv.bpassign %9, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %1 = sv.array_index_inout %_RANDOM[%c0_i0] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: %2 = sv.read_inout %1 : !hw.inout<i32>
// CHECK-NEXT: %3 = comb.extract %2 from 0 : (i32) -> i2
// CHECK-NEXT: %4 = sv.array_index_inout %r[%false] : !hw.inout<array<2xi1>>, i1
// CHECK-NEXT: %5 = comb.extract %3 from 1 : (i2) -> i1
// CHECK-NEXT: sv.bpassign %4, %5 : i1
// CHECK-NEXT: %6 = sv.array_index_inout %r[%true] : !hw.inout<array<2xi1>>, i1
// CHECK-NEXT: %7 = comb.extract %3 from 0 : (i2) -> i1
// CHECK-NEXT: sv.bpassign %6, %7 : i1
// CHECK: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {
@ -445,10 +406,19 @@ hw.module private @init2DVector(%clock: i1, %a: !hw.array<1xarray<1xi1>>) -> (b:
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK: %2 = comb.extract %1 from 0 : (i32) -> i1
// CHECK-NEXT: %3 = sv.array_index_inout %r[%c0_i0] : !hw.inout<array<1xarray<1xi1>>>, i0
// CHECK-NEXT: %4 = sv.array_index_inout %3[%c0_i0] : !hw.inout<array<1xi1>>, i0
// CHECK-NEXT: sv.bpassign %4, %2 : i1
// CHECK-NEXT: %_RANDOM = sv.logic : !hw.inout<uarray<1xi32>>
// CHECK-NEXT: sv.for %i = %false to %true step %true : i1 {
// CHECK-NEXT: %RANDOM = sv.macro.ref.se< "RANDOM"> : i32
// CHECK-NEXT: %6 = comb.extract %i from 0 : (i1) -> i0
// CHECK-NEXT: %7 = sv.array_index_inout %_RANDOM[%6] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: sv.bpassign %7, %RANDOM : i32
// CHECK-NEXT: }
// CHECK-NEXT: %1 = sv.array_index_inout %_RANDOM[%c0_i0] : !hw.inout<uarray<1xi32>>, i0
// CHECK-NEXT: %2 = sv.read_inout %1 : !hw.inout<i32>
// CHECK-NEXT: %3 = comb.extract %2 from 0 : (i32) -> i1
// CHECK-NEXT: %4 = sv.array_index_inout %r[%c0_i0] : !hw.inout<array<1xarray<1xi1>>>, i0
// CHECK-NEXT: %5 = sv.array_index_inout %4[%c0_i0] : !hw.inout<array<1xi1>>, i0
// CHECK-NEXT: sv.bpassign %5, %3 : i1
// CHECK: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {
@ -477,9 +447,9 @@ hw.module private @initStruct(%clock: i1) {
// CHECK-NEXT: sv.verbatim "`INIT_RANDOM_PROLOG_"
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef.procedural "RANDOMIZE_REG_INIT" {
// CHECK: %2 = comb.extract %1 from 0 : (i32) -> i1
// CHECK-NEXT: %3 = sv.struct_field_inout %r["a"] : !hw.inout<struct<a: i1>>
// CHECK-NEXT: sv.bpassign %3, %2 : i1
// CHECK: %[[EXTRACT:.*]] = comb.extract %{{.*}} from 0 : (i32) -> i1
// CHECK-NEXT: %[[INOUT:.*]] = sv.struct_field_inout %r["a"] : !hw.inout<struct<a: i1>>
// CHECK-NEXT: sv.bpassign %[[INOUT]], %[[EXTRACT]] : i1
// CHECK: }
// CHECK-NEXT: }
// CHECK-NEXT: sv.ifdef "FIRRTL_AFTER_INITIAL" {

View File

@ -26,39 +26,26 @@ circuit Foo:
q <= r
; ALL: automatic logic [31:0] _RANDOM_0;
; ALL-NEXT: automatic logic [31:0] _RANDOM_1;
; ALL-NEXT: automatic logic [31:0] _RANDOM_2;
; ALL-NEXT: automatic logic [31:0] _RANDOM_3;
; ALL: _RANDOM_0 = `RANDOM;
; ALL-NEXT: _RANDOM_1 = `RANDOM;
; ALL-NEXT: _RANDOM_2 = `RANDOM;
; ALL-NEXT: _RANDOM_3 = `RANDOM;
; ALL: automatic logic [31:0] _RANDOM[0:3];
; ALL: for (logic [2:0] i = 3'h0; i < 3'h4; i += 3'h1) begin
; ALL-NEXT: _RANDOM[i[1:0]] = `RANDOM;
; NAMED: automatic logic [31:0] _RANDOM_0;
; NAMED-NEXT: automatic logic [31:0] _RANDOM_1;
; NAMED-NEXT: automatic logic [31:0] _RANDOM_2;
; NAMED-NEXT: automatic logic [31:0] _RANDOM_3;
; NAMED: _RANDOM_0 = `RANDOM;
; NAMED-NEXT: _RANDOM_1 = `RANDOM;
; NAMED-NEXT: _RANDOM_2 = `RANDOM;
; NAMED-NEXT: _RANDOM_3 = `RANDOM;
; NAMED: automatic logic [31:0] _RANDOM[0:3];
; NAMED: for (logic [2:0] i = 3'h0; i < 3'h4; i += 3'h1) begin
; NAMED-NEXT: _RANDOM[i[1:0]] = `RANDOM;
; NONE: automatic logic [31:0] _RANDOM_0;
; NONE-NEXT: automatic logic [31:0] _RANDOM_1;
; NONE-NEXT: automatic logic [31:0] _RANDOM_2;
; NONE: _RANDOM_0 = `RANDOM;
; NONE-NEXT: _RANDOM_1 = `RANDOM;
; NONE-NEXT: _RANDOM_2 = `RANDOM;
; NONE: automatic logic [31:0] _RANDOM[0:2];
; NONE: for (logic [1:0] i = 2'h0; i < 2'h3; i += 2'h1) begin
; NONE-NEXT: _RANDOM[i] = `RANDOM;
; ALL: _r = {_RANDOM_0, _RANDOM_1[0]};
; ALL: _r = {_RANDOM[2'h0], _RANDOM[2'h1][0]};
; NAMED-NOT: _r =
; NONE-NOT: _r =
; ALL: r = {_RANDOM_1[31:1], _RANDOM_2[1:0]};
; NAMED: r = {_RANDOM_1[31:1], _RANDOM_2[1:0]};
; NONE: r = {_RANDOM_1[31:1], _RANDOM_2[1:0]};
; ALL: r = {_RANDOM[2'h1][31:1], _RANDOM[2'h2][1:0]};
; NAMED: r = {_RANDOM[2'h1][31:1], _RANDOM[2'h2][1:0]};
; NONE: r = {_RANDOM[2'h1][31:1], _RANDOM[2'h2][1:0]};
; ALL: s = {_RANDOM_2[31:2], _RANDOM_3[2:0]};
; NAMED: s = {_RANDOM_2[31:2], _RANDOM_3[2:0]};
; ALL: s = {_RANDOM[2'h2][31:2], _RANDOM[2'h3][2:0]};
; NAMED: s = {_RANDOM[2'h2][31:2], _RANDOM[2'h3][2:0]};
; NONE-NOT: s = {{.*}};