Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sim] Add printing operations and transformation from non-procedural to procedural flavor #7292

Merged
merged 22 commits into from
Jul 17, 2024
Merged
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
5 changes: 5 additions & 0 deletions include/circt/Dialect/Sim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
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)
20 changes: 20 additions & 0 deletions include/circt/Dialect/Sim/SimOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,24 @@
#define GET_OP_CLASSES
#include "circt/Dialect/Sim/Sim.h.inc"

namespace circt {
namespace sim {

/// Returns the value operand of a value formatting operation.
/// Returns a null value for all other operations.
static inline mlir::Value getFormattedValue(mlir::Operation *fmtOp) {
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatBinOp>(fmtOp))
return fmt.getValue();
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatDecOp>(fmtOp))
return fmt.getValue();
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatHexOp>(fmtOp))
return fmt.getValue();
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatCharOp>(fmtOp))
return fmt.getValue();
return {};
}

} // namespace sim
} // namespace circt

#endif // CIRCT_DIALECT_SIM_SIMOPS_H
38 changes: 38 additions & 0 deletions include/circt/Dialect/Sim/SimOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,42 @@ def FormatStringConcatOp : SimOp<"fmt.concat", [Pure]> {
];
}

def PrintFormattedOp : SimOp<"print"> {
let summary = "Print a formatted string on a given clock and condition";

let description = [{
Evaluate a format string and print it to the simulation console on the
rising edge of the given clock, if, and only if, the condition argument
is 'true'.

Multiple print operations in the same module and on the same clock edge
are performed according to their order of occurence in the IR. The order
of printing for operations in different modules, instances or on different
clocks is undefined.
}];


let arguments = (ins FormatStringType:$input, ClockType:$clock, I1:$condition);

let hasCanonicalizeMethod = true;
let assemblyFormat = "$input `on` $clock `if` $condition attr-dict";
}

def PrintFormattedProcOp : SimOp<"proc.print"> {
let summary = "Print a formatted string within a procedural region";

let description = [{
Evaluate a format string and print it to the simulation console.

This operation must be within a procedural region.
}];

let arguments = (ins FormatStringType:$input);

let hasVerifier = true;
let hasCanonicalizeMethod = true;

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

#endif // CIRCT_DIALECT_SIM_SIMOPS_TD
31 changes: 31 additions & 0 deletions include/circt/Dialect/Sim/SimPasses.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===- 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
#include "circt/Dialect/Sim/SimPasses.h.inc"

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

#endif // CIRCT_DIALECT_SIM_SIMPASSES_H
26 changes: 26 additions & 0 deletions include/circt/Dialect/Sim/SimPasses.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- 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_SEQPASSES
#define CIRCT_DIALECT_SIM_SEQPASSES

include "mlir/Pass/PassBase.td"

def ProceduralizeSim : Pass<"sim-proceduralize", "hw::HWModuleOp"> {
let summary = "Transform non-procedural to procedural operations.";
let description = [{Transform non-procedural simulation operations with clock
and enable to procedural operations wrapped in
a procedural region.}];
let dependentDialects = ["circt::hw::HWDialect, circt::seq::SeqDialect, mlir::scf::SCFDialect"];
}

#endif // CIRCT_DIALECT_SIM_SEQPASSES
2 changes: 2 additions & 0 deletions include/circt/InitAllPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "circt/Dialect/SSP/SSPPasses.h"
#include "circt/Dialect/SV/SVPasses.h"
#include "circt/Dialect/Seq/SeqPasses.h"
#include "circt/Dialect/Sim/SimPasses.h"
#include "circt/Dialect/SystemC/SystemCPasses.h"
#include "circt/Dialect/Verif/VerifPasses.h"
#include "circt/Tools/circt-bmc/Passes.h"
Expand Down Expand Up @@ -72,6 +73,7 @@ inline void registerAllPasses() {
ibis::registerPasses();
hw::registerPasses();
pipeline::registerPasses();
sim::registerPasses();
ssp::registerPasses();
systemc::registerPasses();
verif::registerPasses();
Expand Down
2 changes: 2 additions & 0 deletions lib/Dialect/Sim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ add_circt_dialect_library(CIRCTSim
MLIRPass
MLIRTransforms
)

add_subdirectory(Transforms)
48 changes: 47 additions & 1 deletion lib/Dialect/Sim/SimOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "circt/Dialect/Sim/SimOps.h"
#include "circt/Dialect/HW/ModuleImplementation.h"
#include "circt/Dialect/SV/SVOps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Interfaces/FunctionImplementation.h"

Expand Down Expand Up @@ -346,6 +345,53 @@ LogicalResult FormatStringConcatOp::canonicalize(FormatStringConcatOp op,
return success();
}

LogicalResult PrintFormattedOp::canonicalize(PrintFormattedOp op,
PatternRewriter &rewriter) {
// Remove ops with constant false condition.
if (auto cstCond = op.getCondition().getDefiningOp<hw::ConstantOp>()) {
if (cstCond.getValue().isZero()) {
rewriter.eraseOp(op);
return success();
}
}
return failure();
}

LogicalResult PrintFormattedProcOp::verify() {
// Check if we know for sure that the parent is not procedural.
auto *parentOp = getOperation()->getParentOp();

if (!parentOp)
return emitOpError("must be within a procedural region.");

if (isa<hw::HWDialect>(parentOp->getDialect())) {
if (!isa<hw::TriggeredOp>(parentOp))
return emitOpError("must be within a procedural region.");
return success();
}

if (isa<sv::SVDialect>(parentOp->getDialect())) {
if (!parentOp->hasTrait<sv::ProceduralRegion>())
return emitOpError("must be within a procedural region.");
return success();
}

// Don't fail for dialects that are not explicitly handled.
return success();
}

LogicalResult PrintFormattedProcOp::canonicalize(PrintFormattedProcOp op,
PatternRewriter &rewriter) {
// Remove empty prints.
if (auto litInput = op.getInput().getDefiningOp<FormatLitOp>()) {
if (litInput.getLiteral().empty()) {
rewriter.eraseOp(op);
return success();
}
}
return failure();
}

//===----------------------------------------------------------------------===//
// TableGen generated logic.
//===----------------------------------------------------------------------===//
Expand Down
19 changes: 19 additions & 0 deletions lib/Dialect/Sim/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
add_circt_dialect_library(CIRCTSimTransforms
ProceduralizeSim.cpp


DEPENDS
CIRCTSimTransformsIncGen

LINK_LIBS PUBLIC
CIRCTHW
CIRCTSim
CIRCTSeq
CIRCTSV
CIRCTComb
CIRCTSupport
MLIRIR
MLIRPass
MLIRSCFDialect
MLIRTransformUtils
)
Loading
Loading