CIRCT  20.0.0git
ModelInfo.cpp
Go to the documentation of this file.
1 //===- ModelInfo.cpp - Information about Arc models -----------------------===//
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 // Defines and computes information about Arc models.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 #include "llvm/Support/JSON.h"
16 
17 using namespace mlir;
18 using namespace circt;
19 using namespace arc;
20 
21 LogicalResult circt::arc::collectStates(Value storage, unsigned offset,
22  SmallVector<StateInfo> &states) {
23  struct StateCollectionJob {
24  mlir::Value::user_iterator nextToProcess;
25  mlir::Value::user_iterator end;
26  unsigned offset;
27 
28  StateCollectionJob(Value storage, unsigned offset)
29  : nextToProcess(storage.user_begin()), end(storage.user_end()),
30  offset(offset) {}
31  };
32 
33  SmallVector<StateCollectionJob, 4> jobStack{{storage, offset}};
34 
35  while (!jobStack.empty()) {
36  StateCollectionJob &job = jobStack.back();
37 
38  if (job.nextToProcess == job.end) {
39  jobStack.pop_back();
40  continue;
41  }
42 
43  Operation *op = *job.nextToProcess++;
44  unsigned offset = job.offset;
45 
46  if (auto substorage = dyn_cast<AllocStorageOp>(op)) {
47  if (!substorage.getOffset().has_value())
48  return substorage.emitOpError(
49  "without allocated offset; run state allocation first");
50  Value substorageOutput = substorage.getOutput();
51  jobStack.emplace_back(substorageOutput, offset + *substorage.getOffset());
52  continue;
53  }
54 
55  if (!isa<AllocStateOp, RootInputOp, RootOutputOp, AllocMemoryOp>(op))
56  continue;
57 
58  auto opName = op->getAttrOfType<StringAttr>("name");
59  if (!opName || opName.getValue().empty())
60  continue;
61 
62  auto opOffset = op->getAttrOfType<IntegerAttr>("offset");
63  if (!opOffset)
64  return op->emitOpError(
65  "without allocated offset; run state allocation first");
66 
67  if (isa<AllocStateOp, RootInputOp, RootOutputOp>(op)) {
68  auto result = op->getResult(0);
69  auto &stateInfo = states.emplace_back();
70  stateInfo.type = StateInfo::Register;
71  if (isa<RootInputOp>(op))
72  stateInfo.type = StateInfo::Input;
73  else if (isa<RootOutputOp>(op))
74  stateInfo.type = StateInfo::Output;
75  else if (auto alloc = dyn_cast<AllocStateOp>(op)) {
76  if (alloc.getTap())
77  stateInfo.type = StateInfo::Wire;
78  }
79  stateInfo.name = opName.getValue();
80  stateInfo.offset = opOffset.getValue().getZExtValue() + offset;
81  stateInfo.numBits = cast<StateType>(result.getType()).getBitWidth();
82  continue;
83  }
84 
85  if (auto memOp = dyn_cast<AllocMemoryOp>(op)) {
86  auto stride = op->getAttrOfType<IntegerAttr>("stride");
87  if (!stride)
88  return op->emitOpError(
89  "without allocated stride; run state allocation first");
90  auto memType = memOp.getType();
91  auto intType = memType.getWordType();
92  auto &stateInfo = states.emplace_back();
93  stateInfo.type = StateInfo::Memory;
94  stateInfo.name = opName.getValue();
95  stateInfo.offset = opOffset.getValue().getZExtValue() + offset;
96  stateInfo.numBits = intType.getWidth();
97  stateInfo.memoryStride = stride.getValue().getZExtValue();
98  stateInfo.memoryDepth = memType.getNumWords();
99  continue;
100  }
101  }
102 
103  return success();
104 }
105 
106 LogicalResult circt::arc::collectModels(mlir::ModuleOp module,
107  SmallVector<ModelInfo> &models) {
108 
109  for (auto modelOp : module.getOps<ModelOp>()) {
110  auto storageArg = modelOp.getBody().getArgument(0);
111  auto storageType = cast<StorageType>(storageArg.getType());
112 
113  SmallVector<StateInfo> states;
114  if (failed(collectStates(storageArg, 0, states)))
115  return failure();
116  llvm::sort(states, [](auto &a, auto &b) { return a.offset < b.offset; });
117 
118  models.emplace_back(std::string(modelOp.getName()), storageType.getSize(),
119  std::move(states), modelOp.getInitialFnAttr(),
120  modelOp.getFinalFnAttr());
121  }
122 
123  return success();
124 }
125 
126 void circt::arc::serializeModelInfoToJson(llvm::raw_ostream &outputStream,
127  ArrayRef<ModelInfo> models) {
128  llvm::json::OStream json(outputStream, 2);
129 
130  json.array([&] {
131  for (const ModelInfo &model : models) {
132  json.object([&] {
133  json.attribute("name", model.name);
134  json.attribute("numStateBytes", model.numStateBytes);
135  json.attribute("initialFnSym", !model.initialFnSym
136  ? ""
137  : model.initialFnSym.getValue());
138  json.attribute("finalFnSym",
139  !model.finalFnSym ? "" : model.finalFnSym.getValue());
140  json.attributeArray("states", [&] {
141  for (const auto &state : model.states) {
142  json.object([&] {
143  json.attribute("name", state.name);
144  json.attribute("offset", state.offset);
145  json.attribute("numBits", state.numBits);
146  auto typeStr = [](StateInfo::Type type) {
147  switch (type) {
148  case StateInfo::Input:
149  return "input";
150  case StateInfo::Output:
151  return "output";
152  case StateInfo::Register:
153  return "register";
154  case StateInfo::Memory:
155  return "memory";
156  case StateInfo::Wire:
157  return "wire";
158  }
159  return "";
160  };
161  json.attribute("type", typeStr(state.type));
162  if (state.type == StateInfo::Memory) {
163  json.attribute("stride", state.memoryStride);
164  json.attribute("depth", state.memoryDepth);
165  }
166  });
167  }
168  });
169  });
170  }
171  });
172 }
@ Input
Definition: HW.h:35
@ Output
Definition: HW.h:35
void serializeModelInfoToJson(llvm::raw_ostream &outputStream, llvm::ArrayRef< ModelInfo > models)
Serializes models to outputStream in JSON format.
mlir::LogicalResult collectModels(mlir::ModuleOp module, llvm::SmallVector< ModelInfo > &models)
Collects information about all Arc models in the provided module, and adds it to models.
mlir::LogicalResult collectStates(mlir::Value storage, unsigned offset, llvm::SmallVector< StateInfo > &states)
Collects information about states within the provided Arc model storage storage, assuming default off...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Gathers information about a given Arc model.
Definition: ModelInfo.h:35