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

[HandshakeToDC] Getting some working tests #7858

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
4 changes: 1 addition & 3 deletions include/circt/Conversion/HandshakeToDC.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ namespace circt {
#define GEN_PASS_DECL_HANDSHAKETODC
#include "circt/Conversion/Passes.h.inc"

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

namespace handshaketodc {
using ConvertedOps = DenseSet<Operation *>;

Expand All @@ -37,7 +35,7 @@ using ConvertedOps = DenseSet<Operation *>;
// pattern that converts the container operation (e.g. `op`).
// `configureTarget` can be provided to specialize legalization.
LogicalResult runHandshakeToDC(
mlir::Operation *op,
mlir::Operation *op, HandshakeToDCOptions options,
llvm::function_ref<void(TypeConverter &typeConverter,
ConvertedOps &convertedOps,
RewritePatternSet &patterns)>
Expand Down
7 changes: 6 additions & 1 deletion include/circt/Conversion/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,13 @@ def HandshakeToDC : Pass<"lower-handshake-to-dc", "mlir::ModuleOp"> {
function with graph region behaviour. Thus, for now, we just use `hw.module`
as a container operation.
}];
let constructor = "circt::createHandshakeToDCPass()";
let dependentDialects = ["dc::DCDialect", "mlir::func::FuncDialect", "hw::HWDialect"];
let options = [
Option<"clkName", "clk-name", "std::string", "\"clk\"",
"Name of the clock signal to use in the generated DC module">,
Option<"rstName", "rst-name", "std::string", "\"rst\"",
"Name of the reset signal to use in the generated DC module">,
];
}

//===----------------------------------------------------------------------===//
Expand Down
3 changes: 3 additions & 0 deletions integration_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ if (ESI_RUNTIME)
endif()
endif()

get_target_property(ESI_PrimsDir ESIPrimitives SOURCE_DIR)
set(ESI_Prims "${ESI_PrimsDir}/ESIPrimitives.sv")

set(CIRCT_INTEGRATION_TIMEOUT 60) # Set a 60s timeout on individual tests.
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_init_none --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_init_none --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.
// TODO: This test does not pass with DC. Debug.
// RUNx: hlstool %s --dynamic-hw --dc --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_init_none --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUNx: hlstool %s --dynamic-hw --dc --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_init_none --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s


// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand All @@ -17,4 +28,3 @@ module {
return %f#0 : none
}
}

Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_initial_values --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_initial_values --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.
// TODO: This test does not pass with DC. Debug.
// RUNx: hlstool %s --dynamic-hw --dc --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_initial_values --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUNx: hlstool %s --dynamic-hw --dc --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=buffer_initial_values --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand Down
10 changes: 10 additions & 0 deletions integration_test/Dialect/Handshake/max/max.mlir
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=max --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=max --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.

// RUN: hlstool %s --dynamic-hw --dc --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=max --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --dc --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=max --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// CHECK: ** TEST
// CHECK-NEXT: ********************************
// CHECK-NEXT: ** max.oneInput
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_backedge --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_backedge --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.
// TODO: This test does not pass with DC. Debug.
// RUNx: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_backedge --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUNx: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_backedge --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand Down
11 changes: 11 additions & 0 deletions integration_test/Dialect/Handshake/sync_op/sync_op.mlir
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_op --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_op --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.
// TODO: This test does not pass with DC. Debug.
// RUNx: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_op --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUNx: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables > %t.sv && \
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=sync_op --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s


// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_input --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_input --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.

// RUN: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_input --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// RUN: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=all --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv && \
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_input --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand All @@ -16,4 +26,3 @@ module {
return %sum, %arg1 : i32, none
}
}

Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
// REQUIRES: iverilog,cocotb

// Test the original HandshakeToHW flow.

// RUN: hlstool %s --dynamic-hw --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_packing --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s

// Test the DC lowering flow.
// TODO: This test does not pass with DC. Debug.
// RUNx: hlstool %s --dynamic-hw --dc --input-level core --buffering-strategy=cycles --verilog --lowering-options=disallowLocalVariables,disallowPackedStructAssignments > %t.sv
// RUNx: circt-cocotb-driver.py --objdir=%T --topLevel=top --pythonModule=tuple_packing --pythonFolder="%S,%S/.." %t.sv %esi_prims 2>&1 | FileCheck %s

// CHECK: ** TEST
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0

