15#include "llvm/Support/JSON.h"
22 SmallVector<StateInfo> &states) {
23 struct StateCollectionJob {
24 mlir::Value::user_iterator nextToProcess;
25 mlir::Value::user_iterator
end;
28 StateCollectionJob(Value storage,
unsigned offset)
29 : nextToProcess(storage.user_begin()),
end(storage.user_end()),
33 SmallVector<StateCollectionJob, 4> jobStack{{storage, offset}};
35 while (!jobStack.empty()) {
36 StateCollectionJob &job = jobStack.back();
38 if (job.nextToProcess == job.end) {
43 Operation *op = *job.nextToProcess++;
44 unsigned offset = job.offset;
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());
55 if (!isa<AllocStateOp, RootInputOp, RootOutputOp, AllocMemoryOp>(op))
58 SmallVector<StringAttr> names;
60 auto opName = op->getAttrOfType<StringAttr>(
"name");
61 if (opName && !opName.getValue().empty())
62 names.push_back(opName);
64 if (
auto nameAttrs = op->getAttrOfType<ArrayAttr>(
"names"))
65 for (
auto attr : nameAttrs)
66 if (auto nameAttr = dyn_cast<StringAttr>(attr))
67 if (!nameAttr.
empty())
68 names.push_back(nameAttr);
73 auto opOffset = op->getAttrOfType<IntegerAttr>(
"offset");
75 return op->emitOpError(
76 "without allocated offset; run state allocation first");
79 if (isa<AllocStateOp, RootInputOp, RootOutputOp>(op)) {
80 auto result = op->getResult(0);
81 stateInfo.type = StateInfo::Register;
82 if (isa<RootInputOp>(op))
83 stateInfo.type = StateInfo::Input;
84 else if (isa<RootOutputOp>(op))
85 stateInfo.type = StateInfo::Output;
86 else if (
auto alloc = dyn_cast<AllocStateOp>(op)) {
88 stateInfo.type = StateInfo::Wire;
90 stateInfo.offset = opOffset.getValue().getZExtValue() + offset;
91 stateInfo.numBits = cast<StateType>(result.getType()).getBitWidth();
92 for (
auto name : names) {
93 stateInfo.name = name.getValue();
94 states.push_back(stateInfo);
99 if (
auto memOp = dyn_cast<AllocMemoryOp>(op)) {
100 auto stride = op->getAttrOfType<IntegerAttr>(
"stride");
102 return op->emitOpError(
103 "without allocated stride; run state allocation first");
104 auto memType = memOp.getType();
105 auto intType = memType.getWordType();
106 stateInfo.type = StateInfo::Memory;
107 stateInfo.offset = opOffset.getValue().getZExtValue() + offset;
108 stateInfo.numBits = intType.getWidth();
109 stateInfo.memoryStride = stride.getValue().getZExtValue();
110 stateInfo.memoryDepth = memType.getNumWords();
111 for (
auto name : names) {
112 stateInfo.name = name.getValue();
113 states.push_back(stateInfo);
123 SmallVector<ModelInfo> &models) {
125 for (
auto modelOp : module.getOps<ModelOp>()) {
126 auto storageArg = modelOp.getBody().getArgument(0);
127 auto storageType = cast<StorageType>(storageArg.getType());
129 SmallVector<StateInfo> states;
132 llvm::sort(states, [](
auto &a,
auto &b) {
return a.offset < b.offset; });
134 models.emplace_back(std::string(modelOp.getName()), storageType.getSize(),
135 std::move(states), modelOp.getInitialFnAttr(),
136 modelOp.getFinalFnAttr());
143 ArrayRef<ModelInfo> models) {
144 llvm::json::OStream
json(outputStream, 2);
147 for (
const ModelInfo &model : models) {
149 json.attribute(
"name", model.name);
150 json.attribute(
"numStateBytes", model.numStateBytes);
151 json.attribute(
"initialFnSym", !model.initialFnSym
153 : model.initialFnSym.getValue());
154 json.attribute(
"finalFnSym",
155 !model.finalFnSym ?
"" : model.finalFnSym.getValue());
156 json.attributeArray(
"states", [&] {
157 for (
const auto &state : model.states) {
159 json.attribute(
"name", state.name);
160 json.attribute(
"offset", state.offset);
161 json.attribute(
"numBits", state.numBits);
162 auto typeStr = [](StateInfo::Type type) {
164 case StateInfo::Input:
166 case StateInfo::Output:
168 case StateInfo::Register:
170 case StateInfo::Memory:
172 case StateInfo::Wire:
177 json.attribute(
"type", typeStr(state.type));
178 if (state.type == StateInfo::Memory) {
179 json.attribute(
"stride", state.memoryStride);
180 json.attribute(
"depth", state.memoryDepth);
static InstancePath empty
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.