17 #include "llvm/ADT/TypeSwitch.h"
19 #define DEBUG_TYPE "lec-exporter"
21 using namespace circt;
28 struct Visitor :
public hw::StmtVisitor<Visitor, LogicalResult>,
29 public hw::TypeOpVisitor<Visitor, LogicalResult>,
30 public comb::CombinationalVisitor<Visitor, LogicalResult> {
31 using hw::StmtVisitor<Visitor, LogicalResult>::visitStmt;
32 using hw::TypeOpVisitor<Visitor, LogicalResult>::visitTypeOp;
33 using comb::CombinationalVisitor<Visitor, LogicalResult>::visitComb;
34 friend class hw::StmtVisitor<Visitor, LogicalResult>;
35 friend class hw::TypeOpVisitor<Visitor, LogicalResult>;
36 friend class comb::CombinationalVisitor<Visitor, LogicalResult>;
42 LogicalResult visit(ModuleOp op, llvm::StringRef targetModule) {
44 if (targetModule.empty() || hwModule.getName() == targetModule) {
46 <<
"Using module `" << hwModule.getName() <<
"`\n");
47 return visit(hwModule);
50 op.emitError(
"module not found");
56 for (
auto argument : op.getBodyBlock()->getArguments())
58 for (
auto &op : op.getOps())
59 if (failed(dispatch(&op)))
64 LogicalResult visitUnhandledOp(Operation *op) {
65 op->emitOpError(
"not supported");
70 LogicalResult dispatch(Operation *op) {
return dispatchStmtVisitor(op); }
76 LogicalResult visitStmt(hw::InstanceOp op) {
78 llvm::dyn_cast<hw::HWModuleOp>(op.getReferencedModuleSlow())) {
79 circuit->
addInstance(op.getInstanceName(), hwModule, op->getOperands(),
83 op.emitError(
"instantiated module `" + op.getModuleName() +
84 "` is not an HW module");
88 LogicalResult visitStmt(hw::OutputOp op) {
89 for (
auto operand : op.getOperands())
94 LogicalResult visitInvalidStmt(Operation *op) {
95 return dispatchTypeOpVisitor(op);
97 LogicalResult visitUnhandledStmt(Operation *op) {
98 return visitUnhandledOp(op);
106 circuit->
addConstant(op.getResult(), op.getValue());
110 LogicalResult visitInvalidTypeOp(Operation *op) {
111 return dispatchCombinationalVisitor(op);
113 LogicalResult visitUnhandledTypeOp(Operation *op) {
114 return visitUnhandledOp(op);
122 template <
typename OpTy,
typename FnTy>
123 LogicalResult visitVariadicCombOp(OpTy op, FnTy fn) {
124 if (!op.getTwoState())
125 return op.emitOpError(
"without 'bin' unsupported");
126 (circuit->*fn)(op.getResult(), op.getOperands());
131 template <
typename OpTy,
typename FnTy>
132 LogicalResult visitBinaryCombOp(OpTy op, FnTy fn) {
133 if (!op.getTwoState())
134 return op.emitOpError(
"without 'bin' unsupported");
135 (circuit->*fn)(op.getResult(), op.getLhs(), op.getRhs());
140 template <
typename OpTy,
typename FnTy>
141 LogicalResult visitUnaryCombOp(OpTy op, FnTy fn) {
142 if (!op.getTwoState())
143 return op.emitOpError(
"without 'bin' unsupported");
144 (circuit->*fn)(op.getResult(), op.getInput());
165 circuit->
performExtract(op.getResult(), op.getInput(), op.getLowBit());
168 LogicalResult visitComb(comb::ICmpOp op) {
169 if (!op.getTwoState())
170 return op.emitOpError(
"without 'bin' unsupported");
171 return circuit->
performICmp(op.getResult(), op.getPredicate(), op.getLhs(),
184 if (!op.getTwoState())
185 return op.emitOpError(
"without 'bin' unsupported");
186 circuit->
performMux(op.getResult(), op.getCond(), op.getTrueValue(),
196 LogicalResult visitComb(comb::ReplicateOp op) {
216 LogicalResult visitUnhandledComb(Operation *op) {
217 return visitUnhandledOp(op);
223 return Visitor(circuit).visit(builtinModule, moduleName);
227 return Visitor(circuit).visit(module);
mlir::LogicalResult run(mlir::ModuleOp &module)
Initializes the exporting by visiting the builtin module.
The representation of a circuit within a logical engine.
void performConcat(mlir::Value result, mlir::OperandRange operands)
void performAdd(mlir::Value result, mlir::OperandRange operands)
void performParity(mlir::Value result, mlir::Value input)
void performShl(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void addInstance(llvm::StringRef instanceName, circt::hw::HWModuleOp op, mlir::OperandRange arguments, mlir::ResultRange results)
void performMux(mlir::Value result, mlir::Value cond, mlir::Value trueValue, mlir::Value falseValue)
mlir::LogicalResult performICmp(mlir::Value result, circt::comb::ICmpPredicate predicate, mlir::Value lhs, mlir::Value rhs)
void performOr(mlir::Value result, mlir::OperandRange operands)
void performXor(mlir::Value result, mlir::OperandRange operands)
void performShrS(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void performMul(mlir::Value result, mlir::OperandRange operands)
void performSub(mlir::Value result, mlir::OperandRange operands)
void performDivU(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void addConstant(mlir::Value result, const mlir::APInt &value)
void performAnd(mlir::Value result, mlir::OperandRange operands)
void addInput(mlir::Value)
Add an input to the circuit; internally a new value gets allocated.
void performExtract(mlir::Value result, mlir::Value input, uint32_t lowBit)
void performModS(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void performReplicate(mlir::Value result, mlir::Value input)
void performShrU(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void performModU(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
void addOutput(mlir::Value)
Add an output to the circuit.
void performDivS(mlir::Value result, mlir::Value lhs, mlir::Value rhs)
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
mlir::raw_indented_ostream & dbgs()