mirror of https://github.com/llvm/circt.git
[ExportVerilog] Move emitTypeDims/printPackedType into ModuleEmitter.
This makes way for dimensions that can refer to declarations within the module, like parameters. Note that this exposes some design problems with TypeAliasType. I just xfailed a test for now (the expected diagnostics are emitted on the wrong line now) where ExportVerilog is implementing verification of these decls instead of the verifier. I will tackle that as its own separate workstream, since type parameters needs a sound design as well.
This commit is contained in:
parent
107d378d61
commit
4b9a8a328b
|
@ -170,7 +170,7 @@ def TypeAliasType : HWType<"TypeAlias"> {
|
|||
];
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
Optional<TypedeclOp> getDecl(Operation *op);
|
||||
Optional<TypedeclOp> getTypeDecl(Operation *op);
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -196,29 +196,6 @@ static void getTypeDims(SmallVectorImpl<int64_t> &dims, Type type,
|
|||
}
|
||||
}
|
||||
|
||||
/// Emit a list of dimensions.
|
||||
static void emitDims(ArrayRef<int64_t> dims, raw_ostream &os) {
|
||||
for (int64_t width : dims)
|
||||
switch (width) {
|
||||
case -1: // -1 is an invalid type.
|
||||
os << "<<invalid type>>";
|
||||
return;
|
||||
case 0:
|
||||
os << "/*Zero Width*/";
|
||||
break;
|
||||
default:
|
||||
os << '[' << (width - 1) << ":0]";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a type's packed dimensions, returning whether or not text was emitted.
|
||||
static void emitTypeDims(Type type, Location loc, raw_ostream &os) {
|
||||
SmallVector<int64_t, 4> dims;
|
||||
getTypeDims(dims, type, loc);
|
||||
emitDims(dims, os);
|
||||
}
|
||||
|
||||
/// True iff 'a' and 'b' have the same wire dims.
|
||||
static bool haveMatchingDims(Type a, Type b, Location loc) {
|
||||
SmallVector<int64_t, 4> aDims;
|
||||
|
@ -260,99 +237,6 @@ static Type stripUnpackedTypes(Type type) {
|
|||
.Default([](Type type) { return type; });
|
||||
}
|
||||
|
||||
/// Output the basic type that consists of packed and primitive types. This is
|
||||
/// those to the left of the name in verilog. implicitIntType controls whether
|
||||
/// to print a base type for (logic) for inteters or whether the caller will
|
||||
/// have handled this (with logic, wire, reg, etc).
|
||||
/// Returns true when anything was printed out.
|
||||
static bool printPackedTypeImpl(Type type, raw_ostream &os, Operation *op,
|
||||
SmallVectorImpl<int64_t> &dims,
|
||||
bool implicitIntType,
|
||||
bool singleBitDefaultType) {
|
||||
return TypeSwitch<Type, bool>(type)
|
||||
.Case<IntegerType>([&](IntegerType integerType) {
|
||||
if (!implicitIntType)
|
||||
os << "logic";
|
||||
if (integerType.getWidth() != 1 || !singleBitDefaultType)
|
||||
dims.push_back(integerType.getWidth());
|
||||
if (!dims.empty() && !implicitIntType)
|
||||
os << ' ';
|
||||
|
||||
emitDims(dims, os);
|
||||
return !dims.empty() || !implicitIntType;
|
||||
})
|
||||
.Case<InOutType>([&](InOutType inoutType) {
|
||||
return printPackedTypeImpl(inoutType.getElementType(), os, op, dims,
|
||||
implicitIntType, singleBitDefaultType);
|
||||
})
|
||||
.Case<StructType>([&](StructType structType) {
|
||||
os << "struct packed {";
|
||||
for (auto &element : structType.getElements()) {
|
||||
SmallVector<int64_t, 8> structDims;
|
||||
printPackedTypeImpl(stripUnpackedTypes(element.type), os, op,
|
||||
structDims, /*implicitIntType=*/false,
|
||||
/*singleBitDefaultType=*/true);
|
||||
os << ' ' << element.name << "; ";
|
||||
}
|
||||
os << '}';
|
||||
emitDims(dims, os);
|
||||
return true;
|
||||
})
|
||||
.Case<ArrayType>([&](ArrayType arrayType) {
|
||||
dims.push_back(arrayType.getSize());
|
||||
return printPackedTypeImpl(arrayType.getElementType(), os, op, dims,
|
||||
implicitIntType, singleBitDefaultType);
|
||||
})
|
||||
.Case<InterfaceType>([](InterfaceType ifaceType) { return false; })
|
||||
.Case<UnpackedArrayType>([&](UnpackedArrayType arrayType) {
|
||||
os << "<<unexpected unpacked array>>";
|
||||
op->emitError("Unexpected unpacked array in packed type ") << arrayType;
|
||||
return true;
|
||||
})
|
||||
.Case<TypeAliasType>([&](TypeAliasType typeRef) {
|
||||
auto typedecl = typeRef.getDecl(op);
|
||||
if (!typedecl.hasValue())
|
||||
return false;
|
||||
|
||||
os << typedecl.getValue().getPreferredName();
|
||||
emitDims(dims, os);
|
||||
return true;
|
||||
})
|
||||
.Default([&](Type type) {
|
||||
os << "<<invalid type '" << type << "'>>";
|
||||
op->emitError("value has an unsupported verilog type ") << type;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// Print the specified packed portion of the type to the specified stream. The
|
||||
/// operation specified is used in the case of an error for its location.
|
||||
/// * When `implicitIntType` is false, a "logic" is printed. This is used in
|
||||
/// struct fields and typedefs.
|
||||
/// * When `singleBitDefaultType` is false, single bit values are printed as
|
||||
/// `[0:0]`. This is used in parameter lists.
|
||||
/// This returns true if anything was printed out.
|
||||
static bool printPackedType(Type type, raw_ostream &os, Operation *op,
|
||||
bool implicitIntType = true,
|
||||
bool singleBitDefaultType = true) {
|
||||
SmallVector<int64_t, 8> packedDimensions;
|
||||
return printPackedTypeImpl(type, os, op, packedDimensions, implicitIntType,
|
||||
singleBitDefaultType);
|
||||
}
|
||||
|
||||
/// Output the unpacked array dimensions. This is the part of the type that is
|
||||
/// to the right of the name.
|
||||
static void printUnpackedTypePostfix(Type type, raw_ostream &os) {
|
||||
TypeSwitch<Type, void>(type)
|
||||
.Case<InOutType>([&](InOutType inoutType) {
|
||||
printUnpackedTypePostfix(inoutType.getElementType(), os);
|
||||
})
|
||||
.Case<UnpackedArrayType>([&](UnpackedArrayType arrayType) {
|
||||
printUnpackedTypePostfix(arrayType.getElementType(), os);
|
||||
os << "[0:" << (arrayType.getSize() - 1) << "]";
|
||||
});
|
||||
}
|
||||
|
||||
/// Return the word (e.g. "reg") in Verilog to declare the specified thing.
|
||||
static StringRef getVerilogDeclWord(Operation *op,
|
||||
const LoweringOptions &options) {
|
||||
|
@ -620,12 +504,16 @@ namespace {
|
|||
/// various emitters.
|
||||
class VerilogEmitterState {
|
||||
public:
|
||||
explicit VerilogEmitterState(const LoweringOptions &options,
|
||||
explicit VerilogEmitterState(ModuleOp designOp,
|
||||
const LoweringOptions &options,
|
||||
const SymbolCache &symbolCache,
|
||||
const GlobalNameTable &globalNames,
|
||||
raw_ostream &os)
|
||||
: options(options), symbolCache(symbolCache), globalNames(globalNames),
|
||||
os(os) {}
|
||||
: designOp(designOp), options(options), symbolCache(symbolCache),
|
||||
globalNames(globalNames), os(os) {}
|
||||
|
||||
/// This is the root mlir::ModuleOp that holds the whole design being emitted.
|
||||
ModuleOp designOp;
|
||||
|
||||
/// The emitter options which control verilog emission.
|
||||
const LoweringOptions options;
|
||||
|
@ -816,16 +704,43 @@ public:
|
|||
void emitBind(BindOp op);
|
||||
void emitBindInterface(BindInterfaceOp op);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Methods for formatting types.
|
||||
|
||||
/// Emit a type's packed dimensions.
|
||||
void emitTypeDims(Type type, Location loc, raw_ostream &os);
|
||||
|
||||
/// Print the specified packed portion of the type to the specified stream,
|
||||
///
|
||||
/// * When `implicitIntType` is false, a "logic" is printed. This is used in
|
||||
/// struct fields and typedefs.
|
||||
/// * When `singleBitDefaultType` is false, single bit values are printed as
|
||||
/// `[0:0]`. This is used in parameter lists.
|
||||
///
|
||||
/// This returns true if anything was printed.
|
||||
bool printPackedType(Type type, raw_ostream &os, Location loc,
|
||||
bool implicitIntType = true,
|
||||
bool singleBitDefaultType = true);
|
||||
|
||||
/// Output the unpacked array dimensions. This is the part of the type that
|
||||
/// is to the right of the name.
|
||||
void printUnpackedTypePostfix(Type type, raw_ostream &os);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Methods for formatting parameters.
|
||||
|
||||
/// Prints a parameter attribute expression in a Verilog compatible way to the
|
||||
/// specified stream. This returns the precedence of the generated string.
|
||||
SubExprInfo printParamValue(Attribute value, raw_ostream &os,
|
||||
function_ref<InFlightDiagnostic()> emitError);
|
||||
|
||||
public:
|
||||
SubExprInfo printParamValue(Attribute value, raw_ostream &os,
|
||||
VerilogPrecedence parenthesizeIfLooserThan,
|
||||
function_ref<InFlightDiagnostic()> emitError);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Mutable state while emitting a module body.
|
||||
|
||||
/// This is the current module being emitted for a HWModuleOp.
|
||||
HWModuleOp currentModuleOp;
|
||||
|
||||
|
@ -843,6 +758,133 @@ public:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Methods for formatting types.
|
||||
|
||||
/// Emit a list of dimensions.
|
||||
static void emitDims(ArrayRef<int64_t> dims, raw_ostream &os) {
|
||||
for (int64_t width : dims)
|
||||
switch (width) {
|
||||
case -1: // -1 is an invalid type.
|
||||
os << "<<invalid type>>";
|
||||
return;
|
||||
case 0:
|
||||
os << "/*Zero Width*/";
|
||||
break;
|
||||
default:
|
||||
os << '[' << (width - 1) << ":0]";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a type's packed dimensions.
|
||||
void ModuleEmitter::emitTypeDims(Type type, Location loc, raw_ostream &os) {
|
||||
SmallVector<int64_t, 4> dims;
|
||||
getTypeDims(dims, type, loc);
|
||||
emitDims(dims, os);
|
||||
}
|
||||
|
||||
/// Output the basic type that consists of packed and primitive types. This is
|
||||
/// those to the left of the name in verilog. implicitIntType controls whether
|
||||
/// to print a base type for (logic) for inteters or whether the caller will
|
||||
/// have handled this (with logic, wire, reg, etc).
|
||||
///
|
||||
/// Returns true when anything was printed out.
|
||||
static bool printPackedTypeImpl(Type type, raw_ostream &os, Location loc,
|
||||
SmallVectorImpl<int64_t> &dims,
|
||||
bool implicitIntType, bool singleBitDefaultType,
|
||||
ModuleEmitter &emitter) {
|
||||
return TypeSwitch<Type, bool>(type)
|
||||
.Case<IntegerType>([&](IntegerType integerType) {
|
||||
if (!implicitIntType)
|
||||
os << "logic";
|
||||
if (integerType.getWidth() != 1 || !singleBitDefaultType)
|
||||
dims.push_back(integerType.getWidth());
|
||||
if (!dims.empty() && !implicitIntType)
|
||||
os << ' ';
|
||||
|
||||
emitDims(dims, os);
|
||||
return !dims.empty() || !implicitIntType;
|
||||
})
|
||||
.Case<InOutType>([&](InOutType inoutType) {
|
||||
return printPackedTypeImpl(inoutType.getElementType(), os, loc, dims,
|
||||
implicitIntType, singleBitDefaultType,
|
||||
emitter);
|
||||
})
|
||||
.Case<StructType>([&](StructType structType) {
|
||||
os << "struct packed {";
|
||||
for (auto &element : structType.getElements()) {
|
||||
SmallVector<int64_t, 8> structDims;
|
||||
printPackedTypeImpl(stripUnpackedTypes(element.type), os, loc,
|
||||
structDims, /*implicitIntType=*/false,
|
||||
/*singleBitDefaultType=*/true, emitter);
|
||||
os << ' ' << element.name << "; ";
|
||||
}
|
||||
os << '}';
|
||||
emitDims(dims, os);
|
||||
return true;
|
||||
})
|
||||
.Case<ArrayType>([&](ArrayType arrayType) {
|
||||
dims.push_back(arrayType.getSize());
|
||||
return printPackedTypeImpl(arrayType.getElementType(), os, loc, dims,
|
||||
implicitIntType, singleBitDefaultType,
|
||||
emitter);
|
||||
})
|
||||
.Case<InterfaceType>([](InterfaceType ifaceType) { return false; })
|
||||
.Case<UnpackedArrayType>([&](UnpackedArrayType arrayType) {
|
||||
os << "<<unexpected unpacked array>>";
|
||||
mlir::emitError(loc, "Unexpected unpacked array in packed type ")
|
||||
<< arrayType;
|
||||
return true;
|
||||
})
|
||||
.Case<TypeAliasType>([&](TypeAliasType typeRef) {
|
||||
auto typedecl = typeRef.getTypeDecl(emitter.state.designOp);
|
||||
if (!typedecl.hasValue())
|
||||
return false; // This already emitted an error!?
|
||||
|
||||
os << typedecl.getValue().getPreferredName();
|
||||
emitDims(dims, os);
|
||||
return true;
|
||||
})
|
||||
.Default([&](Type type) {
|
||||
os << "<<invalid type '" << type << "'>>";
|
||||
mlir::emitError(loc, "value has an unsupported verilog type ") << type;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// Print the specified packed portion of the type to the specified stream,
|
||||
///
|
||||
/// * When `implicitIntType` is false, a "logic" is printed. This is used in
|
||||
/// struct fields and typedefs.
|
||||
/// * When `singleBitDefaultType` is false, single bit values are printed as
|
||||
/// `[0:0]`. This is used in parameter lists.
|
||||
///
|
||||
/// This returns true if anything was printed.
|
||||
bool ModuleEmitter::printPackedType(Type type, raw_ostream &os, Location loc,
|
||||
bool implicitIntType,
|
||||
bool singleBitDefaultType) {
|
||||
SmallVector<int64_t, 8> packedDimensions;
|
||||
return printPackedTypeImpl(type, os, loc, packedDimensions, implicitIntType,
|
||||
singleBitDefaultType, *this);
|
||||
}
|
||||
|
||||
/// Output the unpacked array dimensions. This is the part of the type that is
|
||||
/// to the right of the name.
|
||||
void ModuleEmitter::printUnpackedTypePostfix(Type type, raw_ostream &os) {
|
||||
TypeSwitch<Type, void>(type)
|
||||
.Case<InOutType>([&](InOutType inoutType) {
|
||||
printUnpackedTypePostfix(inoutType.getElementType(), os);
|
||||
})
|
||||
.Case<UnpackedArrayType>([&](UnpackedArrayType arrayType) {
|
||||
printUnpackedTypePostfix(arrayType.getElementType(), os);
|
||||
os << "[0:" << (arrayType.getSize() - 1) << "]";
|
||||
});
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Methods for formatting parameters.
|
||||
|
||||
/// Prints a parameter attribute expression in a Verilog compatible way to the
|
||||
/// specified stream. This returns the precedence of the generated string.
|
||||
SubExprInfo
|
||||
|
@ -1482,7 +1524,7 @@ SubExprInfo ExprEmitter::visitTypeOp(BitcastOp op) {
|
|||
Type toType = op.getType();
|
||||
if (!haveMatchingDims(toType, op.input().getType(), op.getLoc())) {
|
||||
os << "/*cast(bit";
|
||||
emitTypeDims(toType, op.getLoc(), os);
|
||||
emitter.emitTypeDims(toType, op.getLoc(), os);
|
||||
os << ")*/";
|
||||
}
|
||||
return emitSubExpr(op.input(), LowestPrecedence, OOLUnary);
|
||||
|
@ -1930,8 +1972,8 @@ void NameCollector::collectNames(Block &block) {
|
|||
// Convert the port's type to a string and measure it.
|
||||
{
|
||||
llvm::raw_svector_ostream stringStream(typeString);
|
||||
printPackedType(stripUnpackedTypes(result.getType()), stringStream,
|
||||
&op);
|
||||
moduleEmitter.printPackedType(stripUnpackedTypes(result.getType()),
|
||||
stringStream, op.getLoc());
|
||||
}
|
||||
maxTypeWidth = std::max(typeString.size(), maxTypeWidth);
|
||||
}
|
||||
|
@ -1970,7 +2012,8 @@ class TypeScopeEmitter
|
|||
public hw::TypeScopeVisitor<TypeScopeEmitter, LogicalResult> {
|
||||
public:
|
||||
/// Create a TypeScopeEmitter for the specified module emitter.
|
||||
TypeScopeEmitter(VerilogEmitterState &state) : EmitterBase(state) {}
|
||||
TypeScopeEmitter(ModuleEmitter &emitter)
|
||||
: EmitterBase(emitter.state), emitter(emitter) {}
|
||||
|
||||
void emitTypeScopeBlock(Block &body);
|
||||
|
||||
|
@ -1978,6 +2021,8 @@ private:
|
|||
friend class TypeScopeVisitor<TypeScopeEmitter, LogicalResult>;
|
||||
|
||||
LogicalResult visitTypeScope(TypedeclOp op);
|
||||
|
||||
ModuleEmitter &emitter;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -1993,8 +2038,9 @@ void TypeScopeEmitter::emitTypeScopeBlock(Block &body) {
|
|||
|
||||
LogicalResult TypeScopeEmitter::visitTypeScope(TypedeclOp op) {
|
||||
indent() << "typedef ";
|
||||
printPackedType(stripUnpackedTypes(op.type()), os, op, false);
|
||||
printUnpackedTypePostfix(op.type(), os);
|
||||
emitter.printPackedType(stripUnpackedTypes(op.type()), os, op.getLoc(),
|
||||
false);
|
||||
emitter.printUnpackedTypePostfix(op.type(), os);
|
||||
os << ' ' << op.getPreferredName();
|
||||
os << ";\n";
|
||||
return success();
|
||||
|
@ -3042,9 +3088,10 @@ LogicalResult StmtEmitter::visitSV(InterfaceOp op) {
|
|||
|
||||
LogicalResult StmtEmitter::visitSV(InterfaceSignalOp op) {
|
||||
indent();
|
||||
printPackedType(stripUnpackedTypes(op.type()), os, op, false);
|
||||
emitter.printPackedType(stripUnpackedTypes(op.type()), os, op->getLoc(),
|
||||
false);
|
||||
os << ' ' << state.globalNames.getInterfaceVerilogName(op);
|
||||
printUnpackedTypePostfix(op.type(), os);
|
||||
emitter.printUnpackedTypePostfix(op.type(), os);
|
||||
os << ";\n";
|
||||
return success();
|
||||
}
|
||||
|
@ -3177,7 +3224,8 @@ bool StmtEmitter::emitDeclarationForTemporary(Operation *op) {
|
|||
os << declWord;
|
||||
if (!declWord.empty())
|
||||
os << ' ';
|
||||
if (printPackedType(stripUnpackedTypes(op->getResult(0).getType()), os, op))
|
||||
if (emitter.printPackedType(stripUnpackedTypes(op->getResult(0).getType()),
|
||||
os, op->getLoc()))
|
||||
os << ' ';
|
||||
os << names.getName(op->getResult(0));
|
||||
|
||||
|
@ -3249,7 +3297,7 @@ void StmtEmitter::collectNamesEmitDecls(Block &block) {
|
|||
os << "()";
|
||||
} else {
|
||||
// Print out any array subscripts.
|
||||
printUnpackedTypePostfix(type, os);
|
||||
emitter.printUnpackedTypePostfix(type, os);
|
||||
}
|
||||
|
||||
if (auto localparam = dyn_cast<LocalParamOp>(op)) {
|
||||
|
@ -3488,7 +3536,7 @@ void ModuleEmitter::emitHWModule(HWModuleOp module) {
|
|||
return;
|
||||
}
|
||||
|
||||
printPackedType(type, sstream, module,
|
||||
printPackedType(type, sstream, module->getLoc(),
|
||||
/*implicitIntType=*/true,
|
||||
// Print single-bit values as explicit `[0:0]` type.
|
||||
/*singleBitDefaultType=*/false);
|
||||
|
@ -3555,7 +3603,8 @@ void ModuleEmitter::emitHWModule(HWModuleOp module) {
|
|||
portTypeStrings.push_back({});
|
||||
{
|
||||
llvm::raw_svector_ostream stringStream(portTypeStrings.back());
|
||||
printPackedType(stripUnpackedTypes(port.type), stringStream, module);
|
||||
printPackedType(stripUnpackedTypes(port.type), stringStream,
|
||||
module->getLoc());
|
||||
}
|
||||
|
||||
maxTypeWidth = std::max(portTypeStrings.back().size(), maxTypeWidth);
|
||||
|
@ -3731,7 +3780,7 @@ private:
|
|||
/// then shared across all per-file emissions that happen in parallel.
|
||||
struct SharedEmitterState {
|
||||
/// The MLIR module to emit.
|
||||
ModuleOp rootOp;
|
||||
ModuleOp designOp;
|
||||
|
||||
/// The main file that collects all operations that are neither replicated
|
||||
/// per-file ops nor specifically assigned to a file.
|
||||
|
@ -3765,8 +3814,9 @@ struct SharedEmitterState {
|
|||
/// Information about renamed global symbols, parameters, etc.
|
||||
const GlobalNameTable globalNames;
|
||||
|
||||
explicit SharedEmitterState(ModuleOp rootOp, GlobalNameTable globalNames)
|
||||
: rootOp(rootOp), options(rootOp), globalNames(std::move(globalNames)) {}
|
||||
explicit SharedEmitterState(ModuleOp designOp, GlobalNameTable globalNames)
|
||||
: designOp(designOp), options(designOp),
|
||||
globalNames(std::move(globalNames)) {}
|
||||
void gatherFiles(bool separateModules);
|
||||
|
||||
using EmissionList = std::vector<StringOrOpToEmit>;
|
||||
|
@ -3800,7 +3850,7 @@ void SharedEmitterState::gatherFiles(bool separateModules) {
|
|||
};
|
||||
|
||||
SmallString<32> outputPath;
|
||||
for (auto &op : *rootOp.getBody()) {
|
||||
for (auto &op : *designOp.getBody()) {
|
||||
auto info = OpFileInfo{&op, replicatedOps.size()};
|
||||
|
||||
bool hasFileName = false;
|
||||
|
@ -3964,7 +4014,8 @@ static void emitOperation(VerilogEmitterState &state, Operation *op) {
|
|||
.Case<InterfaceOp, VerbatimOp, IfDefOp>(
|
||||
[&](auto op) { ModuleEmitter(state).emitStatement(op); })
|
||||
.Case<TypeScopeOp>([&](auto typedecls) {
|
||||
TypeScopeEmitter(state).emitTypeScopeBlock(*typedecls.getBodyBlock());
|
||||
ModuleEmitter emitter(state);
|
||||
TypeScopeEmitter(emitter).emitTypeScopeBlock(*typedecls.getBodyBlock());
|
||||
})
|
||||
.Default([&](auto *op) {
|
||||
state.encounteredError = true;
|
||||
|
@ -3976,7 +4027,7 @@ static void emitOperation(VerilogEmitterState &state, Operation *op) {
|
|||
/// specified file.
|
||||
void SharedEmitterState::emitOps(EmissionList &thingsToEmit, raw_ostream &os,
|
||||
bool parallelize) {
|
||||
MLIRContext *context = rootOp->getContext();
|
||||
MLIRContext *context = designOp->getContext();
|
||||
|
||||
// Disable parallelization overhead if MLIR threading is disabled.
|
||||
if (parallelize)
|
||||
|
@ -3985,7 +4036,7 @@ void SharedEmitterState::emitOps(EmissionList &thingsToEmit, raw_ostream &os,
|
|||
// If we aren't parallelizing output, directly output each operation to the
|
||||
// specified stream.
|
||||
if (!parallelize) {
|
||||
VerilogEmitterState state(options, symbolCache, globalNames, os);
|
||||
VerilogEmitterState state(designOp, options, symbolCache, globalNames, os);
|
||||
for (auto &entry : thingsToEmit) {
|
||||
if (auto *op = entry.getOperation())
|
||||
emitOperation(state, op);
|
||||
|
@ -4014,7 +4065,8 @@ void SharedEmitterState::emitOps(EmissionList &thingsToEmit, raw_ostream &os,
|
|||
|
||||
SmallString<256> buffer;
|
||||
llvm::raw_svector_ostream tmpStream(buffer);
|
||||
VerilogEmitterState state(options, symbolCache, globalNames, tmpStream);
|
||||
VerilogEmitterState state(designOp, options, symbolCache, globalNames,
|
||||
tmpStream);
|
||||
emitOperation(state, op);
|
||||
stringOrOp.setString(buffer);
|
||||
});
|
||||
|
@ -4030,7 +4082,7 @@ void SharedEmitterState::emitOps(EmissionList &thingsToEmit, raw_ostream &os,
|
|||
}
|
||||
|
||||
// If this wasn't emitted to a string (e.g. it is a bind) do so now.
|
||||
VerilogEmitterState state(options, symbolCache, globalNames, os);
|
||||
VerilogEmitterState state(designOp, options, symbolCache, globalNames, os);
|
||||
emitOperation(state, op);
|
||||
}
|
||||
}
|
||||
|
@ -4117,9 +4169,8 @@ createOutputFile(StringRef fileName, StringRef dirname,
|
|||
// Create the output directory if needed.
|
||||
std::error_code error = llvm::sys::fs::create_directories(outputDir);
|
||||
if (error) {
|
||||
mlir::emitError(emitter.rootOp.getLoc(),
|
||||
"cannot create output directory \"" + outputDir +
|
||||
"\": " + error.message());
|
||||
emitter.designOp.emitError("cannot create output directory \"")
|
||||
<< outputDir << "\": " << error.message();
|
||||
emitter.encounteredError = true;
|
||||
return {};
|
||||
}
|
||||
|
@ -4128,7 +4179,7 @@ createOutputFile(StringRef fileName, StringRef dirname,
|
|||
std::string errorMessage;
|
||||
auto output = mlir::openOutputFile(outputFilename, &errorMessage);
|
||||
if (!output) {
|
||||
mlir::emitError(emitter.rootOp.getLoc(), errorMessage);
|
||||
emitter.designOp.emitError(errorMessage);
|
||||
emitter.encounteredError = true;
|
||||
}
|
||||
return output;
|
||||
|
|
|
@ -445,9 +445,11 @@ void TypeAliasType::print(DialectAsmPrinter &p) const {
|
|||
p << getMnemonic() << "<" << getRef() << ", " << getInnerType() << ">";
|
||||
}
|
||||
|
||||
Optional<TypedeclOp> TypeAliasType::getDecl(Operation *op) {
|
||||
Optional<TypedeclOp> TypeAliasType::getTypeDecl(Operation *op) {
|
||||
SymbolRefAttr ref = getRef();
|
||||
auto moduleOp = op->getParentOfType<ModuleOp>();
|
||||
auto moduleOp = ::dyn_cast<ModuleOp>(op);
|
||||
if (!moduleOp)
|
||||
moduleOp = op->getParentOfType<ModuleOp>();
|
||||
|
||||
auto typeScope = moduleOp.lookupSymbol<TypeScopeOp>(ref.getRootReference());
|
||||
if (!typeScope) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: circt-opt %s -export-verilog -verify-diagnostics
|
||||
|
||||
// XFAIL: *
|
||||
hw.type_scope @__hw_typedecls {
|
||||
hw.typedecl @foo : i1
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue