mirror of https://github.com/llvm/circt.git
[FIRRTL] Add generic intrinsic op. (#6874)
Add generic intrinsic operation to FIRRTL. Not used anywhere, just adding to the IR to build on. Re-use module parameter printing/parsing for use as custom printer on the op. See PR for more context.
This commit is contained in:
parent
87020b2ed4
commit
0cff5d90dd
|
@ -13,36 +13,24 @@
|
|||
#ifndef CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_TD
|
||||
#define CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_TD
|
||||
|
||||
def IsXIntrinsicOp : FIRRTLOp<"int.isX",
|
||||
[HasCustomSSAName, Pure]> {
|
||||
let summary = "Test for 'x";
|
||||
let description = [{
|
||||
The `int.isX` expression checks that the operand is not a verilog literal
|
||||
'x. FIRRTL doesn't have a notion of 'x per-se, but x can come in to the
|
||||
system from external modules and from SV constructs. Verification
|
||||
constructs need to explicitly test for 'x.
|
||||
}];
|
||||
include "FIRRTLDialect.td"
|
||||
|
||||
let arguments = (ins FIRRTLBaseType:$arg);
|
||||
let results = (outs NonConstUInt1Type:$result);
|
||||
let hasFolder = 1;
|
||||
let assemblyFormat = "$arg attr-dict `:` type($arg)";
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Generic intrinsic operation for parsing into before lowering.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def HasBeenResetIntrinsicOp : FIRRTLOp<"int.has_been_reset", [Pure]> {
|
||||
let summary = "Check that a proper reset has been seen.";
|
||||
let description = [{
|
||||
The result of `firrtl.int.has_been_reset` reads as 0 immediately after simulation
|
||||
startup and after each power-cycle in a power-aware simulation. The result
|
||||
remains 0 before and during reset and only switches to 1 after the reset is
|
||||
deasserted again.
|
||||
def GenericIntrinsicOp : FIRRTLOp<"int.generic",
|
||||
[HasCustomSSAName]> {
|
||||
let summary = "Generic intrinsic operation for FIRRTL intrinsics.";
|
||||
|
||||
See the corresponding `verif.has_been_reset` operation.
|
||||
}];
|
||||
let arguments = (ins NonConstClockType:$clock, AnyResetType:$reset);
|
||||
let results = (outs NonConstUInt1Type:$result);
|
||||
let hasFolder = 1;
|
||||
let assemblyFormat = "$clock `,` $reset attr-dict `:` type($reset)";
|
||||
let arguments = (
|
||||
ins StrAttr:$intrinsic,
|
||||
Variadic<PassiveType>:$operands,
|
||||
DefaultValuedAttr<ParamDeclArrayAttr, "{}">:$parameters
|
||||
);
|
||||
|
||||
let results = (outs Optional<PassiveType>:$result);
|
||||
let assemblyFormat = "$intrinsic custom<ParameterList>($parameters) ($operands^)? attr-dict-with-keyword `:` functional-type($operands, $result)";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -135,4 +123,41 @@ def ClockInverterIntrinsicOp : FIRRTLOp<"int.clock_inv", []> {
|
|||
let assemblyFormat = "$input attr-dict";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other intrinsics
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def IsXIntrinsicOp : FIRRTLOp<"int.isX",
|
||||
[HasCustomSSAName, Pure]> {
|
||||
let summary = "Test for 'x";
|
||||
let description = [{
|
||||
The `int.isX` expression checks that the operand is not a verilog literal
|
||||
'x. FIRRTL doesn't have a notion of 'x per-se, but x can come in to the
|
||||
system from external modules and from SV constructs. Verification
|
||||
constructs need to explicitly test for 'x.
|
||||
}];
|
||||
|
||||
let arguments = (ins FIRRTLBaseType:$arg);
|
||||
let results = (outs NonConstUInt1Type:$result);
|
||||
let hasFolder = 1;
|
||||
let assemblyFormat = "$arg attr-dict `:` type($arg)";
|
||||
}
|
||||
|
||||
def HasBeenResetIntrinsicOp : FIRRTLOp<"int.has_been_reset", [Pure]> {
|
||||
let summary = "Check that a proper reset has been seen.";
|
||||
let description = [{
|
||||
The result of `firrtl.int.has_been_reset` reads as 0 immediately after simulation
|
||||
startup and after each power-cycle in a power-aware simulation. The result
|
||||
remains 0 before and during reset and only switches to 1 after the reset is
|
||||
deasserted again.
|
||||
|
||||
See the corresponding `verif.has_been_reset` operation.
|
||||
}];
|
||||
let arguments = (ins NonConstClockType:$clock, AnyResetType:$reset);
|
||||
let results = (outs NonConstUInt1Type:$result);
|
||||
let hasFolder = 1;
|
||||
let assemblyFormat = "$clock `,` $reset attr-dict `:` type($reset)";
|
||||
}
|
||||
|
||||
|
||||
#endif // CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_TD
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
LTLConcatIntrinsicOp, LTLNotIntrinsicOp, LTLImplicationIntrinsicOp,
|
||||
LTLEventuallyIntrinsicOp, LTLClockIntrinsicOp,
|
||||
LTLDisableIntrinsicOp, Mux2CellIntrinsicOp, Mux4CellIntrinsicOp,
|
||||
HasBeenResetIntrinsicOp, FPGAProbeIntrinsicOp,
|
||||
HasBeenResetIntrinsicOp, FPGAProbeIntrinsicOp, GenericIntrinsicOp,
|
||||
// Miscellaneous.
|
||||
BitsPrimOp, HeadPrimOp, MuxPrimOp, PadPrimOp, ShlPrimOp, ShrPrimOp,
|
||||
TailPrimOp, VerbatimExprOp, HWStructCastOp, BitCastOp, RefSendOp,
|
||||
|
@ -180,6 +180,7 @@ public:
|
|||
HANDLE(Mux2CellIntrinsicOp, Unhandled);
|
||||
HANDLE(HasBeenResetIntrinsicOp, Unhandled);
|
||||
HANDLE(FPGAProbeIntrinsicOp, Unhandled);
|
||||
HANDLE(GenericIntrinsicOp, Unhandled);
|
||||
|
||||
// Miscellaneous.
|
||||
HANDLE(BitsPrimOp, Unhandled);
|
||||
|
|
|
@ -1255,7 +1255,8 @@ parseModulePorts(OpAsmParser &parser, bool hasSSAIdentifiers,
|
|||
}
|
||||
|
||||
/// Print a paramter list for a module or instance.
|
||||
static void printParameterList(ArrayAttr parameters, OpAsmPrinter &p) {
|
||||
static void printParameterList(OpAsmPrinter &p, Operation *op,
|
||||
ArrayAttr parameters) {
|
||||
if (!parameters || parameters.empty())
|
||||
return;
|
||||
|
||||
|
@ -1283,7 +1284,7 @@ static void printFModuleLikeOp(OpAsmPrinter &p, FModuleLike op) {
|
|||
p.printSymbolName(op.getModuleName());
|
||||
|
||||
// Print the parameter list (if non-empty).
|
||||
printParameterList(op->getAttrOfType<ArrayAttr>("parameters"), p);
|
||||
printParameterList(p, op, op->getAttrOfType<ArrayAttr>("parameters"));
|
||||
|
||||
// Both modules and external modules have a body, but it is always empty for
|
||||
// external modules.
|
||||
|
@ -1372,6 +1373,18 @@ parseOptionalParameters(OpAsmParser &parser,
|
|||
});
|
||||
}
|
||||
|
||||
/// Shim to use with assemblyFormat, custom<ParameterList>.
|
||||
static ParseResult parseParameterList(OpAsmParser &parser,
|
||||
ArrayAttr ¶meters) {
|
||||
SmallVector<Attribute> parseParameters;
|
||||
if (failed(parseOptionalParameters(parser, parseParameters)))
|
||||
return failure();
|
||||
|
||||
parameters = ArrayAttr::get(parser.getContext(), parseParameters);
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
static ParseResult parseFModuleLikeOp(OpAsmParser &parser,
|
||||
OperationState &result,
|
||||
bool hasSSAIdentifiers) {
|
||||
|
@ -5764,6 +5777,9 @@ void GEQPrimOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
|||
void GTPrimOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
genericAsmResultNames(*this, setNameFn);
|
||||
}
|
||||
void GenericIntrinsicOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
genericAsmResultNames(*this, setNameFn);
|
||||
}
|
||||
void HeadPrimOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
genericAsmResultNames(*this, setNameFn);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,17 @@ firrtl.module @Intrinsics(in %ui : !firrtl.uint, in %clock: !firrtl.clock, in %u
|
|||
// CHECK-NEXT: firrtl.int.clock_gate %clock, %ui1, %ui1
|
||||
%cg0 = firrtl.int.clock_gate %clock, %ui1
|
||||
%cg1 = firrtl.int.clock_gate %clock, %ui1, %ui1
|
||||
|
||||
// CHECK-NEXT: firrtl.int.generic "clock_gate" %clock, %ui1 : (!firrtl.clock, !firrtl.uint<1>)
|
||||
// CHECK-NEXT: firrtl.int.generic "noargs" : () -> !firrtl.uint<32>
|
||||
// CHECK-NEXT: firrtl.int.generic "params" <FORMAT: none = "foobar"> : () -> !firrtl.bundle<x: uint<1>>
|
||||
// CHECK-NEXT: firrtl.int.generic "params_and_operand" <X: i64 = 123> %ui1 : (!firrtl.uint<1>) -> !firrtl.clock
|
||||
// CHECK-NEXT: firrtl.int.generic "inputs" %clock, %ui1, %clock : (!firrtl.clock, !firrtl.uint<1>, !firrtl.clock) -> ()
|
||||
%cg2 = firrtl.int.generic "clock_gate" %clock, %ui1 : (!firrtl.clock, !firrtl.uint<1>) -> !firrtl.clock
|
||||
%noargs = firrtl.int.generic "noargs" : () -> !firrtl.uint<32>
|
||||
%p = firrtl.int.generic "params" <FORMAT: none = "foobar"> : () -> !firrtl.bundle<x: uint<1>>
|
||||
%po = firrtl.int.generic "params_and_operand" <X: i64 = 123> %ui1 : (!firrtl.uint<1>) -> !firrtl.clock
|
||||
firrtl.int.generic "inputs" %clock, %ui1, %clock : (!firrtl.clock, !firrtl.uint<1>, !firrtl.clock) -> ()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: firrtl.module @FPGAProbe
|
||||
|
|
Loading…
Reference in New Issue