Skip to content

Commit

Permalink
[FIRRTL][Sim][SV] DPI prototype
Browse files Browse the repository at this point in the history
SV emission is from #4856
  • Loading branch information
uenoku committed Apr 3, 2024
1 parent c5f4330 commit 3fe2ef3
Show file tree
Hide file tree
Showing 24 changed files with 720 additions and 11 deletions.
50 changes: 50 additions & 0 deletions include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,56 @@ def UnclockedAssumeIntrinsicOp : FIRRTLOp<"int.unclocked_assume", []> {
let hasCanonicalizer = 1;
}

//===----------------------------------------------------------------------===//
// DPI intrinsics
//===----------------------------------------------------------------------===//

def DPIImportAndCallIntrinsicOp : FIRRTLOp<"int.dpi.import_and_call",
[HasCustomSSAName]> {
let summary =
[{Intrinsic for importing and calling DPI functions. This should be
deprecated once DPI got in to firrt-spec.}];

// TODO: Add a reset and enable?
let arguments = (ins StrAttr:$function_name,
NonConstClockType:$clock,
Variadic<PassiveType>:$inputs);
let results = (outs Variadic<PassiveType>:$results);
let assemblyFormat = "$function_name $clock `(`$inputs `)` attr-dict `:` functional-type($inputs, $results)";
}

// def DPIImportOp : FIRRTLOp<"dpi.import",
// [Symbol, DeclareOpInterfaceMethods<PortList>]> {
// let summary = "Test for 'x";
// let description = [{}];
//
// let arguments = (ins FlatSymbolRefAttr:$sym_name,
// StrAttr: $function_name,
// DenseBoolArrayAttr:$argDirections,
// ArrayRefAttr:$argLocations,
// ArrayRefAttr:$argNames,
// ArrayRefAttr:$argTypes);
//
// let results = (outs);
// // TODO: Implement a custom prenter.
// let assemblyFormat = "$sym_name $function_name attr-dict";
// }

// def DPICallOp : FIRRTLOp<"dpi.call",
// [DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
// let summary = "Test for 'x";
// let description = [{}];
//
// let arguments = (ins FlatSymbolRefAttr:$sym_name,
// StrAttr: $function_name,
// DenseBoolArrayAttr:$argDirections,
// ArrayRefAttr:$argLocations,
// ArrayRefAttr:$argNames,
// ArrayRefAttr:$argTypes);
//
// let results = (outs);
// }

//===----------------------------------------------------------------------===//
// Other intrinsics
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 3 additions & 1 deletion include/circt/Dialect/FIRRTL/FIRRTLVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class ExprVisitor {
LTLConcatIntrinsicOp, LTLNotIntrinsicOp, LTLImplicationIntrinsicOp,
LTLEventuallyIntrinsicOp, LTLClockIntrinsicOp,
LTLDisableIntrinsicOp, Mux2CellIntrinsicOp, Mux4CellIntrinsicOp,
HasBeenResetIntrinsicOp, FPGAProbeIntrinsicOp, GenericIntrinsicOp,
HasBeenResetIntrinsicOp, FPGAProbeIntrinsicOp,
DPIImportAndCallIntrinsicOp, GenericIntrinsicOp,
// Miscellaneous.
BitsPrimOp, HeadPrimOp, MuxPrimOp, PadPrimOp, ShlPrimOp, ShrPrimOp,
TailPrimOp, VerbatimExprOp, HWStructCastOp, BitCastOp, RefSendOp,
Expand Down Expand Up @@ -180,6 +181,7 @@ class ExprVisitor {
HANDLE(Mux2CellIntrinsicOp, Unhandled);
HANDLE(HasBeenResetIntrinsicOp, Unhandled);
HANDLE(FPGAProbeIntrinsicOp, Unhandled);
HANDLE(DPIImportAndCallIntrinsicOp, Unhandled);
HANDLE(GenericIntrinsicOp, Unhandled);

// Miscellaneous.
Expand Down
81 changes: 81 additions & 0 deletions include/circt/Dialect/SV/SVStatements.td
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/Interfaces/FunctionInterfaces.td"
include "circt/Dialect/Emit/EmitOpInterfaces.td"

//===----------------------------------------------------------------------===//
// Control flow like-operations
Expand Down Expand Up @@ -879,3 +881,82 @@ def MacroDefOp : SVOp<"macro.def",
MacroDeclOp getReferencedMacro(const hw::HWSymbolCache *cache);
}];
}


//===----------------------------------------------------------------------===//
// Function/Call
//===----------------------------------------------------------------------===//

def FunctionDPIImportOp: SVOp<"function.dpi.import",
[DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = "Simulation failure condition";

let arguments = (ins FlatSymbolRefAttr:$callee);
let results = (outs);

let assemblyFormat = "$callee attr-dict";
}

