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 
19 #include "mlir/IR/Attributes.h"
20 #include "mlir/IR/Builders.h"
21 #include "mlir/Pass/Pass.h"
22 #include "llvm/Support/Parallel.h"
23 
24 namespace circt {
25 namespace firrtl {
26 #define GEN_PASS_DEF_RANDOMIZEREGISTERINIT
27 #include "circt/Dialect/FIRRTL/Passes.h.inc"
28 } // namespace firrtl
29 } // namespace circt
30 
31 using namespace mlir;
32 using namespace circt;
33 using namespace firrtl;
34 
35 namespace {
36 struct RandomizeRegisterInitPass
37  : public circt::firrtl::impl::RandomizeRegisterInitBase<
38  RandomizeRegisterInitPass> {
39  void runOnOperation() override;
40 };
41 
42 } // end anonymous namespace
43 
44 std::unique_ptr<mlir::Pass> circt::firrtl::createRandomizeRegisterInitPass() {
45  return std::make_unique<RandomizeRegisterInitPass>();
46 }
47 
48 /// Create attributes indicating the required size of random initialization
49 /// values for each register in the module, and mark which range of these values
50 /// each register should consume. The goal is for registers to always read the
51 /// same random bits for the same seed, regardless of optimizations that might
52 /// remove registers.
53 static void createRandomizationAttributes(FModuleOp mod) {
54  OpBuilder builder(mod);
55 
56  // Walk all registers.
57  uint64_t currentWidth = 0;
58  auto ui64Type = builder.getIntegerType(64, false);
59  mod.walk([&](Operation *op) {
60  if (!isa<RegOp, RegResetOp>(op))
61  return;
62 
63  // Compute the width of all registers, and remember which bits are assigned
64  // to each register.
65  auto regType = type_cast<FIRRTLBaseType>(op->getResult(0).getType());
66  std::optional<int64_t> regWidth = getBitWidth(regType);
67  assert(regWidth.has_value() && "register must have a valid FIRRTL width");
68 
69  auto start = builder.getIntegerAttr(ui64Type, currentWidth);
70  op->setAttr("firrtl.random_init_start", start);
71 
72  currentWidth += *regWidth;
73  });
74 }
75 
76 void RandomizeRegisterInitPass::runOnOperation() {
77  createRandomizationAttributes(getOperation());
78 }
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