-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds Yosys integration
- Loading branch information
Showing
23 changed files
with
2,728 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
//===- ExportRTLIL.h - Export core dialects to Yosys RTLIL --===-*- 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 file declares passes which lower core dialects to RTLIL in-memory IR. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_CONVERSION_EXPORTRTLIL_H | ||
#define CIRCT_CONVERSION_EXPORTRTLIL_H | ||
|
||
#include "circt/Support/LLVM.h" | ||
#include "llvm/ADT/ArrayRef.h" | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace mlir { | ||
class Pass; | ||
} // namespace mlir | ||
|
||
namespace circt { | ||
|
||
#define GEN_PASS_DECL_EXPORTYOSYS | ||
#define GEN_PASS_DECL_EXPORTYOSYSPARALLEL | ||
#include "circt/Conversion/Passes.h.inc" | ||
|
||
std::unique_ptr<mlir::Pass> createYosysOptimizer(); | ||
std::unique_ptr<mlir::Pass> createYosysOptimizerParallel(); | ||
|
||
/// Register the `(import|export)-rtlil` MLIR translation. | ||
void registerRTLILImport(); | ||
void registerRTLILExport(); | ||
void registerRTLILTranslation(); | ||
|
||
} // namespace circt | ||
|
||
#endif // CIRCT_CONVERSION_EXPORTRTLIL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
//===- SeqVisitors.h - Seq Dialect Visitors ---------------------*- 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 file defines visitors for Seq dialect operations. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_DIALECT_SEQ_SEQVISITORS_H | ||
#define CIRCT_DIALECT_SEQ_SEQVISITORS_H | ||
|
||
#include "circt/Dialect/Seq/SeqOps.h" | ||
#include "llvm/ADT/TypeSwitch.h" | ||
|
||
namespace circt { | ||
namespace seq { | ||
|
||
/// This helps visit TypeOp nodes. | ||
template <typename ConcreteType, typename ResultType = void, | ||
typename... ExtraArgs> | ||
class SeqOpVisitor { | ||
public: | ||
ResultType dispatchSeqOpVisitor(Operation *op, ExtraArgs... args) { | ||
auto *thisCast = static_cast<ConcreteType *>(this); | ||
return TypeSwitch<Operation *, ResultType>(op) | ||
.template Case< | ||
// Registers. | ||
CompRegOp, CompRegClockEnabledOp, ShiftRegOp, FirRegOp, FIFOOp, | ||
// Memories. | ||
HLMemOp, ReadPortOp, WritePortOp, FirMemOp, FirMemReadOp, | ||
FirMemWriteOp, FirMemReadWriteOp, | ||
// Clock. | ||
ClockGateOp, ClockMuxOp, ClockDividerOp, ClockInverterOp, | ||
ConstClockOp, ToClockOp, FromClockOp>([&](auto expr) -> ResultType { | ||
return thisCast->visitSeq(expr, args...); | ||
}) | ||
.Default([&](auto expr) -> ResultType { | ||
return thisCast->visitInvalidSeqOp(op, args...); | ||
}); | ||
} | ||
|
||
/// This callback is invoked on any non-expression operations. | ||
ResultType visitInvalidSeqOp(Operation *op, ExtraArgs... args) { | ||
op->emitOpError("unknown seq op"); | ||
abort(); | ||
} | ||
|
||
/// This callback is invoked on any combinational operations that are not | ||
/// handled by the concrete visitor. | ||
ResultType visitUnhandledSeqOp(Operation *op, ExtraArgs... args) { | ||
return ResultType(); | ||
} | ||
|
||
#define HANDLE(OPTYPE, OPKIND) \ | ||
ResultType visitSeq(OPTYPE op, ExtraArgs... args) { \ | ||
return static_cast<ConcreteType *>(this)->visit##OPKIND##SeqOp(op, \ | ||
args...); \ | ||
} | ||
|
||
// Registers. | ||
HANDLE(CompRegOp, Unhandled); | ||
HANDLE(CompRegClockEnabledOp, Unhandled); | ||
HANDLE(ShiftRegOp, Unhandled); | ||
|
||
HANDLE(FirRegOp, Unhandled); | ||
HANDLE(FIFOOp, Unhandled); | ||
|
||
// Memories. | ||
HANDLE(HLMemOp, Unhandled); | ||
HANDLE(ReadPortOp, Unhandled); | ||
HANDLE(WritePortOp, Unhandled); | ||
|
||
// FIRRTL memory ops. | ||
HANDLE(FirMemOp, Unhandled); | ||
HANDLE(FirMemReadOp, Unhandled); | ||
HANDLE(FirMemWriteOp, Unhandled); | ||
HANDLE(FirMemReadWriteOp, Unhandled); | ||
|
||
// Clock gate. | ||
HANDLE(ClockGateOp, Unhandled); | ||
HANDLE(ClockMuxOp, Unhandled); | ||
HANDLE(ClockDividerOp, Unhandled); | ||
HANDLE(ClockInverterOp, Unhandled); | ||
|
||
// Tied-off clock | ||
HANDLE(ConstClockOp, Unhandled); | ||
|
||
// Clock casts. | ||
HANDLE(ToClockOp, Unhandled); | ||
HANDLE(FromClockOp, Unhandled); | ||
|
||
#undef HANDLE | ||
}; | ||
|
||
} // namespace seq | ||
} // namespace circt | ||
|
||
#endif // CIRCT_DIALECT_SEQ_SEQVISITORS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// REQUIRES: yosys-integration | ||
|
||
// RUN: circt-translate --export-rtlil %s | circt-translate --import-rtlil | circt-opt -canonicalize | FileCheck %s | ||
|
||
// CHECK-LABEL: hw.module @Arith(in %in1 : i2, in %in2 : i2, in %in3 : i2, out add : i2, out sub : i2, out mul : i2, out and : i2, out or : i2, out xor : i2) | ||
hw.module @Arith(in %in1 : i2, in %in2 : i2, in %in3: i2, out add : i2, out sub: i2, out mul: i2, out and: i2, out or: i2, out xor: i2 ) { | ||
%0 = comb.add %in1, %in2, %in3: i2 | ||
%1 = comb.sub %in1, %in2: i2 | ||
%2 = comb.mul %in1, %in2, %in3: i2 | ||
%3 = comb.and %in1, %in2, %in3: i2 | ||
%4 = comb.or %in1, %in2, %in3: i2 | ||
%5 = comb.xor %in1, %in2, %in3: i2 | ||
// CHECK-NEXT: %0 = comb.add %in1, %in2, %in3 : i2 | ||
// CHECK-NEXT: %1 = comb.sub %in1, %in2 : i2 | ||
// CHECK-NEXT: %2 = comb.mul %in1, %in2, %in3 : i2 | ||
// CHECK-NEXT: %3 = comb.and %in1, %in2, %in3 : i2 | ||
// CHECK-NEXT: %4 = comb.or %in1, %in2, %in3 : i2 | ||
// CHECK-NEXT: %5 = comb.xor %in1, %in2, %in3 : i2 | ||
// CHECK-NEXT: hw.output %0, %1, %2, %3, %4, %5 : i2, i2, i2, i2, i2, i2 | ||
hw.output %0, %1, %2, %3, %4, %5 : i2, i2, i2, i2, i2, i2 | ||
} | ||
|
||
// CHECK-LABEL: hw.module @ICmp(in %a : i2, in %b : i2, out eq : i1, out ne : i1, out slt : i1, out sle : i1, out sgt : i1, out sge : i1, out ult : i1, out ule : i1, out ugt : i1, out uge : i1) | ||
hw.module @ICmp(in %a : i2, in %b : i2, out eq : i1, | ||
out ne: i1, out slt: i1, out sle: i1, out sgt: i1, out sge: i1, | ||
out ult: i1, out ule: i1, out ugt: i1, out uge: i1 | ||
) { | ||
%eq = comb.icmp eq %a, %b : i2 | ||
%ne = comb.icmp ne %a, %b : i2 | ||
%slt = comb.icmp slt %a, %b : i2 | ||
%sle = comb.icmp sle %a, %b : i2 | ||
%sgt = comb.icmp sgt %a, %b : i2 | ||
%sge = comb.icmp sge %a, %b : i2 | ||
%ult = comb.icmp ult %a, %b : i2 | ||
%ule = comb.icmp ule %a, %b : i2 | ||
%ugt = comb.icmp ugt %a, %b : i2 | ||
%uge = comb.icmp uge %a, %b : i2 | ||
// CHECK-NEXT: %0 = comb.icmp eq %a, %b : i2 | ||
// CHECK-NEXT: %1 = comb.icmp ne %a, %b : i2 | ||
// CHECK-NEXT: %2 = comb.icmp slt %a, %b : i2 | ||
// CHECK-NEXT: %3 = comb.icmp sle %a, %b : i2 | ||
// CHECK-NEXT: %4 = comb.icmp sgt %a, %b : i2 | ||
// CHECK-NEXT: %5 = comb.icmp sge %a, %b : i2 | ||
// CHECK-NEXT: %6 = comb.icmp ult %a, %b : i2 | ||
// CHECK-NEXT: %7 = comb.icmp ule %a, %b : i2 | ||
// CHECK-NEXT: %8 = comb.icmp ugt %a, %b : i2 | ||
// CHECK-NEXT: %9 = comb.icmp uge %a, %b : i2 | ||
// CHECK-NEXT: hw.output %0, %1, %2, %3, %4, %5, %6, %7, %8, %9 : i1, i1, i1, i1, i1, i1, i1, i1, i1, i1 | ||
hw.output %eq, %ne, %slt, %sle, %sgt, %sge, %ult, %ule, %ugt, %uge : i1, i1, i1, i1, i1, i1, i1, i1, i1, i1 | ||
} | ||
|
||
|
||
// CHECK-LABEL: hw.module @counter(in %clk : i1, out o : i8) | ||
hw.module @counter(in %clk: i1, out o: i8) { | ||
// CHECK-NEXT: %c1_i8 = hw.constant 1 : i8 | ||
// CHECK-NEXT: %0 = seq.to_clock %clk | ||
// CHECK-NEXT: %reg = seq.compreg %1, %0 : i8 | ||
// CHECK-NEXT: %1 = comb.add %reg, %c1_i8 : i8 | ||
// CHECK-NEXT: hw.output %reg : i8 | ||
%seq_clk = seq.to_clock %clk | ||
%reg = seq.compreg %added, %seq_clk : i8 | ||
%one = hw.constant 1 : i8 | ||
%added = comb.add %reg, %one : i8 | ||
hw.output %reg : i8 | ||
} | ||
|
||
// CHECK-LABEL: hw.module @misc(in %cond : i1, in %in1 : i2, in %in2 : i2, in %in3 : i5, out mux : i2, out extract : i2, out concat : i9, out replicate : i6, out shl : i5, out parity : i1) | ||
hw.module @misc(in %cond:i1, in %in1 : i2, in %in2 : i2, in %in3: i5, | ||
out mux : i2, out extract: i2, out concat: i9, out replicate: i6, out shl: i5, out parity: i1 ) { | ||
// CHECK-NEXT: %0 = comb.extract %in3 from 3 : (i5) -> i2 | ||
// CHECK-NEXT: %1 = comb.concat %in1, %in2, %in3 : i2, i2, i5 | ||
// CHECK-NEXT: %2 = comb.replicate %in1 : (i2) -> i6 | ||
// CHECK-NEXT: %3 = comb.mux %cond, %in1, %in2 : i2 | ||
// CHECK-NEXT: %4 = comb.shl %in3, %in3 : i5 | ||
// CHECK-NEXT: %5 = comb.parity %in3 : i5 | ||
// CHECK-NEXT: hw.output %3, %0, %1, %2, %4, %5 : i2, i2, i9, i6, i5, i1 | ||
%mux = comb.mux %cond, %in1, %in2 : i2 | ||
%extract = comb.extract %in3 from 3 : (i5) -> i2 | ||
%concat = comb.concat %in1, %in2, %in3 : i2, i2, i5 | ||
%replicate = comb.replicate %in1 : (i2) -> i6 | ||
%shl = comb.shl %in3, %in3 : i5 | ||
%partiy = comb.parity %in3 : i5 | ||
hw.output %mux, %extract, %concat, %replicate, %shl, %partiy: i2, i2, i9, i6, i5, i1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// REQUIRES: libz3 | ||
// REQUIRES: circt-lec-jit | ||
// REQUIRES: yosys-integration | ||
|
||
// Run synthesis and check the LEC. | ||
// RUN: circt-opt --pass-pipeline='builtin.module(yosys-optimizer{passes=synth},canonicalize)' -o %t.mlir %s | ||
|
||
// RUN: circt-lec %s %t.mlir -c1=Arith -c2=Arith --shared-libs=%libz3 | FileCheck %s --check-prefix=COMB | ||
// COMB: c1 == c2 | ||
|
||
hw.module @Arith(in %in1 : i2, in %in2 : i2, out add : i2, out sub: i2, out mul: i2, out and: i2, out or: i2, out xor: i2 ) { | ||
%0 = comb.add %in1, %in2: i2 | ||
%1 = comb.sub %in1, %in2: i2 | ||
%2 = comb.mul %in1, %in2: i2 | ||
%3 = comb.and %in1, %in2: i2 | ||
%4 = comb.or %in1, %in2: i2 | ||
%5 = comb.xor %in1, %in2: i2 | ||
hw.output %0, %1, %2, %3, %4, %5 : i2, i2, i2, i2, i2, i2 | ||
} | ||
|
||
// RUN: circt-lec %s %t.mlir -c1=ICmp -c2=ICmp --shared-libs=%libz3 | FileCheck %s --check-prefix=ICMP | ||
// ICMP: c1 == c2 | ||
hw.module @ICmp(in %a : i2, in %b : i2, out eq : i1, | ||
out ne: i1, out slt: i1, out sle: i1, out sgt: i1, out sge: i1, | ||
out ult: i1, out ule: i1, out ugt: i1, out uge: i1 | ||
) { | ||
%eq = comb.icmp eq %a, %b : i2 | ||
%ne = comb.icmp ne %a, %b : i2 | ||
%slt = comb.icmp slt %a, %b : i2 | ||
%sle = comb.icmp sle %a, %b : i2 | ||
%sgt = comb.icmp sgt %a, %b : i2 | ||
%sge = comb.icmp sge %a, %b : i2 | ||
%ult = comb.icmp ult %a, %b : i2 | ||
%ule = comb.icmp ule %a, %b : i2 | ||
%ugt = comb.icmp ugt %a, %b : i2 | ||
%uge = comb.icmp uge %a, %b : i2 | ||
hw.output %eq, %ne, %slt, %sle, %sgt, %sge, %ult, %ule, %ugt, %uge : i1, i1, i1, i1, i1, i1, i1, i1, i1, i1 | ||
} | ||
|
||
// RUN: circt-lec %s %t.mlir -c1=misc -c2=misc --shared-libs=%libz3 | FileCheck %s --check-prefix=MISC | ||
// MISC: c1 == c2 | ||
hw.module @misc(in %cond:i1, in %in1 : i2, in %in2 : i2, in %in3: i5, | ||
out mux : i2, out extract: i2, out concat: i9, out replicate: i6, out shl: i5, out parity: i1 ) { | ||
%mux = comb.mux %cond, %in1, %in2 : i2 | ||
%extract = comb.extract %in3 from 3 : (i5) -> i2 | ||
%concat = comb.concat %in1, %in2, %in3 : i2, i2, i5 | ||
%replicate = comb.replicate %in1 : (i2) -> i6 | ||
%shl = comb.shl %in3, %in3 : i5 | ||
%partiy = comb.parity %in3 : i5 | ||
hw.output %mux, %extract, %concat, %replicate, %shl, %partiy: i2, i2, i9, i6, i5, i1 | ||
} | ||
|
||
// These are incorrectly lowered now(LEC failure). | ||
// * comb.shrs | ||
// * hw.array_create + hw.array_get | ||
// hw.module @MultibitMux(in %a_0 : i1, in %a_1 : i1, in %a_2 : i1, in %sel : i2, out b : i1) { | ||
// %0 = hw.array_create %a_0, %a_2, %a_1, %a_0 : i1 | ||
// %1 = hw.array_get %0[%sel] : !hw.array<4xi1>, i2 | ||
// hw.output %1 : i1 | ||
// } |
Oops, something went wrong.