// TODO: Add a interface for function declarations.
def FunctionDPIDeclareOp : SVOp<"function.dpi.decl", [IsolatedFromAbove, Symbol,
FunctionOpInterface, HasParent<"mlir::ModuleOp">]> {
let summary = "Import a DPI function";

let arguments = (ins
SymbolNameAttr:$sym_name,
TypeAttrOf<ModuleType>:$module_type,
OptionalAttr<StrAttr>:$verilogName);

let assemblyFormat =
"$sym_name (`function_name` $verilogName^)? attr-dict `:` $module_type $body";
let results = (outs);
let regions = (region AnyRegion:$body);

let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
mlir::FunctionType getFunctionType() {
return getModuleType().getFuncType();
}

void setFunctionTypeAttr(mlir::TypeAttr mlirType) {
// FIXME: This is really unsafe ...... probably we should implement our own
// FunctionOpInterface for named/ordered types.
assert(false);
}

/// Returns the argument types of this function.
ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); }

/// Returns the result types of this function.
ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }

::mlir::Region *getCallableRegion() { return nullptr; }
}];
}

def FunctionCallProceduralOp : SVOp<"function.call.procedural", [CallOpInterface,
DeclareOpInterfaceMethods<SymbolUserOpInterface>, ProceduralOp]> {
let summary = "Simulation failure condition";

let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$inputs);
let results = (outs Variadic<AnyType>);

let assemblyFormat =
"$callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)";
let extraClassDeclaration = [{
operand_range getArgOperands() {
return getInputs();
}
MutableOperandRange getArgOperandsMutable() {
return getInputsMutable();
}
mlir::CallInterfaceCallable getCallableForCallee() {
return (*this)->getAttrOfType<mlir::SymbolRefAttr>("callee");
}

/// Set the callee for this operation.
void setCalleeFromCallable(mlir::CallInterfaceCallable callee) {
(*this)->setAttr(getCalleeAttrName(), callee.get<mlir::SymbolRefAttr>());
}
}];
}
6 changes: 4 additions & 2 deletions include/circt/Dialect/SV/SVVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ class Visitor {
AlwaysCombOp, AlwaysFFOp, InitialOp, CaseOp,
// Other Statements.
AssignOp, BPAssignOp, PAssignOp, ForceOp, ReleaseOp, AliasOp,
FWriteOp, SystemFunctionOp, VerbatimOp,
FWriteOp, SystemFunctionOp, VerbatimOp, FunctionCallProceduralOp,
// Type declarations.
InterfaceOp, InterfaceSignalOp, InterfaceModportOp,
InterfaceInstanceOp, GetModportOp, AssignInterfaceSignalOp,
ReadInterfaceSignalOp, MacroDeclOp, MacroDefOp,
ReadInterfaceSignalOp, MacroDeclOp, MacroDefOp, FunctionDPIImportOp,
// Verification statements.
AssertOp, AssumeOp, CoverOp, AssertConcurrentOp, AssumeConcurrentOp,
CoverConcurrentOp,
Expand Down Expand Up @@ -127,6 +127,7 @@ class Visitor {
HANDLE(AliasOp, Unhandled);
HANDLE(FWriteOp, Unhandled);
HANDLE(SystemFunctionOp, Unhandled);
HANDLE(FunctionCallProceduralOp, Unhandled);
HANDLE(VerbatimOp, Unhandled);

// Type declarations.
Expand All @@ -139,6 +140,7 @@ class Visitor {
HANDLE(ReadInterfaceSignalOp, Unhandled);
HANDLE(MacroDefOp, Unhandled);
HANDLE(MacroDeclOp, Unhandled);
HANDLE(FunctionDPIImportOp, Unhandled);

// Verification statements.
HANDLE(AssertOp, Unhandled);
Expand Down
6 changes: 6 additions & 0 deletions include/circt/Dialect/Sim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@
add_circt_dialect(Sim sim)
add_circt_dialect_doc(Sim sim)
add_dependencies(circt-headers MLIRSimIncGen)

set(LLVM_TARGET_DEFINITIONS SimPasses.td)
mlir_tablegen(SimPasses.h.inc -gen-pass-decls)
add_public_tablegen_target(CIRCTSimTransformsIncGen)
add_dependencies(circt-headers CIRCTSimTransformsIncGen)
add_circt_doc(SimPasses SimPasses -gen-pass-doc)
2 changes: 2 additions & 0 deletions include/circt/Dialect/Sim/SimOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Interfaces/FunctionInterfaces.h"

#include "circt/Dialect/Seq/SeqDialect.h"
#include "circt/Dialect/Seq/SeqTypes.h"
Expand Down
77 changes: 77 additions & 0 deletions include/circt/Dialect/Sim/SimOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
include "mlir/Interfaces/SideEffectInterfaces.td"
include "circt/Dialect/Sim/SimDialect.td"
include "circt/Dialect/Seq/SeqTypes.td"
include "circt/Dialect/HW/HWTypes.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/FunctionInterfaces.td"

class SimOp<string mnemonic, list<Trait> traits = []> :
Op<SimDialect, mnemonic, traits>;
Expand Down Expand Up @@ -54,4 +57,78 @@ def FatalOp : SimOp<"fatal"> {
let assemblyFormat = "$clk `,` $cond attr-dict";
}

def DPIImportAndCallOp : SimOp<"dpi.import_and_call"> {
let summary = "Import and call DPI functions";

let arguments = (ins StrAttr:$function_name,
ClockType:$clock,
Variadic<AnyType>:$inputs);
let results = (outs Variadic<AnyType>);

let assemblyFormat =
"$function_name $clock `(` $inputs `)` attr-dict `:` functional-type($inputs, results)";
}

def DPIImportOp : SimOp<"dpi.import", [IsolatedFromAbove, Symbol,
FunctionOpInterface, HasParent<"mlir::ModuleOp">]> {
let summary = "Import a DPI function";

let arguments = (ins
SymbolNameAttr:$sym_name,
TypeAttrOf<ModuleType>:$module_type,
OptionalAttr<StrAttr>:$verilogName);

let assemblyFormat = "$sym_name (`function_name` $verilogName^)? attr-dict `:` $module_type $body";
let results = (outs);
let regions = (region AnyRegion:$body);

let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
mlir::FunctionType getFunctionType() {
return getModuleType().getFuncType();
}

void setFunctionTypeAttr(mlir::TypeAttr mlirType) {
// FIXME: This is really unsafe ...... probably we should implement our own
// FunctionOpInterface for named/ordered types.
assert(false);
}

/// Returns the argument types of this function.
ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); }

/// Returns the result types of this function.
ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }

::mlir::Region *getCallableRegion() { return nullptr; }
}];
}

