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

Add the ICE40 dialect. #8018

Draft
wants to merge 3 commits 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
17 changes: 17 additions & 0 deletions docs/Dialects/ICE40/RationaleICE40.md
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.
1 change: 1 addition & 0 deletions include/circt/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions include/circt/Dialect/ICE40/CMakeLists.txt
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)
20 changes: 20 additions & 0 deletions include/circt/Dialect/ICE40/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
23 changes: 23 additions & 0 deletions include/circt/Dialect/ICE40/ICE40Dialect.h
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
33 changes: 33 additions & 0 deletions include/circt/Dialect/ICE40/ICE40Dialect.td
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
23 changes: 23 additions & 0 deletions include/circt/Dialect/ICE40/ICE40Ops.h
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
74 changes: 74 additions & 0 deletions include/circt/Dialect/ICE40/ICE40Ops.td
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
2 changes: 2 additions & 0 deletions include/circt/InitAllDialects.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -70,6 +71,7 @@ inline void registerAllDialects(mlir::DialectRegistry &registry) {
handshake::HandshakeDialect,
hw::HWDialect,
hwarith::HWArithDialect,
ice40::ICE40Dialect,
interop::InteropDialect,
kanagawa::KanagawaDialect,
llhd::LLHDDialect,
Expand Down
1 change: 1 addition & 0 deletions lib/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions lib/Dialect/ICE40/CMakeLists.txt
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)
33 changes: 33 additions & 0 deletions lib/Dialect/ICE40/ICE40Dialect.cpp
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"
44 changes: 44 additions & 0 deletions lib/Dialect/ICE40/ICE40Ops.cpp
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(); }

//===----------------------------------------------------------------------===//
// 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"
11 changes: 11 additions & 0 deletions test/Dialect/ICE40/basic.mlir
Original file line number Diff line number Diff line change
@@ -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
}
Loading