Skip to content

Commit

Permalink
[HandshakeToDC] Getting some working tests
Browse files Browse the repository at this point in the history
- Adding port name propagation to HandshakeToDC
- Configurable port names for clock and reset
- Add ESIPrimitives.sv to the list of SV files
- Adding test runs for a few integration tests which look like they
should work, but then disabling running if they don't.
  • Loading branch information
teqdruid committed Nov 20, 2024
1 parent da2c0f5 commit fe4b989
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 60 deletions.
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@ module {
return %r0, %r1 : i32, i32
}
}

1 change: 0 additions & 1 deletion integration_test/Dialect/Handshake/dot/dot.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,3 @@ module {
return %6 : i32
}
}

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
11 changes: 10 additions & 1 deletion integration_test/Dialect/Handshake/tuple_input/tuple_input.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 --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
84 changes: 40 additions & 44 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 @@ -692,35 +689,10 @@ class FuncOpConversion : public DCOpConversionPattern<handshake::FuncOp> {
}
};

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

size_t numInputs = mod.getNumInputPorts();
mod.insertInput(numInputs, "clk", 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.setPortAttrs(
numInputs + 1,
DictionaryAttr::get(ctx, {NamedAttribute(StringAttr::get(ctx, "dc.reset"),
UnitAttr::get(ctx))}));

// We must initialize any port attributes that are not set otherwise the
// verifier will fail.
for (size_t portNum = 0, e = mod.getNumPorts(); portNum < e; ++portNum) {
auto attrs = dyn_cast_or_null<DictionaryAttr>(mod.getPortAttrs(portNum));
if (attrs)
continue;
mod.setPortAttrs(portNum, DictionaryAttr::get(ctx, {}));
}
}

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 +707,43 @@ 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>();
/// Add DC clock and reset ports to the module.
void addClkRst(hw::HWModuleOp mod, StringRef clkName, StringRef rstName) {
auto *ctx = mod.getContext();

size_t numInputs = mod.getNumInputPorts();
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, rstName, IntegerType::get(ctx, 1));
mod.setPortAttrs(
numInputs + 1,
DictionaryAttr::get(ctx, {NamedAttribute(StringAttr::get(ctx, "dc.reset"),
UnitAttr::get(ctx))}));

// We must initialize any port attributes that are not set otherwise the
// verifier will fail.
for (size_t portNum = 0, e = mod.getNumPorts(); portNum < e; ++portNum) {
auto attrs = dyn_cast_or_null<DictionaryAttr>(mod.getPortAttrs(portNum));
if (attrs)
continue;
mod.setPortAttrs(portNum, DictionaryAttr::get(ctx, {}));
}
}

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 @@ -787,7 +783,7 @@ LogicalResult circt::handshaketodc::runHandshakeToDC(
RewritePatternSet patterns(ctx);

// Add handshake conversion patterns.
// Note: merge/control merge are not supported - these are non-deterministic
// Note: merge/control merge are not supported - these are non - deterministic
// operators and we do not care for them.
patterns
.add<BufferOpConversion, CondBranchConversionPattern,
Expand All @@ -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
Loading

0 comments on commit fe4b989

Please sign in to comment.