CIRCT  20.0.0git
RandomizeRegisterInit.cpp
Go to the documentation of this file.
1 //===- RandomizeRegisterInit.cpp - Randomize register initialization ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the RandomizeRegisterInit pass.
10 //
11 //===----------------------------------------------------------------------===//
12 
17 #include "mlir/IR/Attributes.h"
18 #include "mlir/IR/Builders.h"
19 #include "mlir/Pass/Pass.h"
20 
21 namespace circt {
22 namespace firrtl {
23 #define GEN_PASS_DEF_RANDOMIZEREGISTERINIT
24 #include "circt/Dialect/FIRRTL/Passes.h.inc"
25 } // namespace firrtl
26 } // namespace circt
27 
28 using namespace mlir;
29 using namespace circt;
30 using namespace firrtl;
31 
32 namespace {
33 struct RandomizeRegisterInitPass
34  : public circt::firrtl::impl::RandomizeRegisterInitBase<
35  RandomizeRegisterInitPass> {
36  void runOnOperation() override;
37 };
38 
39 } // end anonymous namespace
40 
41 std::unique_ptr<mlir::Pass> circt::firrtl::createRandomizeRegisterInitPass() {
42  return std::make_unique<RandomizeRegisterInitPass>();
43 }
44 
45 /// Create attributes indicating the required size of random initialization
46 /// values for each register in the module, and mark which range of these values
47 /// each register should consume. The goal is for registers to always read the
48 /// same random bits for the same seed, regardless of optimizations that might
49 /// remove registers.
50 static void createRandomizationAttributes(FModuleOp mod) {
51  OpBuilder builder(mod);
52 
53  // Walk all registers.
54  uint64_t currentWidth = 0;
55  auto ui64Type = builder.getIntegerType(64, false);
56  mod.walk([&](Operation *op) {
57  if (!isa<RegOp, RegResetOp>(op))
58  return;
59 
60  // Compute the width of all registers, and remember which bits are assigned
61  // to each register.
62  auto regType = type_cast<FIRRTLBaseType>(op->getResult(0).getType());
63  std::optional<int64_t> regWidth = getBitWidth(regType);
64  assert(regWidth.has_value() && "register must have a valid FIRRTL width");
65 
66  auto start = builder.getIntegerAttr(ui64Type, currentWidth);
67  op->setAttr("firrtl.random_init_start", start);
68 
69  currentWidth += *regWidth;
70  });
71 }
72 
73 void RandomizeRegisterInitPass::runOnOperation() {
74  createRandomizationAttributes(getOperation());
75 }
assert(baseType &&"element must be base type")
static void createRandomizationAttributes(FModuleOp mod)
Create attributes indicating the required size of random initialization values for each register in t...
std::unique_ptr< mlir::Pass > createRandomizeRegisterInitPass()
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21