def DPICallOp : SimOp<"dpi.call", [CallOpInterface,
DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = "Simulation failure condition";

let arguments = (ins FlatSymbolRefAttr:$callee,
ClockType:$clock, Variadic<AnyType>:$inputs);
let results = (outs Variadic<AnyType>);

let assemblyFormat = "$callee $clock `(` $inputs `)` attr-dict `:` functional-type($inputs, results)";
let extraClassDeclaration = [{
operand_range getArgOperands() {
return getInputs();
}
MutableOperandRange getArgOperandsMutable() {
return getInputsMutable();
}
mlir::CallInterfaceCallable getCallableForCallee() {
return (*this)->getAttrOfType<mlir::SymbolRefAttr>("callee");
}

/// Set the callee for this operation.
void setCalleeFromCallable(mlir::CallInterfaceCallable callee) {
(*this)->setAttr(getCalleeAttrName(), callee.get<mlir::SymbolRefAttr>());
}
}];
}

#endif // CIRCT_DIALECT_SIM_SIMOPS_TD
33 changes: 33 additions & 0 deletions include/circt/Dialect/Sim/SimPasses.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===- SimPasses.h - Sim pass entry points ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This header file defines prototypes that expose pass constructors.
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_SIM_SIMPASSES_H
#define CIRCT_DIALECT_SIM_SIMPASSES_H

#include "mlir/Pass/Pass.h"
#include "llvm/ADT/StringRef.h"

namespace circt {
namespace sim {

#define GEN_PASS_DECL_SEPARATEIMPORTANDCALL
#include "circt/Dialect/Sim/SimPasses.h.inc"

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

/// Generate the code for registering passes.
#define GEN_PASS_REGISTRATION
#include "circt/Dialect/Sim/SimPasses.h.inc"
} // namespace seq
} // namespace circt

#endif // CIRCT_DIALECT_SIM_SIMPASSES_H
23 changes: 23 additions & 0 deletions include/circt/Dialect/Sim/SimPasses.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- SimPasses.td - Sim pass definition file ------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains definitions for passes that work on the Sim dialect.
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_SIM_SIMPASSES
#define CIRCT_DIALECT_SIM_SIMPASSES

include "mlir/Pass/PassBase.td"

def SeparateImportAndCall: Pass<"separate-import-and-call-op", "mlir::ModuleOp"> {
let summary = "Lower sim.dpi.import_and_call op into import and call ops";
let constructor = "circt::sim::createSeparateImportAndCall()";
}

#endif // CIRCT_DIALECT_SIM_SIMPASSES
2 changes: 2 additions & 0 deletions include/circt/InitAllPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "circt/Dialect/FIRRTL/Passes.h"
#include "circt/Dialect/FSM/FSMPasses.h"
#include "circt/Dialect/HW/HWPasses.h"
#include "circt/Dialect/Sim/SimPasses.h"
#include "circt/Dialect/Handshake/HandshakePasses.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/LLHD/Transforms/Passes.h"
Expand Down Expand Up @@ -61,6 +62,7 @@ inline void registerAllPasses() {
msft::registerPasses();
om::registerPasses();
seq::registerPasses();
sim::registerPasses();
sv::registerPasses();
handshake::registerPasses();
ibis::registerPasses();
Expand Down
Loading

0 comments on commit 3fe2ef3

Please sign in to comment.