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
39 changes: 32 additions & 7 deletions include/circt/Dialect/FIRRTL/FIRRTLDeclarations.td
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,27 @@ def InstanceOp : HardwareDeclOp<"instance", [
CArg<"hw::InnerSymAttr", "hw::InnerSymAttr()">:$innerSym)>];

let extraClassDeclaration = [{
/// Return the number of ports for this instance.
size_t getNumPorts() {
return getNumResults();
}

/// Return the port direction for the specified result number.
Direction getPortDirection(size_t resultNo) {
return direction::get(getPortDirections()[resultNo]);
}

/// Return the port name for the specified result number.
StringAttr getPortName(size_t resultNo) {
StringAttr getPortNameAttr(size_t resultNo) {
return cast<StringAttr>(getPortNames()[resultNo]);
}
StringRef getPortNameStr(size_t resultNo) {
return getPortName(resultNo).getValue();

StringRef getPortName(size_t resultNo) {
return getPortNameAttr(resultNo).getValue();
}

Location getPortLocation(size_t) {
return getLoc();
}

/// Hooks for port annotations.
Expand Down Expand Up @@ -208,15 +218,29 @@ def InstanceChoiceOp : HardwareDeclOp<"instance_choice", [
let hasCustomAssemblyFormat = 1;

let extraClassDeclaration = [{
/// Return the number of ports for this instance.
size_t getNumPorts() {
return getNumResults();
}

/// Return the port direction for the specified result number.
Direction getPortDirection(size_t resultNo) {
return direction::get(getPortDirections()[resultNo]);
}

/// Return the port name for the specified result number.
StringAttr getPortName(size_t resultNo) {
StringAttr getPortNameAttr(size_t resultNo) {
return cast<StringAttr>(getPortNames()[resultNo]);
}

StringRef getPortName(size_t resultNo) {
return getPortNameAttr(resultNo).getValue();
}

Location getPortLocation(size_t resultNo) {
return getLoc();
}

/// Return the default target attribute.
FlatSymbolRefAttr getDefaultTargetAttr() {
return llvm::cast<FlatSymbolRefAttr>(getModuleNamesAttr()[0]);
Expand Down Expand Up @@ -313,9 +337,10 @@ def MemOp : HardwareDeclOp<"mem", [DeclareOpInterfaceMethods<CombDataflow>]> {
size_t getMaskBits();

/// Return the port name for the specified result number.
StringAttr getPortName(size_t resultNo);
StringRef getPortNameStr(size_t resultNo) {
return getPortName(resultNo).getValue();
StringAttr getPortNameAttr(size_t resultNo);

StringRef getPortName(size_t resultNo) {
return getPortNameAttr(resultNo).getValue();
}

/// Return the port type for the specified result number.
Expand Down
22 changes: 22 additions & 0 deletions include/circt/Dialect/FIRRTL/FIRRTLOpInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,28 @@ struct PortInfo {
annotations(annos), domains(domains) {}
};

inline bool operator==(const PortInfo &lhs, const PortInfo &rhs) {
if (lhs.name != rhs.name)
return false;
if (lhs.type != rhs.type)
return false;
if (lhs.direction != rhs.direction)
return false;
if (lhs.sym != rhs.sym)
return false;
if (lhs.loc != rhs.loc)
return false;
if (lhs.annotations != rhs.annotations)
return false;
if (lhs.domains != rhs.domains)
return false;
return true;
}

inline bool operator!=(const PortInfo &lhs, const PortInfo &rhs) {
return !(lhs == rhs);
}

enum class ConnectBehaviorKind {
/// Classic FIRRTL connections: last connect 'wins' across paths;
/// conditionally applied under 'when'.
Expand Down
13 changes: 13 additions & 0 deletions include/circt/Dialect/FIRRTL/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,19 @@ def CheckLayers : Pass<"firrtl-check-layers", "firrtl::CircuitOp"> {
}];
}

def InferDomains : Pass<"firrtl-infer-domains", "firrtl::CircuitOp"> {
let summary = "Infer and type check all firrtl domains";
let description = [{
This pass does domain inference on a FIRRTL circuit. The end result of this
is either a corrrctly domain-checked FIRRTL circuit or failure with verbose
error messages indicating why the FIRRTL circuit has illegal domain
constructs.

E.g., this pass can be used to check for illegal clock-domain-crossings if
clock domains are specified for signals in the design.
}];
}

def LowerDomains : Pass<"firrtl-lower-domains", "firrtl::CircuitOp"> {
let summary = "lower domain information to properties";
let description = [{
Expand Down
8 changes: 8 additions & 0 deletions include/circt/Firtool/Firtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ class FirtoolOptions {

bool getEmitAllBindFiles() const { return emitAllBindFiles; }

bool shouldInferDomains() const { return inferDomains; }

// Setters, used by the CAPI
FirtoolOptions &setOutputFilename(StringRef name) {
outputFilename = name;
Expand Down Expand Up @@ -393,6 +395,11 @@ class FirtoolOptions {
return *this;
}

FirtoolOptions &setInferDomains(bool value) {
inferDomains = value;
return *this;
}

private:
std::string outputFilename;

Expand Down Expand Up @@ -447,6 +454,7 @@ class FirtoolOptions {
bool lintStaticAsserts;
bool lintXmrsInDesign;
bool emitAllBindFiles;
bool inferDomains;
};

void registerFirtoolCLOptions();
Expand Down
7 changes: 7 additions & 0 deletions include/circt/Support/InstanceGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ class InstanceGraphNode;
class InstanceRecord
: public llvm::ilist_node_with_parent<InstanceRecord, InstanceGraphNode> {
public:
/// Get the op that this is tracking.
Operation *getOperation() {
return instance.getOperation();
}

/// Get the instance-like op that this is tracking.
template <typename TTarget = InstanceOpInterface>
auto getInstance() {
Expand Down Expand Up @@ -113,6 +118,8 @@ class InstanceGraphNode : public llvm::ilist_node<InstanceGraphNode> {
public:
InstanceGraphNode() : module(nullptr) {}

Operation *getOperation() { return module.getOperation(); }

/// Get the module that this node is tracking.
template <typename TTarget = ModuleOpInterface>
auto getModule() {
Expand Down
4 changes: 2 additions & 2 deletions lib/Dialect/FIRRTL/Export/FIREmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ void Emitter::emitStatement(InstanceOp op) {
portName.push_back('.');
unsigned baseLen = portName.size();
for (unsigned i = 0, e = op.getNumResults(); i < e; ++i) {
portName.append(legalize(op.getPortName(i)));
portName.append(legalize(op.getPortNameAttr(i)));
addValueName(op.getResult(i), portName);
portName.resize(baseLen);
}
Expand All @@ -1153,7 +1153,7 @@ void Emitter::emitStatement(InstanceChoiceOp op) {
portName.push_back('.');
unsigned baseLen = portName.size();
for (unsigned i = 0, e = op.getNumResults(); i < e; ++i) {
portName.append(legalize(op.getPortName(i)));
portName.append(legalize(op.getPortNameAttr(i)));
addValueName(op.getResult(i), portName);
portName.resize(baseLen);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Dialect/FIRRTL/FIRRTLAnnotationHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ using llvm::StringRef;
static LogicalResult updateExpandedPort(StringRef field, AnnoTarget &ref) {
if (auto mem = dyn_cast<MemOp>(ref.getOp()))
for (size_t p = 0, pe = mem.getPortNames().size(); p < pe; ++p)
if (mem.getPortNameStr(p) == field) {
if (mem.getPortName(p) == field) {
ref = PortAnnoTarget(mem, p);
return success();
}
Expand Down
41 changes: 23 additions & 18 deletions lib/Dialect/FIRRTL/FIRRTLOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2736,7 +2736,7 @@ InstanceOp InstanceOp::cloneWithInsertedPorts(
}

newPortDirections.push_back(getPortDirection(i));
newPortNames.push_back(getPortName(i));
newPortNames.push_back(getPortNameAttr(i));
newPortTypes.push_back(getType(i));
newPortAnnos.push_back(getPortAnnotation(i));
newDomainInfo.push_back(getDomainInfo()[i]);
Expand Down Expand Up @@ -2887,7 +2887,7 @@ void InstanceOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
base = "inst";

for (size_t i = 0, e = (*this)->getNumResults(); i != e; ++i) {
setNameFn(getResult(i), (base + "_" + getPortNameStr(i)).str());
setNameFn(getResult(i), (base + "_" + getPortName(i)).str());
}
}

Expand Down Expand Up @@ -3219,7 +3219,7 @@ InstanceChoiceOp InstanceChoiceOp::cloneWithInsertedPorts(
}

newPortDirections.push_back(getPortDirection(i));
newPortNames.push_back(getPortName(i));
newPortNames.push_back(getPortNameAttr(i));
newPortTypes.push_back(getType(i));
newPortAnnos.push_back(getPortAnnotations()[i]);
newDomainInfo.push_back(getDomainInfo()[i]);
Expand Down Expand Up @@ -3343,7 +3343,7 @@ LogicalResult MemOp::verify() {
FIRRTLType oldDataType;

for (size_t i = 0, e = getNumResults(); i != e; ++i) {
auto portName = getPortName(i);
auto portName = getPortNameAttr(i);

// Get a bundle type representing this port, stripping an outer
// flip if it exists. If this is not a bundle<> or
Expand Down Expand Up @@ -3453,10 +3453,10 @@ LogicalResult MemOp::verify() {
// Error if the type of the current port was not the same as the
// last port, but skip checking the first port.
if (oldDataType && oldDataType != dataType) {
emitOpError() << "port " << getPortName(i)
<< " has a different type than port " << getPortName(i - 1)
<< " (expected " << oldDataType << ", but got " << dataType
<< ")";
emitOpError() << "port " << getPortNameAttr(i)
<< " has a different type than port "
<< getPortNameAttr(i - 1) << " (expected " << oldDataType
<< ", but got " << dataType << ")";
return failure();
}

Expand Down Expand Up @@ -3539,7 +3539,7 @@ SmallVector<MemOp::NamedPort> MemOp::getPorts() {
for (size_t i = 0, e = getNumResults(); i != e; ++i) {
// Each port is a bundle.
auto portType = type_cast<FIRRTLType>(getResult(i).getType());
result.push_back({getPortName(i), getMemPortKindFromType(portType)});
result.push_back({getPortNameAttr(i), getMemPortKindFromType(portType)});
}
return result;
}
Expand Down Expand Up @@ -3596,7 +3596,7 @@ FIRRTLBaseType MemOp::getDataType() {
.getElementType(dataFieldName);
}

StringAttr MemOp::getPortName(size_t resultNo) {
StringAttr MemOp::getPortNameAttr(size_t resultNo) {
return cast<StringAttr>(getPortNames()[resultNo]);
}

Expand Down Expand Up @@ -3717,7 +3717,7 @@ void MemOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
base = "mem";

for (size_t i = 0, e = (*this)->getNumResults(); i != e; ++i) {
setNameFn(getResult(i), (base + "_" + getPortNameStr(i)).str());
setNameFn(getResult(i), (base + "_" + getPortName(i)).str());
}
}

Expand Down Expand Up @@ -4278,6 +4278,14 @@ LogicalResult PropAssignOp::verify() {
return success();
}

template <typename T>
static FlatSymbolRefAttr getDomainTypeNameOfResult(T op, size_t i) {
auto info = op.getDomainInfo();
if (info.empty())
return {};
return dyn_cast<FlatSymbolRefAttr>(info[i]);
}

static FlatSymbolRefAttr getDomainTypeName(Value value) {
if (!isa<DomainType>(value.getType()))
return {};
Expand All @@ -4297,13 +4305,10 @@ static FlatSymbolRefAttr getDomainTypeName(Value value) {

if (auto result = dyn_cast<OpResult>(value)) {
auto *op = result.getDefiningOp();
if (auto instance = dyn_cast<InstanceOp>(op)) {
auto info = instance.getDomainInfo();
if (info.empty())
return {};
auto attr = info[result.getResultNumber()];
return dyn_cast<FlatSymbolRefAttr>(attr);
}
if (auto instance = dyn_cast<InstanceOp>(op))
return getDomainTypeNameOfResult(instance, result.getResultNumber());
if (auto instance = dyn_cast<InstanceChoiceOp>(op))
return getDomainTypeNameOfResult(instance, result.getResultNumber());
return {};
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Dialect/FIRRTL/FIRRTLReductions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ struct InstanceStubber : public OpReduction<firrtl::InstanceOp> {
for (unsigned i = 0, e = instOp.getNumResults(); i != e; ++i) {
auto result = instOp.getResult(i);
auto name = builder.getStringAttr(Twine(instOp.getName()) + "_" +
instOp.getPortNameStr(i));
instOp.getPortName(i));
auto wire =
firrtl::WireOp::create(builder, result.getType(), name,
firrtl::NameKindEnum::DroppableName,
Expand Down Expand Up @@ -463,7 +463,7 @@ struct MemoryStubber : public OpReduction<firrtl::MemOp> {
for (unsigned i = 0, e = memOp.getNumResults(); i != e; ++i) {
auto result = memOp.getResult(i);
auto name = builder.getStringAttr(Twine(memOp.getName()) + "_" +
memOp.getPortNameStr(i));
memOp.getPortName(i));
auto wire =
firrtl::WireOp::create(builder, result.getType(), name,
firrtl::NameKindEnum::DroppableName,
Expand Down Expand Up @@ -1190,7 +1190,7 @@ struct EagerInliner : public OpReduction<InstanceOp> {
for (unsigned i = 0, e = instOp.getNumResults(); i != e; ++i) {
auto result = instOp.getResult(i);
auto name = rewriter.getStringAttr(Twine(instOp.getName()) + "_" +
instOp.getPortNameStr(i));
instOp.getPortName(i));
auto wire = WireOp::create(rewriter, instOp.getLoc(), result.getType(),
name, NameKindEnum::DroppableName,
instOp.getPortAnnotation(i), StringAttr{})
Expand Down
3 changes: 1 addition & 2 deletions lib/Dialect/FIRRTL/FIRRTLUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,7 @@ static void getDeclName(Value value, SmallString<64> &string, bool nameSafe) {
.Case<InstanceOp, MemOp>([&](auto op) {
string += op.getName();
string += nameSafe ? "_" : ".";
string += op.getPortName(cast<OpResult>(value).getResultNumber())
.getValue();
string += op.getPortName(cast<OpResult>(value).getResultNumber());
value = nullptr;
})
.Case<FNamableOp>([&](auto op) {
Expand Down
1 change: 1 addition & 0 deletions lib/Dialect/FIRRTL/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_circt_dialect_library(CIRCTFIRRTLTransforms
GrandCentral.cpp
IMConstProp.cpp
IMDeadCodeElim.cpp
InferDomains.cpp
InferReadWrite.cpp
InferResets.cpp
InferWidths.cpp
Expand Down
2 changes: 1 addition & 1 deletion lib/Dialect/FIRRTL/Transforms/Dedup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,7 @@ fixupSymbolSensitiveOp(Operation *op, InstanceGraph &instanceGraph,
continue;
LLVM_DEBUG(llvm::dbgs()
<< "- Updating instance port \"" << instOp.getInstanceName()
<< "." << instOp.getPortName(index).getValue() << "\" from "
<< "." << instOp.getPortName(index) << "\" from "
<< oldType << " to " << newType << "\n");

// If the type changed we transform it back to the old type with an
Expand Down
4 changes: 2 additions & 2 deletions lib/Dialect/FIRRTL/Transforms/ExtractInstances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ void ExtractInstancesPass::extractInstances() {
for (unsigned portIdx = 0; portIdx < numInstPorts; ++portIdx) {
// Assemble the new port name as "<prefix>_<name>", where the prefix is
// provided by the extraction annotation.
auto name = inst.getPortNameStr(portIdx);
auto name = inst.getPortName(portIdx);
auto nameAttr = StringAttr::get(
&getContext(),
prefix.empty() ? Twine(name) : Twine(prefix) + "_" + name);
Expand Down Expand Up @@ -913,7 +913,7 @@ void ExtractInstancesPass::groupInstances() {
StringRef prefix(instPrefixNamesPair[inst].first);
unsigned portNum = inst.getNumResults();
for (unsigned portIdx = 0; portIdx < portNum; ++portIdx) {
auto name = inst.getPortNameStr(portIdx);
auto name = inst.getPortName(portIdx);
auto nameAttr = builder.getStringAttr(
prefix.empty() ? Twine(name) : Twine(prefix) + "_" + name);
PortInfo port{nameAttr,
Expand Down
2 changes: 1 addition & 1 deletion lib/Dialect/FIRRTL/Transforms/FlattenMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ struct FlattenMemoryPass
auto result = memOp.getResult(index);
auto wire = WireOp::create(builder, result.getType(),
(memOp.getName() + "_" +
memOp.getPortName(index).getValue())
memOp.getPortName(index))
.str())
.getResult();
result.replaceAllUsesWith(wire);
Expand Down
Loading
Loading