CIRCT  18.0.0git
FIRRTLFieldSource.cpp
Go to the documentation of this file.
1 //===- FIRRTLFieldSource.cpp - Field Source Analysis ------------*- C++ -*-===//
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 a basic points-to like analysis.
10 // This analysis tracks any aggregate generated by an operation and maps any
11 // value derived from indexing of that aggregate back to the source of the
12 // aggregate along with a path through the type from the source. In parallel,
13 // this tracks any value which is an alias for a writable storage element, even
14 // if scalar. This is sufficient to allow any value used on the LHS of a
15 // connect to be traced to its source, and to track any value which is a read
16 // of a storage element back to the source storage element.
17 //
18 // There is a redundant walk of the IR going on since flow is walking backwards
19 // over operations we've already visited. We need to refactor foldFlow so we
20 // can build up the flow incrementally.
21 //
22 //===----------------------------------------------------------------------===//
23 
25 
26 using namespace circt;
27 using namespace firrtl;
28 
29 FieldSource::FieldSource(Operation *operation) {
30  FModuleOp mod = cast<FModuleOp>(operation);
31  // All ports define locations
32  for (auto port : mod.getBodyBlock()->getArguments())
33  makeNodeForValue(port, port, {}, foldFlow(port));
34 
35  mod.walk<mlir::WalkOrder::PreOrder>([&](Operation *op) { visitOp(op); });
36 }
37 
38 void FieldSource::visitOp(Operation *op) {
39  if (auto sf = dyn_cast<SubfieldOp>(op))
40  return visitSubfield(sf);
41  if (auto si = dyn_cast<SubindexOp>(op))
42  return visitSubindex(si);
43  if (auto sa = dyn_cast<SubaccessOp>(op))
44  return visitSubaccess(sa);
45  if (isa<WireOp, RegOp, RegResetOp>(op))
46  return makeNodeForValue(op->getResult(0), op->getResult(0), {},
47  foldFlow(op->getResult(0)));
48  if (auto mem = dyn_cast<MemOp>(op))
49  return visitMem(mem);
50  if (auto inst = dyn_cast<InstanceOp>(op))
51  return visitInst(inst);
52 
53  // Track all other definitions of aggregates.
54  if (op->getNumResults()) {
55  auto type = op->getResult(0).getType();
56  if (auto baseType = type_dyn_cast<FIRRTLBaseType>(type);
57  baseType && !baseType.isGround())
58  makeNodeForValue(op->getResult(0), op->getResult(0), {},
59  foldFlow(op->getResult(0)));
60  }
61 }
62 
63 void FieldSource::visitSubfield(SubfieldOp sf) {
64  auto value = sf.getInput();
65  const auto *node = nodeForValue(value);
66  assert(node && "node should be in the map");
67  auto sv = node->path;
68  sv.push_back(sf.getFieldIndex());
69  makeNodeForValue(sf.getResult(), node->src, sv, foldFlow(sf));
70 }
71 
72 void FieldSource::visitSubindex(SubindexOp si) {
73  auto value = si.getInput();
74  const auto *node = nodeForValue(value);
75  assert(node && "node should be in the map");
76  auto sv = node->path;
77  sv.push_back(si.getIndex());
78  makeNodeForValue(si.getResult(), node->src, sv, foldFlow(si));
79 }
80 
81 void FieldSource::visitSubaccess(SubaccessOp sa) {
82  auto value = sa.getInput();
83  const auto *node = nodeForValue(value);
84  assert(node && "node should be in the map");
85  auto sv = node->path;
86  sv.push_back(-1);
87  makeNodeForValue(sa.getResult(), node->src, sv, foldFlow(sa));
88 }
89 
90 void FieldSource::visitMem(MemOp mem) {
91  for (auto r : mem.getResults())
92  makeNodeForValue(r, r, {}, foldFlow(r));
93 }
94 
95 void FieldSource::visitInst(InstanceOp inst) {
96  for (auto r : inst.getResults())
97  makeNodeForValue(r, r, {}, foldFlow(r));
98 }
99 
101  auto ii = paths.find(v);
102  if (ii == paths.end())
103  return nullptr;
104  return &ii->second;
105 }
106 
107 void FieldSource::makeNodeForValue(Value dst, Value src, ArrayRef<int64_t> path,
108  Flow flow) {
109  auto ii = paths.try_emplace(dst, src, path, flow);
110  (void)ii;
111  assert(ii.second && "Double insert into the map");
112 }
lowerAnnotationsNoRefTypePorts FirtoolPreserveValuesMode value
Definition: Firtool.cpp:95
assert(baseType &&"element must be base type")
const PathNode * nodeForValue(Value v) const
void visitSubaccess(SubaccessOp sa)
DenseMap< Value, PathNode > paths
void visitSubfield(SubfieldOp sf)
FieldSource(Operation *operation)
void visitInst(InstanceOp inst)
void makeNodeForValue(Value dst, Value src, ArrayRef< int64_t > path, Flow flow)
void visitSubindex(SubindexOp si)
Flow foldFlow(Value val, Flow accumulatedFlow=Flow::Source)
Compute the flow for a Value, val, as determined by the FIRRTL specification.
Definition: FIRRTLOps.cpp:180
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
Definition: DebugAnalysis.h:21
Definition: sv.py:1