Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/circt/Debug/HWDebug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef CIRCT_DEBUG_HWDEBUG_H
#define CIRCT_DEBUG_HWDEBUG_H

#include "mlir/Pass/Pass.h"

namespace circt::debug {
std::unique_ptr<mlir::Pass> createExportHGDBPass(std::string filename);
} // namespace circt::debug

#endif // CIRCT_DEBUG_HWDEBUG_H
7 changes: 3 additions & 4 deletions include/circt/Dialect/FIRRTL/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ std::unique_ptr<mlir::Pass>
createLowerFIRRTLAnnotationsPass(bool ignoreUnhandledAnnotations = false,
bool ignoreClasslessAnnotations = false);

std::unique_ptr<mlir::Pass>
createLowerFIRRTLTypesPass(bool replSeqMem = false,
bool preserveAggregate = false,
bool preservePublicTypes = true);
std::unique_ptr<mlir::Pass> createLowerFIRRTLTypesPass(
bool replSeqMem = false, bool preserveAggregate = false,
bool preservePublicTypes = true, bool insertDebugInfo = false);

std::unique_ptr<mlir::Pass> createLowerBundleVectorTypesPass();

Expand Down
4 changes: 3 additions & 1 deletion include/circt/Dialect/FIRRTL/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def LowerFIRRTLTypes : Pass<"firrtl-lower-types", "firrtl::CircuitOp"> {
"Preserve passive aggregate types in the module.">,
Option<"preservePublicTypes", "preserve-public-types", "bool",
"true", "Force to lower ports of toplevel and external modules even"
"when aggregate preservation mode.">
"when aggregate preservation mode.">,
Option<"insertDebugInfo", "insert-debug-info", "bool", "false",
"Insert debug information.">
];
let dependentDialects = ["hw::HWDialect"];
}
Expand Down
3 changes: 3 additions & 0 deletions include/circt/Dialect/HW/HWOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct PortInfo {
/// The optional symbol for this port.
StringAttr sym = {};

// The optional debug attribute for this port
StringAttr debugAttr = {};

StringRef getName() const { return name.getValue(); }
bool isOutput() const { return direction == OUTPUT; }

Expand Down
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_subdirectory(Analysis)
add_subdirectory(Bindings)
add_subdirectory(CAPI)
add_subdirectory(Conversion)
add_subdirectory(Debug)
add_subdirectory(Dialect)
add_subdirectory(Scheduling)
add_subdirectory(Support)
Expand Down
2 changes: 1 addition & 1 deletion lib/Conversion/ExportVerilog/ExportVerilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ static bool isDuplicatableExpression(Operation *op) {
/// Return the verilog name of the operations that can define a symbol.
/// Except for <WireOp, RegOp, LocalParamOp, InstanceOp>, check global state
/// `getDeclarationVerilogName` for them.
static StringRef getSymOpName(Operation *symOp) {
StringRef getSymOpName(Operation *symOp) {
// Typeswitch of operation types which can define a symbol.
// If legalizeNames has renamed it, then the attribute must be set.
if (auto attr = symOp->getAttrOfType<StringAttr>("hw.verilogName"))
Expand Down
126 changes: 109 additions & 17 deletions lib/Conversion/FIRRTLToHW/LowerToHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,17 @@ LogicalResult FIRRTLModuleLowering::lowerPorts(
hwPort.type = lowerType(firrtlPort.type);
hwPort.sym = firrtlPort.sym;

// Pass down the debug attr if any
// Notice that hasAnnotation does not work since the debug attribute
// is not inserted as a class
for (auto anno : firrtlPort.annotations) {
auto annoDict = anno.getDict();
if (auto debugAttr = annoDict.get("hw.debug.name")) {
hwPort.debugAttr = debugAttr.cast<StringAttr>();
firrtlPort.annotations.removeAnnotation(anno);
break;
}
}
// We can't lower all types, so make sure to cleanly reject them.
if (!hwPort.type) {
moduleOp->emitError("cannot lower this port type to HW");
Expand Down Expand Up @@ -989,7 +1000,6 @@ FIRRTLModuleLowering::lowerModule(FModuleOp oldModule, Block *topLevelModule,

if (failed)
return {};

loweringState.processRemainingAnnotations(oldModule, annos);
return newModule;
}
Expand Down Expand Up @@ -1068,6 +1078,15 @@ static Value tryEliminatingConnectsToValue(Value flipValue,

auto connectSrc = theConnect.src();

if (auto *srcOp = connectSrc.getDefiningOp()) {
if (srcOp->hasAttr("hw.debug.name")) {
// If the source has debug attribute, we don't do any optimization
// because otherwise we will lose this symbol
auto str = srcOp->getAttr("hw.debug.name").cast<StringAttr>().str();
return {};
}
}

// Convert fliped sources to passive sources.
if (!connectSrc.getType().cast<FIRRTLType>().isPassive())
connectSrc =
Expand Down Expand Up @@ -1557,6 +1576,11 @@ void FIRRTLLowering::optimizeTemporaryWire(sv::WireOp wire) {
SmallVector<sv::ReadInOutOp> reads;
sv::AssignOp write;

// if the wire has debug attributes, skip it
if (wire->hasAttr("hw.debug.name")) {
return;
}

for (auto *user : wire->getUsers()) {
if (auto read = dyn_cast<sv::ReadInOutOp>(user)) {
reads.push_back(read);
Expand Down Expand Up @@ -1936,6 +1960,10 @@ template <typename ResultOpType, typename... CtorArgTypes>
LogicalResult FIRRTLLowering::setLoweringTo(Operation *orig,
CtorArgTypes... args) {
auto result = builder.createOrFold<ResultOpType>(args...);
if (auto debugAttr = orig->getAttr("hw.debug.name")) {
auto *op = result.getDefiningOp();
op->setAttr("hw.debug.name", debugAttr);
}
if (auto *op = result.getDefiningOp())
tryCopyName(op, orig);
return setPossiblyFoldedLowering(orig->getResult(0), result);
Expand Down Expand Up @@ -1974,6 +2002,11 @@ Value FIRRTLLowering::getReadInOutOp(Value v) {
}

result = builder.createOrFold<sv::ReadInOutOp>(v);
if (auto *vOp = v.getDefiningOp()) {
if (auto debugAttr = vOp->getAttr("hw.debug.name")) {
result.getDefiningOp()->setAttr("hw.debug.name", debugAttr);
}
}
builder.restoreInsertionPoint(oldIP);
return result;
}
Expand Down Expand Up @@ -2280,10 +2313,12 @@ LogicalResult FIRRTLLowering::visitDecl(NodeOp op) {
// Node operations are logical noops, but may carry annotations or be
// referred to through an inner name. If a don't touch is present, ensure
// that we have a symbol name so we can keep the node as a wire.
// Or we have debug attribute attached
auto symName = op.inner_symAttr();
auto name = op.nameAttr();
if (AnnotationSet::removeAnnotations(
op, "firrtl.transforms.DontTouchAnnotation") &&
if ((AnnotationSet::removeAnnotations(
op, "firrtl.transforms.DontTouchAnnotation") ||
op->hasAttr("hw.debug.name")) &&
!symName) {
// name may be empty
auto moduleName = cast<hw::HWModuleOp>(op->getParentOp()).getName();
Expand All @@ -2293,7 +2328,11 @@ LogicalResult FIRRTLLowering::visitDecl(NodeOp op) {

if (symName) {
auto wire = builder.create<sv::WireOp>(operand.getType(), name, symName);
builder.create<sv::AssignOp>(wire, operand);
auto assign = builder.create<sv::AssignOp>(wire, operand);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assign->setAttr("hw.debug.name", debugAttr);
wire->setAttr("hw.debug.name", debugAttr);
}
}

return setLowering(op, operand);
Expand Down Expand Up @@ -2499,10 +2538,15 @@ LogicalResult FIRRTLLowering::visitDecl(RegResetOp op) {
symName = op.nameAttr();
auto regResult =
builder.create<sv::RegOp>(resultType, op.nameAttr(), symName);
if (auto debugAttr = op->getAttr("hw.debug.name"))
regResult->setAttr("hw.debug.name", debugAttr);
(void)setLowering(op, regResult);

auto resetFn = [&]() {
builder.create<sv::PAssignOp>(regResult, resetValue);
auto assignOP = builder.create<sv::PAssignOp>(regResult, resetValue);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOP->setAttr("hw.debug.name", debugAttr);
}
};

if (op.resetSignal().getType().isa<AsyncResetType>()) {
Expand Down Expand Up @@ -2751,8 +2795,20 @@ LogicalResult FIRRTLLowering::visitDecl(InstanceOp oldInstance) {

// Create a wire for each input/inout operand, so there is
// something to connect to.
Value wire =
createTmpWireOp(portType, "." + port.getName().str() + ".wire");
auto w = createTmpWireOp(portType, "." + port.getName().str() + ".wire");
Value wire = w;

// migrate the renaming process
auto *op = wire.getDefiningOp();
auto &annos = port.annotations;
if (op) {
for (auto const &attr : annos) {
auto const &dict = attr.getDict();
if (auto name = dict.get("hw.debug.name")) {
w->setAttr("hw.debug.name", name);
}
}
}

// Know that the argument FIRRTL value is equal to this wire, allowing
// connects to it to be lowered.
Expand Down Expand Up @@ -3290,8 +3346,13 @@ LogicalResult FIRRTLLowering::visitStmt(ConnectOp op) {
if (!clockVal)
return failure();

addToAlwaysBlock(clockVal,
[&]() { builder.create<sv::PAssignOp>(destVal, srcVal); });
addToAlwaysBlock(clockVal, [&]() {
auto assignOp = builder.create<sv::PAssignOp>(destVal, srcVal);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOp->setAttr("hw.debug.name", debugAttr);
}
return assignOp;
});
return success();
}

Expand All @@ -3307,12 +3368,26 @@ LogicalResult FIRRTLLowering::visitStmt(ConnectOp op) {
regResetOp.resetSignal().getType().isa<AsyncResetType>()
? ::ResetType::AsyncReset
: ::ResetType::SyncReset,
sv::EventControl::AtPosEdge, resetSignal,
[&]() { builder.create<sv::PAssignOp>(destVal, srcVal); });
sv::EventControl::AtPosEdge, resetSignal, [&]() {
auto assignOp =
builder.create<sv::PAssignOp>(destVal, srcVal);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOp->setAttr("hw.debug.name", debugAttr);
}

return assignOp;
});
return success();
}

builder.create<sv::AssignOp>(destVal, srcVal);
auto newAssignOp = builder.create<sv::AssignOp>(destVal, srcVal);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
newAssignOp->setAttr("hw.debug.name", debugAttr);
} else if (auto *destOp = op.dest().getDefiningOp()) {
if ((debugAttr = destOp->getAttr("hw.debug.name"))) {
newAssignOp->setAttr("hw.debug.name", debugAttr);
}
}
return success();
}

Expand Down Expand Up @@ -3343,8 +3418,13 @@ LogicalResult FIRRTLLowering::visitStmt(PartialConnectOp op) {
if (!clockVal)
return failure();

addToAlwaysBlock(clockVal,
[&]() { builder.create<sv::PAssignOp>(destVal, srcVal); });
addToAlwaysBlock(clockVal, [&]() {
auto assignOp = builder.create<sv::PAssignOp>(destVal, srcVal);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOp->setAttr("hw.debug.name", debugAttr);
}
return assignOp;
});
return success();
}

Expand All @@ -3360,8 +3440,14 @@ LogicalResult FIRRTLLowering::visitStmt(PartialConnectOp op) {
? ::ResetType::AsyncReset
: ::ResetType::SyncReset;
addToAlwaysBlock(sv::EventControl::AtPosEdge, clockVal, resetStyle,
sv::EventControl::AtPosEdge, resetSignal,
[&]() { builder.create<sv::PAssignOp>(destVal, srcVal); });
sv::EventControl::AtPosEdge, resetSignal, [&]() {
auto assignOp =
builder.create<sv::PAssignOp>(destVal, srcVal);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOp->setAttr("hw.debug.name", debugAttr);
}
return assignOp;
});
return success();
}

Expand Down Expand Up @@ -3390,7 +3476,13 @@ LogicalResult FIRRTLLowering::visitStmt(PartialConnectOp op) {
srcVectorType.getElementType());
}
})
.Case<IntType>([&](auto) { builder.create<sv::AssignOp>(dest, src); })
.Case<IntType>([&](auto) {
auto assignOp = builder.create<sv::AssignOp>(dest, src);
if (auto debugAttr = op->getAttr("hw.debug.name")) {
assignOp->setAttr("hw.debug.name", debugAttr);
}
return assignOp;
})
.Default([&](auto) { llvm_unreachable("must fail before"); });
};
recurse(destVal, srcVal, destType, op.src().getType());
Expand Down
14 changes: 14 additions & 0 deletions lib/Debug/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
add_circt_translation_library(CIRCTDebug
HWDebug.cpp

ADDITIONAL_HEADER_DIRS

DEPENDS
CIRCTConversionPassIncGen

LINK_COMPONENTS
Core

LINK_LIBS PUBLIC
CIRCTExportVerilog
)
Loading