Expand Down
2 changes: 2 additions & 0 deletions integration_test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@
if ieee_sims and ieee_sims[-1][1] == config.iverilog_path:
config.available_features.add('ieee-sim-iverilog')

config.substitutions.append(("%esi_prims", config.esi_prims))

# Enable ESI runtime tests.
if config.esi_runtime == "1":
config.available_features.add('esi-runtime')
Expand Down
1 change: 1 addition & 0 deletions integration_test/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ config.clang_tidy_path = "@CLANG_TIDY_PATH@"
config.have_systemc = "@HAVE_SYSTEMC@"
config.esi_runtime = "@ESI_RUNTIME@"
config.esi_runtime_path = "@ESIRuntimePath@"
config.esi_prims = "@ESI_Prims@"
config.bindings_python_enabled = @CIRCT_BINDINGS_PYTHON_ENABLED@
config.bindings_tcl_enabled = @CIRCT_BINDINGS_TCL_ENABLED@
config.lec_enabled = "@CIRCT_LEC_ENABLED@"
Expand Down
40 changes: 18 additions & 22 deletions lib/Conversion/HandshakeToDC/HandshakeToDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,25 +628,22 @@ class MuxOpConversionPattern : public DCOpConversionPattern<handshake::MuxOp> {
static hw::ModulePortInfo getModulePortInfoHS(const TypeConverter &tc,
handshake::FuncOp funcOp) {
SmallVector<hw::PortInfo> inputs, outputs;
auto *ctx = funcOp->getContext();
auto ft = funcOp.getFunctionType();
funcOp.resolveArgAndResNames();

// Add all inputs of funcOp.
for (auto [index, type] : llvm::enumerate(ft.getInputs())) {
inputs.push_back({{StringAttr::get(ctx, "in" + std::to_string(index)),
tc.convertType(type), hw::ModulePort::Direction::Input},
for (auto [index, type] : llvm::enumerate(ft.getInputs()))
inputs.push_back({{funcOp.getArgName(index), tc.convertType(type),
hw::ModulePort::Direction::Input},
index,
{}});
}

// Add all outputs of funcOp.
for (auto [index, type] : llvm::enumerate(ft.getResults())) {
outputs.push_back(
{{StringAttr::get(ctx, "out" + std::to_string(index)),
tc.convertType(type), hw::ModulePort::Direction::Output},
index,
{}});
}
for (auto [index, type] : llvm::enumerate(ft.getResults()))
outputs.push_back({{funcOp.getResName(index), tc.convertType(type),
hw::ModulePort::Direction::Output},
index,
{}});

return hw::ModulePortInfo{inputs, outputs};
}
Expand Down Expand Up @@ -693,16 +690,16 @@ class FuncOpConversion : public DCOpConversionPattern<handshake::FuncOp> {
};

/// Add DC clock and reset ports to the module.
static void addClkRst(hw::HWModuleOp mod) {
void addClkRst(hw::HWModuleOp mod, StringRef clkName, StringRef rstName) {
auto *ctx = mod.getContext();

size_t numInputs = mod.getNumInputPorts();
mod.insertInput(numInputs, "clk", seq::ClockType::get(ctx));
mod.insertInput(numInputs, clkName, seq::ClockType::get(ctx));
mod.setPortAttrs(
numInputs,
DictionaryAttr::get(ctx, {NamedAttribute(StringAttr::get(ctx, "dc.clock"),
UnitAttr::get(ctx))}));
mod.insertInput(numInputs + 1, "rst", IntegerType::get(ctx, 1));
mod.insertInput(numInputs + 1, rstName, IntegerType::get(ctx, 1));
mod.setPortAttrs(
numInputs + 1,
DictionaryAttr::get(ctx, {NamedAttribute(StringAttr::get(ctx, "dc.reset"),
Expand All @@ -721,6 +718,7 @@ static void addClkRst(hw::HWModuleOp mod) {
class HandshakeToDCPass
: public circt::impl::HandshakeToDCBase<HandshakeToDCPass> {
public:
using Base::Base;
void runOnOperation() override {
mlir::ModuleOp mod = getOperation();
auto targetModifier = [](mlir::ConversionTarget &target) {
Expand All @@ -735,19 +733,17 @@ class HandshakeToDCPass
patterns.add<ReturnOpConversion>(typeConverter, mod.getContext());
};

LogicalResult res = runHandshakeToDC(mod, patternBuilder, targetModifier);
LogicalResult res =
runHandshakeToDC(mod, circt::HandshakeToDCOptions{clkName, rstName},
patternBuilder, targetModifier);
if (failed(res))
signalPassFailure();
}
};
} // namespace

std::unique_ptr<mlir::Pass> circt::createHandshakeToDCPass() {
return std::make_unique<HandshakeToDCPass>();
}

LogicalResult circt::handshaketodc::runHandshakeToDC(
mlir::Operation *op,
mlir::Operation *op, circt::HandshakeToDCOptions options,
llvm::function_ref<void(TypeConverter &typeConverter,
handshaketodc::ConvertedOps &convertedOps,
RewritePatternSet &patterns)>
Expand Down Expand Up @@ -809,7 +805,7 @@ LogicalResult circt::handshaketodc::runHandshakeToDC(
// Add clock and reset ports to each converted module.
for (auto &op : convertedOps)
if (auto mod = dyn_cast<hw::HWModuleOp>(op); mod)
addClkRst(mod);
addClkRst(mod, options.clkName, options.rstName);

return success();
}
4 changes: 2 additions & 2 deletions lib/Dialect/ESI/ESIPrimitives.sv
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
/// | --- | ----- | --------- | ------- | ------ | ------------------ |
///
module ESI_PipelineStage # (
int WIDTH = 8
parameter WIDTH = 8
) (
input logic clk,
input logic rst,
Expand Down Expand Up @@ -80,7 +80,7 @@ module ESI_PipelineStage # (
// Did we accept a token this cycle?
wire a_rcv = a_ready && a_valid;

always_ff @(posedge clk) begin
always @(posedge clk) begin
if (rst) begin
l_valid <= 1'b0;
x_valid_reg <= 1'b0;
Expand Down
4 changes: 2 additions & 2 deletions lib/Dialect/Ibis/Transforms/IbisConvertHandshakeToDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ void ConvertHandshakeToDCPass::runOnOperation() {
typeConverter, classOp.getContext());
};

LogicalResult res =
handshaketodc::runHandshakeToDC(classOp, patternBuilder, targetModifier);
LogicalResult res = handshaketodc::runHandshakeToDC(
classOp, {"clk", "rst"}, patternBuilder, targetModifier);
if (failed(res))
signalPassFailure();
}
Expand Down
4 changes: 2 additions & 2 deletions test/Conversion/HandshakeToDC/basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ handshake.func @test_control_fixed_index_type(%arg0 : i4, %arg1 : i4) -> (i4, i3
// CHECK: %[[VAL_3]], %[[VAL_4]] = dc.branch %[[VAL_14]]
// CHECK: hw.output %[[VAL_5]], %[[VAL_10]] : !dc.token, !dc.value<index>
// CHECK: }
handshake.func @branch_and_merge(%0 : i1, %1 : none) -> (none, index) {
handshake.func @branch_and_merge(%arg0 : i1, %arg1 : none) -> (none, index) {
%out, %idx = control_merge %true, %false : none, index
%true, %false = cond_br %0, %1 : none
%true, %false = cond_br %arg0, %arg1 : none
return %out, %idx : none, index
}

Expand Down
11 changes: 9 additions & 2 deletions tools/hlstool/hlstool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,17 @@ static LogicalResult doHLSFlowDynamic(
addIRLevel(IRLevel::RTL, [&]() {
pm.nest<handshake::FuncOp>().addPass(createSimpleCanonicalizerPass());
if (withDC) {
pm.addPass(circt::createHandshakeToDCPass());
pm.addPass(circt::dc::createDCMaterializeForksSinksPass());
pm.addPass(circt::createHandshakeToDC({"clock", "reset"}));
// This pass sometimes resolves an error in the
pm.addPass(createSimpleCanonicalizerPass());
pm.nest<hw::HWModuleOp>().addPass(
circt::dc::createDCMaterializeForksSinksPass());
// TODO: We assert without a canonicalizer pass here. Debug.
pm.addPass(createSimpleCanonicalizerPass());
pm.addPass(circt::createDCToHWPass());
pm.addPass(createSimpleCanonicalizerPass());
pm.addPass(circt::createMapArithToCombPass());
pm.addPass(createSimpleCanonicalizerPass());
} else {
pm.addPass(circt::createHandshakeToHWPass());
}
Expand Down
Loading