diff --git a/docs/Dialects/ICE40/RationaleICE40.md b/docs/Dialects/ICE40/RationaleICE40.md new file mode 100644 index 000000000000..ee8aaf8920fb --- /dev/null +++ b/docs/Dialects/ICE40/RationaleICE40.md @@ -0,0 +1,17 @@ +# `ice40` Dialect Rationale + +This document describes various design points of the ice40 dialect, a +dialect that matches the technology library used in the Lattice ICE40 family +of FPGAs. + +## Introduction to the `ice40` Dialect + +The `ice40` dialect provides a collection of operations that match the +documented operations for the ICE40 family of FPGAs. The dialect hues closely +to the documentation. + +The intent of the dialect is as a target of synthesis. + +## Type System for `ice40` Dialect + +The dialect uses signless 1-bit integers for all values. diff --git a/include/circt/Dialect/CMakeLists.txt b/include/circt/Dialect/CMakeLists.txt index e5b55dcb068e..62155eaf5b97 100644 --- a/include/circt/Dialect/CMakeLists.txt +++ b/include/circt/Dialect/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(FSM) add_subdirectory(Handshake) add_subdirectory(HW) add_subdirectory(HWArith) +add_subdirectory(ICE40) add_subdirectory(Interop) add_subdirectory(LLHD) add_subdirectory(LoopSchedule) diff --git a/include/circt/Dialect/ICE40/CMakeLists.txt b/include/circt/Dialect/ICE40/CMakeLists.txt new file mode 100644 index 000000000000..8b5453d3a86f --- /dev/null +++ b/include/circt/Dialect/ICE40/CMakeLists.txt @@ -0,0 +1,3 @@ +add_circt_dialect(ICE40 ice40) + +set(LLVM_TARGET_DEFINITIONS ICE40.td) diff --git a/include/circt/Dialect/ICE40/ICE40.td b/include/circt/Dialect/ICE40/ICE40.td new file mode 100644 index 000000000000..4c8a8b804375 --- /dev/null +++ b/include/circt/Dialect/ICE40/ICE40.td @@ -0,0 +1,20 @@ +//===- ICE40.td - ICE40 FPGA dialect definition ------------*- tablegen -*-===// +// +// 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 is the top level file for the ICE40 dialect. This dialect targets the +// Lattice ICE40 FPGA technology library. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_ICE40_ICE40_TD +#define CIRCT_DIALECT_ICE40_ICE40_TD + +include "circt/Dialect/ICE40/ICE40Dialect.td" +include "circt/Dialect/ICE40/ICE40Ops.td" + +#endif // CIRCT_DIALECT_ICE40_ICE40_TD diff --git a/include/circt/Dialect/ICE40/ICE40Dialect.h b/include/circt/Dialect/ICE40/ICE40Dialect.h new file mode 100644 index 000000000000..170184b57c9d --- /dev/null +++ b/include/circt/Dialect/ICE40/ICE40Dialect.h @@ -0,0 +1,23 @@ +//===- ICE40Dialect.h - ICE40 dialect declaration ---------------*- 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 an ICE40 MLIR dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_ICE40_ICE40DIALECT_H +#define CIRCT_DIALECT_ICE40_ICE40DIALECT_H + +#include "circt/Support/LLVM.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Dialect.h" + +// Pull in the dialect definition. +#include "circt/Dialect/ICE40/ICE40Dialect.h.inc" + +#endif // CIRCT_DIALECT_ICE40_ICE40DIALECT_H diff --git a/include/circt/Dialect/ICE40/ICE40Dialect.td b/include/circt/Dialect/ICE40/ICE40Dialect.td new file mode 100644 index 000000000000..a21f9e510eb8 --- /dev/null +++ b/include/circt/Dialect/ICE40/ICE40Dialect.td @@ -0,0 +1,33 @@ +//===- ICE40Dialect.td - ICE40 dialect definition ----------*- tablegen -*-===// +// +// 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 contains the ICE40Dialect definition to be included in other files. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_ICE40_ICE40DIALECT +#define CIRCT_DIALECT_ICE40_ICE40DIALECT + +include "mlir/IR/OpBase.td" + +def ICE40Dialect : Dialect { + let name = "ice40"; + let cppNamespace = "::circt::ice40"; + + let summary = "Types and operations for the ICE40 technology library dialect"; + let description = [{ + This dialect defines the `ice40` dialect, which is a dialect of the technology + library for the Lattice ICE40 family of products. + }]; +} + +// Base class for the operation in this dialect. +class ICE40Op traits = []> : + Op; + +#endif // CIRCT_DIALECT_ICE40_ICE40DIALECT diff --git a/include/circt/Dialect/ICE40/ICE40Ops.h b/include/circt/Dialect/ICE40/ICE40Ops.h new file mode 100644 index 000000000000..4e3475583669 --- /dev/null +++ b/include/circt/Dialect/ICE40/ICE40Ops.h @@ -0,0 +1,23 @@ +//===- ICE40Ops.h - Declare ICE40 dialect operations ------------*- 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 the operation classes for the ICE40 dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_ICE40_ICE40OPS_H +#define CIRCT_DIALECT_ICE40_ICE40OPS_H + +#include "circt/Dialect/ICE40/ICE40Dialect.h" +#include "mlir/Bytecode/BytecodeOpInterface.h" +#include "mlir/IR/OpImplementation.h" + +#define GET_OP_CLASSES +#include "circt/Dialect/ICE40/ICE40.h.inc" + +#endif // CIRCT_DIALECT_ICE40_ICE40OPS_H diff --git a/include/circt/Dialect/ICE40/ICE40Ops.td b/include/circt/Dialect/ICE40/ICE40Ops.td new file mode 100644 index 000000000000..9fdc6bfcddaf --- /dev/null +++ b/include/circt/Dialect/ICE40/ICE40Ops.td @@ -0,0 +1,74 @@ +//===- ICE40Ops.td - ICE40 ops ============-----------------*- tablegen -*-===// +// +// 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 defines the ICE40 ops, matching the technology library. Documentation +// is here: https://www.latticesemi.com/-/media/LatticeSemi/Documents/TechnicalBriefs/FPGA-TN-02026-3-2-iCE40-Technology-Library.ashx?document_id=52206 +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_ICE40_ICE40OPS_TD +#define CIRCT_DIALECT_ICE40_ICE40OPS_TD + +include "circt/Dialect/ICE40/ICE40Dialect.td" + +def I1Property : IntProperty<"bool">; + +def SBLut4Op : ICE40Op<"sb_lut4", []> { + let summary = "A basic lut"; + let description = [{ + The basic look up table. f(i0, i1, i2, i3) = lut_init[concat(i3,i2,i1,i0)]. + }]; + + let arguments = (ins I1:$i0, I1:$i1, I1:$i2, I1:$i3, ArrayProperty:$lut_init); + let results = (outs I1:$result); + + let hasVerifier = 1; + + let assemblyFormat = [{ + $i0 `,` $i1 `,` $i2 `,` $i3 `,` $lut_init attr-dict + }]; +} + +def SBCarryOp : ICE40Op<"sb_carry", []> { + let summary = "Dedicated carry Lookahead logic"; + let description = [{ + The basic carry lookahead logic. f(i0, i1, ci) = 1 iff popcount(concat(i0,i1,ci)) >= 2. + There are constraints on the use, as i0 and i1 have to be the i0 and i1 input of a single lut. + This op doesn't check this. There is a combined op that handles that. + }]; + + let arguments = (ins I1:$i0, I1:$i1, I1:$ci); + let results = (outs I1:$result); + + let hasVerifier = 1; + + let assemblyFormat = [{ + $i0 `,` $i1 `,` $ci attr-dict + }]; +} + +def SBLut4CarryOp : ICE40Op<"sb_lut4_carry", []> { + let summary = "LUT which also utilizes the carry logic"; + let description = [{ + carry_out(i0, i1, ci) = 1 iff popcount(concat(i0,i1,ci)) >= 2. + result(i0, i1, i2, i3) = lut_init[concat(i3,i2,i1,i0)]. + There are constraints on the use, as i0 and i1 have to be the i0 and i1 input of a single lut. + This op doesn't check this. There is a combined op that handles that. + }]; + + let arguments = (ins I1:$i0, I1:$i1, I1:$i2, I1:$i3, I1:$ci, ArrayProperty:$lut_init); + let results = (outs I1:$result, I1:$carry_out); + + let hasVerifier = 1; + + let assemblyFormat = [{ + $i0 `,` $i1 `,` $i2 `,` $i3 `,` $ci `,` $lut_init attr-dict + }]; +} + +#endif // CIRCT_DIALECT_ICE40_ICE40OPS_TD diff --git a/include/circt/InitAllDialects.h b/include/circt/InitAllDialects.h index 8e53c5fe211a..1825e1ac123e 100644 --- a/include/circt/InitAllDialects.h +++ b/include/circt/InitAllDialects.h @@ -28,6 +28,7 @@ #include "circt/Dialect/HW/HWDialect.h" #include "circt/Dialect/HWArith/HWArithDialect.h" #include "circt/Dialect/Handshake/HandshakeDialect.h" +#include "circt/Dialect/ICE40/ICE40Dialect.h" #include "circt/Dialect/Interop/InteropDialect.h" #include "circt/Dialect/Kanagawa/KanagawaDialect.h" #include "circt/Dialect/LLHD/IR/LLHDDialect.h" @@ -70,6 +71,7 @@ inline void registerAllDialects(mlir::DialectRegistry ®istry) { handshake::HandshakeDialect, hw::HWDialect, hwarith::HWArithDialect, + ice40::ICE40Dialect, interop::InteropDialect, kanagawa::KanagawaDialect, llhd::LLHDDialect, diff --git a/lib/Dialect/CMakeLists.txt b/lib/Dialect/CMakeLists.txt index a7bf7be67e1f..d086f601dd86 100644 --- a/lib/Dialect/CMakeLists.txt +++ b/lib/Dialect/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(Handshake) add_subdirectory(HW) add_subdirectory(HWArith) add_subdirectory(Kanagawa) +add_subdirectory(ICE40) add_subdirectory(Interop) add_subdirectory(LLHD) add_subdirectory(LoopSchedule) diff --git a/lib/Dialect/ICE40/CMakeLists.txt b/lib/Dialect/ICE40/CMakeLists.txt new file mode 100644 index 000000000000..b9f12eeacf57 --- /dev/null +++ b/lib/Dialect/ICE40/CMakeLists.txt @@ -0,0 +1,19 @@ +add_circt_dialect_library(CIRCTICE40 + ICE40Ops.cpp + ICE40Dialect.cpp + + ADDITIONAL_HEADER_DIRS + ${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/ICE40 + + DEPENDS + MLIRICE40IncGen + + LINK_COMPONENTS + Support + + LINK_LIBS PUBLIC + MLIRIR + MLIRInferTypeOpInterface + ) + +add_dependencies(circt-headers MLIRICE40IncGen) diff --git a/lib/Dialect/ICE40/ICE40Dialect.cpp b/lib/Dialect/ICE40/ICE40Dialect.cpp new file mode 100644 index 000000000000..152a91261844 --- /dev/null +++ b/lib/Dialect/ICE40/ICE40Dialect.cpp @@ -0,0 +1,33 @@ +//===- ICE40Dialect.cpp - Implement the ICE40 dialect ---------------------===// +// +// 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 implements the ICE40 dialect. +// +//===----------------------------------------------------------------------===// + +#include "circt/Dialect/ICE40/ICE40Dialect.h" +#include "circt/Dialect/ICE40/ICE40Ops.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/DialectImplementation.h" + +using namespace circt; +using namespace ice40; + +//===----------------------------------------------------------------------===// +// Dialect specification. +//===----------------------------------------------------------------------===// + +void ICE40Dialect::initialize() { + // Register operations. + addOperations< +#define GET_OP_LIST +#include "circt/Dialect/ICE40/ICE40.cpp.inc" + >(); +} + +#include "circt/Dialect/ICE40/ICE40Dialect.cpp.inc" diff --git a/lib/Dialect/ICE40/ICE40Ops.cpp b/lib/Dialect/ICE40/ICE40Ops.cpp new file mode 100644 index 000000000000..227e37e89d1d --- /dev/null +++ b/lib/Dialect/ICE40/ICE40Ops.cpp @@ -0,0 +1,44 @@ +//===- ICE40Ops.cpp - Implement the ICE40 operations ----------------------===// +// +// 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 implements ICE40 ops. +// +//===----------------------------------------------------------------------===// + +#include "circt/Dialect/ICE40/ICE40Ops.h" +#include "mlir/IR/DialectImplementation.h" +#include "mlir/IR/ImplicitLocOpBuilder.h" + +using namespace circt; +using namespace ice40; + +//===----------------------------------------------------------------------===// +// SBLut4Op +//===----------------------------------------------------------------------===// + +LogicalResult SBLut4Op::verify() { return success(); } + +//===----------------------------------------------------------------------===// +// SBCarryOp +//===----------------------------------------------------------------------===// + +LogicalResult SBCarryOp::verify() { return success(); } + +//===----------------------------------------------------------------------===// +// SBLut4CarryOp +//===----------------------------------------------------------------------===// + +LogicalResult SBLut4CarryOp::verify() { return success(); } + +//===----------------------------------------------------------------------===// +// TableGen generated logic. +//===----------------------------------------------------------------------===// + +// Provide the autogenerated implementation guts for the Op classes. +#define GET_OP_CLASSES +#include "circt/Dialect/ICE40/ICE40.cpp.inc" diff --git a/test/Dialect/ICE40/basic.mlir b/test/Dialect/ICE40/basic.mlir new file mode 100644 index 000000000000..28e5a31b5273 --- /dev/null +++ b/test/Dialect/ICE40/basic.mlir @@ -0,0 +1,11 @@ +// RUN: circt-opt %s | FileCheck %s + +func.func @basic(%i : i1) { + // CHECK: ice40.sb_lut4 + %a = ice40.sb_lut4 %i, %i, %i, %i, [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] + // CHECK: ice40.sb_carry + %b = ice40.sb_carry %i, %i, %a + // CHECK: ice40.sb_lut4_carry + %c, %d = ice40.sb_lut4_carry %i, %i, %a, %a, %b, [1,0,1,1,0,1,1,1,0,1,1,1,1,0,1,1] + func.return +}