CIRCT 20.0.0git
Loading...
Searching...
No Matches
FirRegLowering.h
Go to the documentation of this file.
1//===- FirRegLowering.h - FirReg lowering utilities ===========--*- 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// NOLINTNEXTLINE(llvm-header-guard)
10#ifndef CONVERSION_SEQTOSV_FIRREGLOWERING_H
11#define CONVERSION_SEQTOSV_FIRREGLOWERING_H
12
17#include "circt/Support/LLVM.h"
20#include "llvm/ADT/SmallPtrSet.h"
21
22namespace circt {
23
24using namespace hw;
25// This class computes the set of muxes that are reachable from an op.
26// The heuristic propagates the reachability only through the 3 ops, mux,
27// array_create and array_get. All other ops block the reachability.
28// This analysis is built lazily on every query.
29// The query: is a mux is reachable from a reg, results in a DFS traversal
30// of the IR rooted at the register. This traversal is completed and the
31// result is cached in a Map, for faster retrieval on any future query of any
32// op in this subgraph.
34public:
35 ReachableMuxes(HWModuleOp m) : module(m) {}
36
37 bool isMuxReachableFrom(seq::FirRegOp regOp, comb::MuxOp muxOp);
38
39private:
40 void buildReachabilityFrom(Operation *startNode);
41 HWModuleOp module;
42 llvm::DenseMap<Operation *, llvm::SmallDenseSet<Operation *>> reachableMuxes;
43 llvm::SmallPtrSet<Operation *, 16> visited;
44};
45
46// The op and its users information that needs to be tracked on the stack
47// for an iterative DFS traversal.
48struct OpUserInfo {
49 Operation *op;
51 llvm::filter_iterator<Operation::user_iterator,
52 std::function<bool(const Operation *)>>;
53
55 static std::function<bool(const Operation *op)> opAllowsReachability;
56
57 OpUserInfo(Operation *op)
58 : op(op), userIter(op->getUsers().begin(), op->getUsers().end(),
60 userEnd(op->getUsers().end(), op->getUsers().end(),
62
64 if (unvisited) {
65 unvisited = false;
66 return true;
67 }
68 return false;
69 }
70
71private:
72 bool unvisited = true;
73};
74
75/// Lower FirRegOp to `sv.reg` and `sv.always`.
77public:
78 FirRegLowering(TypeConverter &typeConverter, hw::HWModuleOp module,
79 bool disableRegRandomization = false,
80 bool emitSeparateAlwaysBlocks = false);
81
82 void lower();
83 bool needsRegRandomization() const { return needsRandom; }
84
86
87private:
88 struct RegLowerInfo {
90 IntegerAttr preset;
93 int64_t randStart;
94 size_t width;
95 };
96
97 RegLowerInfo lower(seq::FirRegOp reg);
98
99 void initialize(OpBuilder &builder, RegLowerInfo reg, ArrayRef<Value> rands);
100 void initializeRegisterElements(Location loc, OpBuilder &builder, Value reg,
101 Value rand, unsigned &pos);
102
103 void createTree(OpBuilder &builder, Value reg, Value term, Value next);
104 std::optional<std::tuple<Value, Value, Value>>
105 tryRestoringSubaccess(OpBuilder &builder, Value reg, Value term,
106 hw::ArrayCreateOp nextRegValue);
107
108 void addToAlwaysBlock(Block *block, sv::EventControl clockEdge, Value clock,
109 const std::function<void(OpBuilder &)> &body,
110 sv::ResetType resetStyle = {},
111 sv::EventControl resetEdge = {}, Value reset = {},
112 const std::function<void(OpBuilder &)> &resetBody = {});
113
114 void addToIfBlock(OpBuilder &builder, Value cond,
115 const std::function<void()> &trueSide,
116 const std::function<void()> &falseSide);
117
118 hw::ConstantOp getOrCreateConstant(Location loc, const APInt &value) {
119 OpBuilder builder(module.getBody());
120 auto &constant = constantCache[value];
121 if (constant) {
122 constant->setLoc(builder.getFusedLoc({constant->getLoc(), loc}));
123 return constant;
124 }
125
126 constant = builder.create<hw::ConstantOp>(loc, value);
127 return constant;
128 }
129
130 using AlwaysKeyType = std::tuple<Block *, sv::EventControl, Value,
131 sv::ResetType, sv::EventControl, Value>;
134
135 using IfKeyType = std::pair<Block *, Value>;
137
140 std::unique_ptr<ReachableMuxes> reachableMuxes;
141
142 TypeConverter &typeConverter;
143 hw::HWModuleOp module;
144
147
148 bool needsRandom = false;
149};
150} // namespace circt
151
152#endif // CONVERSION_SEQTOSV_FIRREGLOWERING_H
Lower FirRegOp to sv.reg and sv.always.
std::unique_ptr< ReachableMuxes > reachableMuxes
bool needsRegRandomization() const
void initialize(OpBuilder &builder, RegLowerInfo reg, ArrayRef< Value > rands)
llvm::SmallDenseMap< std::pair< Value, unsigned >, Value > arrayIndexCache
llvm::SmallDenseMap< IfKeyType, sv::IfOp > ifCache
RegLowerInfo lower(seq::FirRegOp reg)
void addToIfBlock(OpBuilder &builder, Value cond, const std::function< void()> &trueSide, const std::function< void()> &falseSide)
std::optional< std::tuple< Value, Value, Value > > tryRestoringSubaccess(OpBuilder &builder, Value reg, Value term, hw::ArrayCreateOp nextRegValue)
llvm::SmallDenseMap< APInt, hw::ConstantOp > constantCache
std::pair< Block *, Value > IfKeyType
void createTree(OpBuilder &builder, Value reg, Value term, Value next)
hw::ConstantOp getOrCreateConstant(Location loc, const APInt &value)
void addToAlwaysBlock(Block *block, sv::EventControl clockEdge, Value clock, const std::function< void(OpBuilder &)> &body, sv::ResetType resetStyle={}, sv::EventControl resetEdge={}, Value reset={}, const std::function< void(OpBuilder &)> &resetBody={})
std::tuple< Block *, sv::EventControl, Value, sv::ResetType, sv::EventControl, Value > AlwaysKeyType
void initializeRegisterElements(Location loc, OpBuilder &builder, Value reg, Value rand, unsigned &pos)
TypeConverter & typeConverter
hw::HWModuleOp bool disableRegRandomization
llvm::SmallDenseMap< AlwaysKeyType, std::pair< sv::AlwaysOp, sv::IfOp > > alwaysBlocks
void buildReachabilityFrom(Operation *startNode)
llvm::SmallPtrSet< Operation *, 16 > visited
HWModuleOp llvm::DenseMap< Operation *, llvm::SmallDenseSet< Operation * > > reachableMuxes
bool isMuxReachableFrom(seq::FirRegOp regOp, comb::MuxOp muxOp)
ReachableMuxes(HWModuleOp m)
Definition sv.py:68
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
llvm::filter_iterator< Operation::user_iterator, std::function< bool(const Operation *)> > ValidUsersIterator
static std::function< bool(const Operation *op)> opAllowsReachability
OpUserInfo(Operation *op)
ValidUsersIterator userIter
ValidUsersIterator userEnd