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

[Moore] Add FVIntegerAttr #7461

Merged
merged 1 commit into from
Aug 8, 2024
Merged
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
6 changes: 2 additions & 4 deletions include/circt/Dialect/Moore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ mlir_tablegen(MooreEnums.cpp.inc -gen-enum-defs)
add_public_tablegen_target(CIRCTMooreEnumsIncGen)
add_dependencies(circt-headers CIRCTMooreEnumsIncGen)

mlir_tablegen(MooreAttributes.h.inc -gen-attrdef-decls
-attrdefs-dialect MooreDialect)
mlir_tablegen(MooreAttributes.cpp.inc -gen-attrdef-defs
-attrdefs-dialect MooreDialect)
mlir_tablegen(MooreAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect moore)
mlir_tablegen(MooreAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect moore)
add_public_tablegen_target(CIRCTMooreAttributesIncGen)
add_dependencies(circt-headers CIRCTMooreAttributesIncGen)

Expand Down
1 change: 1 addition & 0 deletions include/circt/Dialect/Moore/Moore.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

include "circt/Dialect/Moore/MooreDialect.td"
include "circt/Dialect/Moore/MooreTypes.td"
include "circt/Dialect/Moore/MooreAttributes.td"
include "circt/Dialect/Moore/MooreOps.td"

#endif // CIRCT_DIALECT_MOORE_MOORE
25 changes: 25 additions & 0 deletions include/circt/Dialect/Moore/MooreAttributes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===- MooreAttributes.h - Declare Moore dialect attributes ------*- 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 attributes for the Moore dialect.
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_MOORE_MOOREATTRIBUTES_H
#define CIRCT_DIALECT_MOORE_MOOREATTRIBUTES_H

#include "circt/Support/FVInt.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"

// Include generated attributes.
#define GET_ATTRDEF_CLASSES
#include "circt/Dialect/Moore/MooreAttributes.h.inc"

#endif // CIRCT_DIALECT_MOORE_MOOREATTRIBUTES_H
22 changes: 22 additions & 0 deletions include/circt/Dialect/Moore/MooreAttributes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===- MooreAttributes.td - Moore attribute definitions ----*- 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
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_MOORE_MOOREATTRIBUTES
#define CIRCT_DIALECT_MOORE_MOOREATTRIBUTES

include "circt/Dialect/Moore/MooreDialect.td"
include "mlir/IR/AttrTypeBase.td"

def FVIntegerAttr : AttrDef<MooreDialect, "FVInteger"> {
let mnemonic = "fvint";
let summary = "An attribute containing a four-valued integer";
let parameters = (ins "FVInt":$value);
let hasCustomAssemblyFormat = 1;
}

#endif // CIRCT_DIALECT_MOORE_MOOREATTRIBUTES
3 changes: 3 additions & 0 deletions include/circt/Dialect/Moore/MooreDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ def MooreDialect : Dialect {
let extraClassDeclaration = [{
/// Register all Moore types.
void registerTypes();
/// Register all Moore attributes.
void registerAttributes();

/// Type parsing and printing.
Type parseType(DialectAsmParser &parser) const override;
void printType(Type, DialectAsmPrinter &) const override;
}];
let useDefaultAttributePrinterParser = 1;
let useDefaultTypePrinterParser = 0;
let dependentDialects = ["hw::HWDialect"];
}
Expand Down
27 changes: 27 additions & 0 deletions include/circt/Support/FVInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,33 @@ inline raw_ostream &operator<<(raw_ostream &os, const FVInt &value) {

llvm::hash_code hash_value(const FVInt &a);

/// Print a four-valued integer usign an `AsmPrinter`. This produces the
/// following output formats:
///
/// - Decimal notation if the integer has no unknown bits. The sign bit is used
/// to determine whether the value is printed as negative number or not.
/// - Hexadecimal notation with a leading `h` if the integer the bits in each
/// hex digit are either all known, all X, or all Z.
/// - Binary notation with a leading `b` in all other cases.
void printFVInt(AsmPrinter &p, const FVInt &value);

/// Parse a four-valued integer using an `AsmParser`. This accepts the following
/// formats:
///
/// - `42`/`-42`: positive or negative integer in decimal notation. The sign bit
/// of the result indicates whether the value was negative. Cannot contain
/// unknown X or Z digits.
/// - `h123456789ABCDEF0XZ`: signless integer in hexadecimal notation. Can
/// contain unknown X or Z digits.
/// - `b10XZ`: signless integer in binary notation. Can contain unknown X or Z
/// digits.
///
/// The result has enough bits to fully represent the parsed integer, and to
/// have the sign bit encode whether the integer was written as a negative
/// number in the input. The result's bit width may be larger than the minimum
/// number of bits required to represent its value.
ParseResult parseFVInt(AsmParser &p, FVInt &result);

} // namespace circt

