Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
6 changes: 6 additions & 0 deletions lib/Tools/circt-bmc/LowerToBMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "circt/Support/LLVM.h"
#include "circt/Support/Namespace.h"
#include "circt/Tools/circt-bmc/Passes.h"
#include "mlir/Analysis/TopologicalSortUtils.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
Expand Down Expand Up @@ -60,6 +61,11 @@ void LowerToBMCPass::runOnOperation() {
return signalPassFailure();
}

if (!sortTopologically(&hwModule.getBodyRegion().front())) {
hwModule->emitError("could not resolve cycles in module");
return signalPassFailure();
}

// Create necessary function declarations and globals
auto *ctx = &getContext();
OpBuilder builder(ctx);
Expand Down
12 changes: 12 additions & 0 deletions test/Tools/circt-bmc/lower-to-bmc-errors.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,15 @@ hw.module @testModule(in %clk0 : !seq.clock, in %clkStruct : !hw.struct<clk: !se
verif.assert %1 : i1
hw.output %0, %in0, %in1 : i32, i32, i32
}

// -----

// expected-error @below {{could not resolve cycles in module}}
hw.module @testModule(in %in0 : i32) attributes {num_regs = 0 : i32, initial_values = []} {
%add = comb.add %in0, %or : i32
%or = comb.or %in0, %add : i32
// Dummy property
%true = hw.constant true
verif.assert %true : i1
hw.output
}
37 changes: 37 additions & 0 deletions test/Tools/circt-bmc/lower-to-bmc.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,40 @@ hw.module @seq(in %clk : !seq.clock, in %in0 : i32, in %in1 : i32, in %reg_state
verif.assert %1 : i1
hw.output %reg_state, %0 : i32, i32
}

// RUN: circt-opt --lower-to-bmc="top-module=nondominance bound=10" %s | FileCheck %s --check-prefix=CHECK2

// CHECK2: llvm.func @printf(!llvm.ptr, ...)
// CHECK2: func.func @nondominance() {
// CHECK2: [[BMC:%.+]] = verif.bmc bound 20 num_regs 1 initial_values [unit] init {
// CHECK2: [[FALSE:%.+]] = hw.constant false
// CHECK2: [[INIT_CLK:%.+]] = seq.to_clock [[FALSE]]
// CHECK2: verif.yield [[INIT_CLK]]
// CHECK2: } loop {
// CHECK2: ^bb0([[CLK:%.+]]: !seq.clock):
// CHECK2: [[FROM_CLK:%.+]] = seq.from_clock [[CLK]]
// CHECK2: [[TRUE:%.+]] = hw.constant true
// CHECK2: [[NCLK:%.+]] = comb.xor [[FROM_CLK]], [[TRUE]]
// CHECK2: [[NEW_CLOCK:%.+]] = seq.to_clock [[NCLK]]
// CHECK2: verif.yield [[NEW_CLOCK]]
// CHECK2: } circuit {
// CHECK2: ^bb0([[CLK:%.+]]: !seq.clock, [[ARG1:%.+]]: i32, [[ARG2:%.+]]: i32, [[ARG3:%.+]]: i32):
// CHECK2: [[OP0:%.+]] = comb.add [[ARG1]], [[ARG2]]
// CHECK2: [[OP2:%.+]] = comb.icmp eq [[OP0]], [[ARG1]]
// CHECK2: verif.assert [[OP2]]
// CHECK2: verif.yield [[ARG3]], [[OP0]]
// CHECK2: }
// CHECK2: [[SSTR_ADDR:%.+]] = llvm.mlir.addressof [[SSTR:@.+]] : !llvm.ptr
// CHECK2: [[FSTR_ADDR:%.+]] = llvm.mlir.addressof [[FSTR:@.+]] : !llvm.ptr
// CHECK2: [[SEL:%.+]] = llvm.select [[BMC]], [[SSTR_ADDR]], [[FSTR_ADDR]]
// CHECK2: llvm.call @printf([[SEL]])
// CHECK2: return
// CHECK2: }
// CHECK2: llvm.mlir.global private constant [[SSTR]]("Bound reached with no violations!\0A\00") {addr_space = 0 : i32}
// CHECK2: llvm.mlir.global private constant [[FSTR]]("Assertion can be violated!\0A\00") {addr_space = 0 : i32}
hw.module @nondominance(in %clk : !seq.clock, in %in0 : i32, in %in1 : i32, in %reg_state : i32, out out : i32, out reg_input : i32) attributes {num_regs = 1 : i32, initial_values = [unit]} {
%0 = comb.icmp eq %1, %in0 : i32
%1 = comb.add %in0, %in1 : i32
verif.assert %0 : i1
hw.output %reg_state, %1 : i32, i32
}
Loading