-
Notifications
You must be signed in to change notification settings - Fork 309
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
Add the ICE40 dialect. #8018
base: main
Are you sure you want to change the base?
Add the ICE40 dialect. #8018
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
add_circt_dialect(ICE40 ice40) | ||
|
||
set(LLVM_TARGET_DEFINITIONS ICE40.td) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string mnemonic, list<Trait> traits = []> : | ||
Op<ICE40Dialect, mnemonic, traits>; | ||
|
||
#endif // CIRCT_DIALECT_ICE40_ICE40DIALECT |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<I1Property>:$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<I1Property>:$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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really exciting! One nit - is it worth verifying that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed it should check. |
||
|
||
//===----------------------------------------------------------------------===// | ||
// SBCarryOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
LogicalResult SBCarryOp::verify() { return success(); } | ||
|
||
//===----------------------------------------------------------------------===// | ||
// SBLut4CarryOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
LogicalResult SBLut4CarryOp::verify() { return success(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment re checking here. |
||
|
||
//===----------------------------------------------------------------------===// | ||
// TableGen generated logic. | ||
//===----------------------------------------------------------------------===// | ||
|
||
// Provide the autogenerated implementation guts for the Op classes. | ||
#define GET_OP_CLASSES | ||
#include "circt/Dialect/ICE40/ICE40.cpp.inc" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// RUN: circt-opt %s | FileCheck %s | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you add the verifier, create an error test. |
||
|
||
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the combined op?