#endif // CIRCT_SUPPORT_FVINT_H
1 change: 1 addition & 0 deletions lib/Dialect/Moore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_circt_dialect_library(CIRCTMoore
MooreAttributes.cpp
MooreDialect.cpp
MooreOps.cpp
MooreTypes.cpp
Expand Down
68 changes: 68 additions & 0 deletions lib/Dialect/Moore/MooreAttributes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===- MooreAttributes.cpp - Implement the Moore attributes ---------------===//
//
// 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 Moore dialect attributes.
//
//===----------------------------------------------------------------------===//

#include "circt/Dialect/Moore/MooreAttributes.h"
#include "circt/Dialect/Moore/MooreDialect.h"
#include "circt/Dialect/Moore/MooreTypes.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.h"

using namespace circt;
using namespace circt::moore;
using mlir::AsmParser;
using mlir::AsmPrinter;

//===----------------------------------------------------------------------===//
// FVIntegerAttr
//===----------------------------------------------------------------------===//

Attribute FVIntegerAttr::parse(AsmParser &p, Type) {
// Parse the value and width specifier.
FVInt value;
unsigned width;
llvm::SMLoc widthLoc;
if (p.parseLess() || parseFVInt(p, value) || p.parseColon() ||
p.getCurrentLocation(&widthLoc) || p.parseInteger(width) ||
p.parseGreater())
return {};

// Make sure the integer fits into the requested number of bits.
unsigned neededBits =
value.isNegative() ? value.getSignificantBits() : value.getActiveBits();
if (width < neededBits) {
p.emitError(widthLoc) << "integer literal requires at least " << neededBits
<< " bits, but attribute specifies only " << width;
return {};
}

return FVIntegerAttr::get(p.getContext(), value.sextOrTrunc(width));
}

void FVIntegerAttr::print(AsmPrinter &p) const {
p << "<";
printFVInt(p, getValue());
p << " : " << getValue().getBitWidth() << ">";
}

//===----------------------------------------------------------------------===//
// Generated logic
//===----------------------------------------------------------------------===//

#define GET_ATTRDEF_CLASSES
#include "circt/Dialect/Moore/MooreAttributes.cpp.inc"

void MooreDialect::registerAttributes() {
addAttributes<
#define GET_ATTRDEF_LIST
#include "circt/Dialect/Moore/MooreAttributes.cpp.inc"
>();
}
3 changes: 2 additions & 1 deletion lib/Dialect/Moore/MooreDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ using namespace circt::moore;
//===----------------------------------------------------------------------===//

void MooreDialect::initialize() {
// Register types.
// Register types and attributes.
registerTypes();
registerAttributes();

// Register operations.
addOperations<
Expand Down
50 changes: 50 additions & 0 deletions lib/Support/FVInt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "circt/Support/FVInt.h"
#include "mlir/IR/OpImplementation.h"
#include "llvm/ADT/StringExtras.h"

#define DEBUG_TYPE "fvint"
Expand Down Expand Up @@ -142,3 +143,52 @@ void FVInt::print(raw_ostream &os) const {
llvm::hash_code circt::hash_value(const FVInt &a) {
return llvm::hash_combine(a.getRawValue(), a.getRawUnknown());
}

void circt::printFVInt(AsmPrinter &p, const FVInt &value) {
SmallString<32> buffer;
if (value.isNegative() && (-value).tryToString(buffer)) {
p << "-" << buffer;
} else if (value.tryToString(buffer)) {
p << buffer;
} else if (value.tryToString(buffer, 16)) {
p << "h" << buffer;
} else {
value.tryToString(buffer, 2);
p << "b" << buffer;
}
}

ParseResult circt::parseFVInt(AsmParser &p, FVInt &result) {
// Parse the value as either a keyword (`b[01XZ]+` for binary or
// `h[0-9A-FXZ]+` for hexadecimal), or an integer value (for decimal).
FVInt value;
StringRef strValue;
auto valueLoc = p.getCurrentLocation();
if (succeeded(p.parseOptionalKeyword(&strValue))) {
// Determine the radix based on the `b` or `h` prefix.
unsigned base = 0;
if (strValue.consume_front("b")) {
base = 2;
} else if (strValue.consume_front("h")) {
base = 16;
} else {
return p.emitError(valueLoc) << "expected `b` or `h` prefix";
}

// Parse the value.
auto parsedValue = FVInt::tryFromString(strValue, base);
if (!parsedValue) {
return p.emitError(valueLoc)
<< "expected base-" << base << " four-valued integer";
}

// Add a zero bit at the top to ensure the value reads as positive.
result = parsedValue->zext(parsedValue->getBitWidth() + 1);
} else {
APInt intValue;
if (p.parseInteger(intValue))
return failure();
result = std::move(intValue);
}
return success();
}
4 changes: 4 additions & 0 deletions test/Dialect/Moore/attrs-error.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: circt-opt --verify-diagnostics --split-input-file %s

// expected-error @below {{integer literal requires at least 6 bits, but attribute specifies only 3}}
hw.constant false {foo = #moore.fvint<42 : 3>}
12 changes: 12 additions & 0 deletions test/Dialect/Moore/attrs.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s

// CHECK: #moore.fvint<42 : 32>
hw.constant false {foo = #moore.fvint<42 : 32>}
// CHECK: #moore.fvint<-42 : 32>
hw.constant false {foo = #moore.fvint<-42 : 32>}
// CHECK: #moore.fvint<1234567890123456789012345678901234567890 : 131>
hw.constant false {foo = #moore.fvint<1234567890123456789012345678901234567890 : 131>}
// CHECK: #moore.fvint<hABCDEFXZ0123456789 : 72>
hw.constant false {foo = #moore.fvint<hABCDEFXZ0123456789 : 72>}
// CHECK: #moore.fvint<b1010XZ01 : 8>
hw.constant false {foo = #moore.fvint<b1010XZ01 : 8>}
Loading