mirror of https://github.com/llvm/circt.git
[LLHD] Use hw.inout instead of llhd.sig (#7353)
This commit is contained in:
parent
2345382e67
commit
c012ab88a9
|
@ -1,34 +0,0 @@
|
||||||
//===- HWToLLHD.h - HW to LLHD pass entry point ---------------------------===//
|
|
||||||
//
|
|
||||||
// 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 header file defines prototypes that expose the HWToLLHD pass
|
|
||||||
// constructors.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef CIRCT_CONVERSION_HWTOLLHD_HWTOLLHD_H_
|
|
||||||
#define CIRCT_CONVERSION_HWTOLLHD_HWTOLLHD_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace mlir {
|
|
||||||
template <typename T>
|
|
||||||
class OperationPass;
|
|
||||||
class ModuleOp;
|
|
||||||
} // namespace mlir
|
|
||||||
|
|
||||||
namespace circt {
|
|
||||||
|
|
||||||
#define GEN_PASS_DECL_CONVERTHWTOLLHD
|
|
||||||
#include "circt/Conversion/Passes.h.inc"
|
|
||||||
|
|
||||||
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
|
|
||||||
createConvertHWToLLHDPass();
|
|
||||||
} // namespace circt
|
|
||||||
|
|
||||||
#endif // CIRCT_CONVERSION_HWTOLLHD_HWTOLLHD_H_
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "circt/Conversion/FSMToSV.h"
|
#include "circt/Conversion/FSMToSV.h"
|
||||||
#include "circt/Conversion/HWArithToHW.h"
|
#include "circt/Conversion/HWArithToHW.h"
|
||||||
#include "circt/Conversion/HWToBTOR2.h"
|
#include "circt/Conversion/HWToBTOR2.h"
|
||||||
#include "circt/Conversion/HWToLLHD.h"
|
|
||||||
#include "circt/Conversion/HWToLLVM.h"
|
#include "circt/Conversion/HWToLLVM.h"
|
||||||
#include "circt/Conversion/HWToSMT.h"
|
#include "circt/Conversion/HWToSMT.h"
|
||||||
#include "circt/Conversion/HWToSV.h"
|
#include "circt/Conversion/HWToSV.h"
|
||||||
|
|
|
@ -545,20 +545,6 @@ def HWArithToHW : Pass<"lower-hwarith-to-hw", "mlir::ModuleOp"> {
|
||||||
let dependentDialects = ["hw::HWDialect", "comb::CombDialect", "sv::SVDialect"];
|
let dependentDialects = ["hw::HWDialect", "comb::CombDialect", "sv::SVDialect"];
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// HWToLLHD
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
def ConvertHWToLLHD : Pass<"convert-hw-to-llhd", "mlir::ModuleOp"> {
|
|
||||||
let summary = "Convert HW to LLHD";
|
|
||||||
let description = [{
|
|
||||||
This pass translates a HW design into an equivalent structural LLHD
|
|
||||||
description.
|
|
||||||
}];
|
|
||||||
let constructor = "circt::createConvertHWToLLHDPass()";
|
|
||||||
let dependentDialects = ["llhd::LLHDDialect"];
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// HWToSystemC
|
// HWToSystemC
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -41,6 +41,10 @@ def InOutType : DialectType<HWDialect,
|
||||||
CPred<"::circt::hw::type_isa<circt::hw::InOutType>($_self)">,
|
CPred<"::circt::hw::type_isa<circt::hw::InOutType>($_self)">,
|
||||||
"InOutType", "InOutType">;
|
"InOutType", "InOutType">;
|
||||||
|
|
||||||
|
class InOutTypeOf<list<Type> allowedTypes>
|
||||||
|
: ContainerType<AnyTypeOf<allowedTypes>, CPred<"::circt::hw::type_isa<::circt::hw::InOutType>($_self)">,
|
||||||
|
"::circt::hw::type_cast<::circt::hw::InOutType>($_self).getElementType()", "InOutType">;
|
||||||
|
|
||||||
// A handle to refer to circt::hw::ArrayType in ODS.
|
// A handle to refer to circt::hw::ArrayType in ODS.
|
||||||
def ArrayType : DialectType<HWDialect,
|
def ArrayType : DialectType<HWDialect,
|
||||||
CPred<"::circt::hw::type_isa<circt::hw::ArrayType>($_self)">,
|
CPred<"::circt::hw::type_isa<circt::hw::ArrayType>($_self)">,
|
||||||
|
|
|
@ -25,7 +25,7 @@ class SigPtrIndexBitWidthConstraint<string index, string input>
|
||||||
class SigArrayElementTypeConstraint<string result, string input>
|
class SigArrayElementTypeConstraint<string result, string input>
|
||||||
: TypesMatchWith<"result must be a signal of the array element type",
|
: TypesMatchWith<"result must be a signal of the array element type",
|
||||||
input, result,
|
input, result,
|
||||||
"llhd::SigType::get(llhd::getLLHDElementType($_self))">;
|
"hw::InOutType::get(llhd::getLLHDElementType($_self))">;
|
||||||
|
|
||||||
class PtrArrayElementTypeConstraint<string result, string input>
|
class PtrArrayElementTypeConstraint<string result, string input>
|
||||||
: TypesMatchWith<"result must be a pointer of the array element type",
|
: TypesMatchWith<"result must be a pointer of the array element type",
|
||||||
|
@ -59,9 +59,9 @@ def LLHD_SigExtractOp : LLHD_Op<"sig.extract",
|
||||||
operand. The result length is defined by the result type.
|
operand. The result length is defined by the result type.
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_SigType<[HWIntegerType]>:$input,
|
let arguments = (ins InOutTypeOf<[HWIntegerType]>:$input,
|
||||||
HWIntegerType:$lowBit);
|
HWIntegerType:$lowBit);
|
||||||
let results = (outs LLHD_SigType<[HWIntegerType]>: $result);
|
let results = (outs InOutTypeOf<[HWIntegerType]>: $result);
|
||||||
|
|
||||||
let assemblyFormat = [{
|
let assemblyFormat = [{
|
||||||
$input `from` $lowBit attr-dict `:` functional-type($input, $result)
|
$input `from` $lowBit attr-dict `:` functional-type($input, $result)
|
||||||
|
@ -128,13 +128,13 @@ def LLHD_SigArraySliceOp : LLHD_Op<"sig.array_slice",
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
%3 = llhd.sig.array_slice %input at %lowIndex :
|
%3 = llhd.sig.array_slice %input at %lowIndex :
|
||||||
(!llhd.sig<!hw.array<4xi8>>) -> !llhd.sig<!hw.array<2xi8>>
|
(!hw.inout<array<4xi8>>) -> !hw.inout<array<2xi8>>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_SigType<[ArrayType]>: $input,
|
let arguments = (ins InOutTypeOf<[ArrayType]>: $input,
|
||||||
HWIntegerType: $lowIndex);
|
HWIntegerType: $lowIndex);
|
||||||
let results = (outs LLHD_SigType<[ArrayType]>: $result);
|
let results = (outs InOutTypeOf<[ArrayType]>: $result);
|
||||||
|
|
||||||
let assemblyFormat = [{
|
let assemblyFormat = [{
|
||||||
$input `at` $lowIndex attr-dict `:` functional-type($input, $result)
|
$input `at` $lowIndex attr-dict `:` functional-type($input, $result)
|
||||||
|
@ -144,12 +144,12 @@ def LLHD_SigArraySliceOp : LLHD_Op<"sig.array_slice",
|
||||||
unsigned getResultWidth() { return getLLHDTypeWidth(getResult().getType()); }
|
unsigned getResultWidth() { return getLLHDTypeWidth(getResult().getType()); }
|
||||||
unsigned getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
|
unsigned getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
|
||||||
hw::ArrayType getInputArrayType() {
|
hw::ArrayType getInputArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
hw::ArrayType getResultArrayType() {
|
hw::ArrayType getResultArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
|
||||||
getResult().getType()).getUnderlyingType());
|
getResult().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
let hasFolder = true;
|
let hasFolder = true;
|
||||||
|
@ -196,11 +196,11 @@ def LLHD_PtrArraySliceOp : LLHD_Op<"ptr.array_slice",
|
||||||
unsigned getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
|
unsigned getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
|
||||||
hw::ArrayType getInputArrayType() {
|
hw::ArrayType getInputArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
hw::ArrayType getResultArrayType() {
|
hw::ArrayType getResultArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
||||||
getResult().getType()).getUnderlyingType());
|
getResult().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
let hasFolder = true;
|
let hasFolder = true;
|
||||||
|
@ -221,20 +221,20 @@ def LLHD_SigArrayGetOp : LLHD_Op<"sig.array_get",
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
// Returns a !llhd.sig<i8>
|
// Returns a !hw.inout<i8>
|
||||||
%0 = llhd.sig.array_get %arr[%index] : !llhd.sig<!hw.array<4xi8>>
|
%0 = llhd.sig.array_get %arr[%index] : !hw.inout<array<4xi8>>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_SigType<[ArrayType]>:$input, HWIntegerType:$index);
|
let arguments = (ins InOutTypeOf<[ArrayType]>:$input, HWIntegerType:$index);
|
||||||
let results = (outs LLHD_SigType<[HWNonInOutType]>: $result);
|
let results = (outs InOutTypeOf<[HWNonInOutType]>: $result);
|
||||||
|
|
||||||
let assemblyFormat = "$input `[` $index `]` attr-dict `:` qualified(type($input))";
|
let assemblyFormat = "$input `[` $index `]` attr-dict `:` qualified(type($input))";
|
||||||
|
|
||||||
let extraClassDeclaration = [{
|
let extraClassDeclaration = [{
|
||||||
hw::ArrayType getArrayType() {
|
hw::ArrayType getArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ def LLHD_PtrArrayGetOp : LLHD_Op<"ptr.array_get",
|
||||||
let extraClassDeclaration = [{
|
let extraClassDeclaration = [{
|
||||||
hw::ArrayType getArrayType() {
|
hw::ArrayType getArrayType() {
|
||||||
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -286,21 +286,21 @@ def LLHD_SigStructExtractOp : LLHD_Op<"sig.struct_extract", [Pure,
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
// Returns a !llhd.sig<i8>
|
// Returns a !hw.inout<i8>
|
||||||
%0 = llhd.sig.struct_extract %struct["foo"]
|
%0 = llhd.sig.struct_extract %struct["foo"]
|
||||||
: !llhd.sig<!hw.struct<foo: i8, bar: i16>>
|
: !hw.inout<struct<foo: i8, bar: i16>>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_SigType<[StructType]>:$input, StrAttr:$field);
|
let arguments = (ins InOutTypeOf<[StructType]>:$input, StrAttr:$field);
|
||||||
let results = (outs LLHD_SigType<[HWNonInOutType]>:$result);
|
let results = (outs InOutTypeOf<[HWNonInOutType]>:$result);
|
||||||
|
|
||||||
let assemblyFormat = "$input `[` $field `]` attr-dict `:` qualified(type($input))";
|
let assemblyFormat = "$input `[` $field `]` attr-dict `:` qualified(type($input))";
|
||||||
|
|
||||||
let extraClassDeclaration = [{
|
let extraClassDeclaration = [{
|
||||||
hw::StructType getStructType() {
|
hw::StructType getStructType() {
|
||||||
return llvm::cast<hw::StructType>(llvm::cast<llhd::SigType>(
|
return llvm::cast<hw::StructType>(llvm::cast<hw::InOutType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ def LLHD_PtrStructExtractOp : LLHD_Op<"ptr.struct_extract", [Pure,
|
||||||
let extraClassDeclaration = [{
|
let extraClassDeclaration = [{
|
||||||
hw::StructType getStructType() {
|
hw::StructType getStructType() {
|
||||||
return llvm::cast<hw::StructType>(llvm::cast<llhd::PtrType>(
|
return llvm::cast<hw::StructType>(llvm::cast<llhd::PtrType>(
|
||||||
getInput().getType()).getUnderlyingType());
|
getInput().getType()).getElementType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#ifndef CIRCT_DIALECT_LLHD_IR_LLHD
|
#ifndef CIRCT_DIALECT_LLHD_IR_LLHD
|
||||||
#define CIRCT_DIALECT_LLHD_IR_LLHD
|
#define CIRCT_DIALECT_LLHD_IR_LLHD
|
||||||
|
|
||||||
|
include "circt/Dialect/HW/HWTypes.td"
|
||||||
include "mlir/IR/AttrTypeBase.td"
|
include "mlir/IR/AttrTypeBase.td"
|
||||||
include "mlir/IR/OpBase.td"
|
include "mlir/IR/OpBase.td"
|
||||||
include "mlir/IR/PatternBase.td"
|
include "mlir/IR/PatternBase.td"
|
||||||
|
@ -30,6 +31,7 @@ include "mlir/IR/SymbolInterfaces.td"
|
||||||
def LLHD_Dialect : Dialect {
|
def LLHD_Dialect : Dialect {
|
||||||
let name = "llhd";
|
let name = "llhd";
|
||||||
let cppNamespace = "::circt::llhd";
|
let cppNamespace = "::circt::llhd";
|
||||||
|
let dependentDialects = ["circt::hw::HWDialect"];
|
||||||
|
|
||||||
let description = [{
|
let description = [{
|
||||||
A low-level hardware description dialect in MLIR.
|
A low-level hardware description dialect in MLIR.
|
||||||
|
@ -68,28 +70,17 @@ def LLHD_TimeType : DialectType<LLHD_Dialect,
|
||||||
BuildableType<"TimeType::get($_builder.getContext())">;
|
BuildableType<"TimeType::get($_builder.getContext())">;
|
||||||
|
|
||||||
// Legal underlying types for signals and pointers.
|
// Legal underlying types for signals and pointers.
|
||||||
def LLHD_AnyUnderlyingType :
|
def LLHD_AnyElementType :
|
||||||
AnyTypeOf<[HWIntegerType, ArrayType, StructType]>;
|
AnyTypeOf<[HWIntegerType, ArrayType, StructType]>;
|
||||||
|
|
||||||
// LLHD sig type
|
|
||||||
class LLHD_SigType<list<Type> allowedTypes>
|
|
||||||
: ContainerType<AnyTypeOf<allowedTypes>, CPred<"llvm::isa<SigType>($_self)">,
|
|
||||||
"llvm::cast<SigType>($_self).getUnderlyingType()", "LLHD sig type">;
|
|
||||||
|
|
||||||
def LLHD_AnySigType : LLHD_SigType<[LLHD_AnyUnderlyingType]>;
|
|
||||||
|
|
||||||
// LLHD ptr type
|
// LLHD ptr type
|
||||||
class LLHD_PtrType<list<Type> allowedTypes>
|
class LLHD_PtrType<list<Type> allowedTypes>
|
||||||
: ContainerType<AnyTypeOf<allowedTypes>, CPred<"llvm::isa<PtrType>($_self)">,
|
: ContainerType<AnyTypeOf<allowedTypes>, CPred<"llvm::isa<PtrType>($_self)">,
|
||||||
"llvm::cast<PtrType>($_self).getUnderlyingType()", "LLHD pointer type">;
|
"llvm::cast<PtrType>($_self).getElementType()", "LLHD pointer type">;
|
||||||
|
|
||||||
def LLHD_AnyPtrType : LLHD_PtrType<[LLHD_AnyUnderlyingType]>;
|
def LLHD_AnyPtrType : LLHD_PtrType<[LLHD_AnyElementType]>;
|
||||||
|
|
||||||
// LLHD sig or ptr type
|
def LLHD_AnySigOrPtrType : AnyTypeOf<[LLHD_AnyPtrType, InOutType]>;
|
||||||
class LLHD_SigOrPtrType<list<Type> allowedTypes>
|
|
||||||
: AnyTypeOf<[LLHD_SigType<allowedTypes>, LLHD_PtrType<allowedTypes>]>;
|
|
||||||
|
|
||||||
def LLHD_AnySigOrPtrType : LLHD_SigOrPtrType<[LLHD_AnyUnderlyingType]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// LLHD op definition
|
// LLHD op definition
|
||||||
|
|
|
@ -17,26 +17,6 @@ class LLHDType<string name> : TypeDef<LLHD_Dialect, name> { }
|
||||||
// Type declarations
|
// Type declarations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Declares the llhd::SigType in C++.
|
|
||||||
def SigTypeImpl : LLHDType<"Sig"> {
|
|
||||||
let summary = "signal type";
|
|
||||||
let description = [{
|
|
||||||
Signals correspond directly to wires in a physical design, and are used to
|
|
||||||
model propagation delays and timing. Signals are used to carry values across
|
|
||||||
time steps in the LLHD execution model.
|
|
||||||
}];
|
|
||||||
|
|
||||||
let mnemonic = "sig";
|
|
||||||
let parameters = (ins "::mlir::Type":$underlyingType);
|
|
||||||
let assemblyFormat = "`<` $underlyingType `>`";
|
|
||||||
|
|
||||||
let builders = [
|
|
||||||
AttrBuilderWithInferredContext<(ins "::mlir::Type":$underlyingType), [{
|
|
||||||
return $_get(underlyingType.getContext(), underlyingType);
|
|
||||||
}]>
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declares the llhd::PtrType in C++.
|
// Declares the llhd::PtrType in C++.
|
||||||
def PtrTypeImpl : LLHDType<"Ptr"> {
|
def PtrTypeImpl : LLHDType<"Ptr"> {
|
||||||
let summary = "pointer type";
|
let summary = "pointer type";
|
||||||
|
@ -46,12 +26,12 @@ def PtrTypeImpl : LLHDType<"Ptr"> {
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let mnemonic = "ptr";
|
let mnemonic = "ptr";
|
||||||
let parameters = (ins "::mlir::Type":$underlyingType);
|
let parameters = (ins "::mlir::Type":$elementType);
|
||||||
let assemblyFormat = "`<` $underlyingType `>`";
|
let assemblyFormat = "`<` $elementType `>`";
|
||||||
|
|
||||||
let builders = [
|
let builders = [
|
||||||
AttrBuilderWithInferredContext<(ins "::mlir::Type":$underlyingType), [{
|
AttrBuilderWithInferredContext<(ins "::mlir::Type":$elementType), [{
|
||||||
return $_get(underlyingType.getContext(), underlyingType);
|
return $_get(elementType.getContext(), elementType);
|
||||||
}]>
|
}]>
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ def LLHD_VarOp : LLHD_Op<"var", [
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_AnyUnderlyingType: $init);
|
let arguments = (ins LLHD_AnyElementType: $init);
|
||||||
let results = (outs Res<LLHD_AnyPtrType, "the newly allocated reference",
|
let results = (outs Res<LLHD_AnyPtrType, "the newly allocated reference",
|
||||||
[MemAlloc]>: $result);
|
[MemAlloc]>: $result);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ def LLHD_VarOp : LLHD_Op<"var", [
|
||||||
def LLHD_LoadOp : LLHD_Op<"load", [
|
def LLHD_LoadOp : LLHD_Op<"load", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'result' and underlying type of 'pointer' have to match.",
|
"type of 'result' and underlying type of 'pointer' have to match.",
|
||||||
"pointer", "result", "llvm::cast<PtrType>($_self).getUnderlyingType()">
|
"pointer", "result", "llvm::cast<PtrType>($_self).getElementType()">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Load a value.";
|
let summary = "Load a value.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -64,7 +64,7 @@ def LLHD_LoadOp : LLHD_Op<"load", [
|
||||||
|
|
||||||
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to load from",
|
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to load from",
|
||||||
[MemRead]>: $pointer);
|
[MemRead]>: $pointer);
|
||||||
let results = (outs LLHD_AnyUnderlyingType: $result);
|
let results = (outs LLHD_AnyElementType: $result);
|
||||||
|
|
||||||
let assemblyFormat = "$pointer attr-dict `:` qualified(type($pointer))";
|
let assemblyFormat = "$pointer attr-dict `:` qualified(type($pointer))";
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ def LLHD_LoadOp : LLHD_Op<"load", [
|
||||||
def LLHD_StoreOp : LLHD_Op<"store", [
|
def LLHD_StoreOp : LLHD_Op<"store", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'value' and underlying type of 'pointer' have to match.",
|
"type of 'value' and underlying type of 'pointer' have to match.",
|
||||||
"pointer", "value", "llvm::cast<PtrType>($_self).getUnderlyingType()">
|
"pointer", "value", "llvm::cast<PtrType>($_self).getElementType()">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Store a value.";
|
let summary = "Store a value.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -94,7 +94,7 @@ def LLHD_StoreOp : LLHD_Op<"store", [
|
||||||
|
|
||||||
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to store to",
|
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to store to",
|
||||||
[MemWrite]>: $pointer,
|
[MemWrite]>: $pointer,
|
||||||
LLHD_AnyUnderlyingType: $value);
|
LLHD_AnyElementType: $value);
|
||||||
|
|
||||||
let assemblyFormat = "$pointer `,` $value attr-dict `:` qualified(type($pointer))";
|
let assemblyFormat = "$pointer `,` $value attr-dict `:` qualified(type($pointer))";
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ include "mlir/IR/EnumAttr.td"
|
||||||
def LLHD_SigOp : LLHD_Op<"sig", [
|
def LLHD_SigOp : LLHD_Op<"sig", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'init' and underlying type of 'signal' have to match.",
|
"type of 'init' and underlying type of 'signal' have to match.",
|
||||||
"init", "result", "SigType::get($_self)">
|
"init", "result", "hw::InOutType::get($_self)">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Create a signal.";
|
let summary = "Create a signal.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -45,8 +45,8 @@ def LLHD_SigOp : LLHD_Op<"sig", [
|
||||||
signal named "bar", carrying an `i1` type with initial value of 1.
|
signal named "bar", carrying an `i1` type with initial value of 1.
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins StrAttr: $name, LLHD_AnyUnderlyingType: $init);
|
let arguments = (ins StrAttr: $name, LLHD_AnyElementType: $init);
|
||||||
let results = (outs LLHD_AnySigType: $result);
|
let results = (outs InOutType: $result);
|
||||||
|
|
||||||
let assemblyFormat = "$name $init attr-dict `:` qualified(type($init))";
|
let assemblyFormat = "$name $init attr-dict `:` qualified(type($init))";
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ def LLHD_SigOp : LLHD_Op<"sig", [
|
||||||
def LLHD_PrbOp : LLHD_Op<"prb", [
|
def LLHD_PrbOp : LLHD_Op<"prb", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'result' and underlying type of 'signal' have to match.",
|
"type of 'result' and underlying type of 'signal' have to match.",
|
||||||
"signal", "result", "llvm::cast<SigType>($_self).getUnderlyingType()">
|
"signal", "result", "llvm::cast<hw::InOutType>($_self).getElementType()">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Probe a signal.";
|
let summary = "Probe a signal.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -65,7 +65,7 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
|
||||||
Syntax:
|
Syntax:
|
||||||
|
|
||||||
```
|
```
|
||||||
prb-op ::= ssa-id `=` `llhd.prb` ssa-sig attr-dict `:` !llhd.sig<type>
|
prb-op ::= ssa-id `=` `llhd.prb` ssa-sig attr-dict `:` !hw.inout<type>
|
||||||
```
|
```
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -73,13 +73,13 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
|
||||||
```mlir
|
```mlir
|
||||||
%const_i1 = llhd.const 1 : i1
|
%const_i1 = llhd.const 1 : i1
|
||||||
%sig_i1 = llhd.sig %const_i1 : i1
|
%sig_i1 = llhd.sig %const_i1 : i1
|
||||||
%prbd = llhd.prb %sig_i1 : !llhd.sig<i1>
|
%prbd = llhd.prb %sig_i1 : !hw.inout<i1>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins Arg<LLHD_AnySigType, "the signal to probe from",
|
let arguments = (ins Arg<InOutType, "the signal to probe from",
|
||||||
[MemRead]>: $signal);
|
[MemRead]>: $signal);
|
||||||
let results = (outs LLHD_AnyUnderlyingType: $result);
|
let results = (outs LLHD_AnyElementType: $result);
|
||||||
|
|
||||||
let assemblyFormat = "$signal attr-dict `:` qualified(type($signal))";
|
let assemblyFormat = "$signal attr-dict `:` qualified(type($signal))";
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
|
||||||
def LLHD_OutputOp : LLHD_Op<"output", [
|
def LLHD_OutputOp : LLHD_Op<"output", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'value' and underlying type of 'result' have to match.",
|
"type of 'value' and underlying type of 'result' have to match.",
|
||||||
"value", "result", "SigType::get($_self)">
|
"value", "result", "hw::InOutType::get($_self)">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Introduce a new signal and drive a value onto it.";
|
let summary = "Introduce a new signal and drive a value onto it.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -109,15 +109,15 @@ def LLHD_OutputOp : LLHD_Op<"output", [
|
||||||
%value = llhd.const 1 : i1
|
%value = llhd.const 1 : i1
|
||||||
%time = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
|
%time = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
|
||||||
%sig = llhd.sig "sigName" %value : i1
|
%sig = llhd.sig "sigName" %value : i1
|
||||||
llhd.drv %sig, %value after %time : !llhd.sig<i1>
|
llhd.drv %sig, %value after %time : !hw.inout<i1>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins OptionalAttr<StrAttr>: $name,
|
let arguments = (ins OptionalAttr<StrAttr>: $name,
|
||||||
LLHD_AnyUnderlyingType: $value,
|
LLHD_AnyElementType: $value,
|
||||||
LLHD_TimeType: $time);
|
LLHD_TimeType: $time);
|
||||||
|
|
||||||
let results = (outs LLHD_AnySigType: $result);
|
let results = (outs InOutType: $result);
|
||||||
|
|
||||||
let assemblyFormat = [{
|
let assemblyFormat = [{
|
||||||
( $name^ )? $value `after` $time attr-dict `:` qualified(type($value))
|
( $name^ )? $value `after` $time attr-dict `:` qualified(type($value))
|
||||||
|
@ -127,7 +127,7 @@ def LLHD_OutputOp : LLHD_Op<"output", [
|
||||||
def LLHD_DrvOp : LLHD_Op<"drv", [
|
def LLHD_DrvOp : LLHD_Op<"drv", [
|
||||||
TypesMatchWith<
|
TypesMatchWith<
|
||||||
"type of 'value' and underlying type of 'signal' have to match.",
|
"type of 'value' and underlying type of 'signal' have to match.",
|
||||||
"signal", "value", "llvm::cast<SigType>($_self).getUnderlyingType()">
|
"signal", "value", "llvm::cast<hw::InOutType>($_self).getElementType()">
|
||||||
]> {
|
]> {
|
||||||
let summary = "Drive a value into a signal.";
|
let summary = "Drive a value into a signal.";
|
||||||
let description = [{
|
let description = [{
|
||||||
|
@ -142,7 +142,7 @@ def LLHD_DrvOp : LLHD_Op<"drv", [
|
||||||
|
|
||||||
```
|
```
|
||||||
drv-op ::= `llhd.drv` ssa-signal `,` ssa-const `after` ssa-time
|
drv-op ::= `llhd.drv` ssa-signal `,` ssa-const `after` ssa-time
|
||||||
(`if` ssa-enable)? `:` !llhd.sig<const-type>
|
(`if` ssa-enable)? `:` !hw.inout<const-type>
|
||||||
```
|
```
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -154,14 +154,14 @@ def LLHD_DrvOp : LLHD_Op<"drv", [
|
||||||
%sig = llhd.sig %init : i1
|
%sig = llhd.sig %init : i1
|
||||||
%new = llhd.not %init : i1
|
%new = llhd.not %init : i1
|
||||||
|
|
||||||
llhd.drv %sig, %new after %time : !llhd.sig<i1>
|
llhd.drv %sig, %new after %time : !hw.inout<i1>
|
||||||
llhd.drv %sig, %new after %time if %en : !llhd.sig<i1>
|
llhd.drv %sig, %new after %time if %en : !hw.inout<i1>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins Arg<LLHD_AnySigType, "the signal to drive to",
|
let arguments = (ins Arg<InOutType, "the signal to drive to",
|
||||||
[MemWrite]>: $signal,
|
[MemWrite]>: $signal,
|
||||||
LLHD_AnyUnderlyingType: $value,
|
LLHD_AnyElementType: $value,
|
||||||
LLHD_TimeType: $time,
|
LLHD_TimeType: $time,
|
||||||
Optional<I1>: $enable);
|
Optional<I1>: $enable);
|
||||||
|
|
||||||
|
@ -230,30 +230,30 @@ def LLHD_RegOp : LLHD_Op<"reg", [
|
||||||
A rising, falling, and dual-edge triggered flip-flop:
|
A rising, falling, and dual-edge triggered flip-flop:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.reg %Q, (%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
llhd.reg %Q, (%D, "rise" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
llhd.reg %Q, (%D, "fall" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
llhd.reg %Q, (%D, "fall" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
llhd.reg %Q, (%D, "both" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
llhd.reg %Q, (%D, "both" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
```
|
```
|
||||||
|
|
||||||
A rising-edge triggered flip-flop with active-low reset:
|
A rising-edge triggered flip-flop with active-low reset:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
|
llhd.reg %Q, (%init, "low" %RSTB after %T : !hw.inout<i8>),
|
||||||
(%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
(%D, "rise" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
```
|
```
|
||||||
|
|
||||||
A rising-edge triggered enable flip-flop with active-low reset:
|
A rising-edge triggered enable flip-flop with active-low reset:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
|
llhd.reg %Q, (%init, "low" %RSTB after %T : !hw.inout<i8>),
|
||||||
(%D, "rise" %CLK after %T if %EN : !llhd.sig<i8>) : !llhd.sig<i8>
|
(%D, "rise" %CLK after %T if %EN : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
```
|
```
|
||||||
|
|
||||||
A transparent-low and transparent-high latch:
|
A transparent-low and transparent-high latch:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.reg %Q, (%D, "low" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
llhd.reg %Q, (%D, "low" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
llhd.reg %Q, (%D, "high" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
|
llhd.reg %Q, (%D, "high" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
|
||||||
```
|
```
|
||||||
|
|
||||||
An SR latch:
|
An SR latch:
|
||||||
|
@ -261,15 +261,15 @@ def LLHD_RegOp : LLHD_Op<"reg", [
|
||||||
```mlir
|
```mlir
|
||||||
%0 = llhd.const 0 : i1
|
%0 = llhd.const 0 : i1
|
||||||
%1 = llhd.const 1 : i1
|
%1 = llhd.const 1 : i1
|
||||||
llhd.reg %Q, (%0, "high" %R after %T : !llhd.sig<i1>),
|
llhd.reg %Q, (%0, "high" %R after %T : !hw.inout<i1>),
|
||||||
(%1, "high" %S after %T : !llhd.sig<i1>) : !llhd.sig<i1>
|
(%1, "high" %S after %T : !hw.inout<i1>) : !hw.inout<i1>
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins
|
let arguments = (ins
|
||||||
LLHD_AnySigType: $signal,
|
InOutType: $signal,
|
||||||
LLHD_RegModeArrayAttr: $modes,
|
LLHD_RegModeArrayAttr: $modes,
|
||||||
Variadic<AnyTypeOf<[LLHD_AnyUnderlyingType, LLHD_AnySigType]>>: $values,
|
Variadic<AnyTypeOf<[LLHD_AnyElementType, InOutType]>>: $values,
|
||||||
Variadic<I1>: $triggers,
|
Variadic<I1>: $triggers,
|
||||||
Variadic<LLHD_TimeType>: $delays,
|
Variadic<LLHD_TimeType>: $delays,
|
||||||
Variadic<I1>: $gates,
|
Variadic<I1>: $gates,
|
||||||
|
|
|
@ -40,11 +40,11 @@ def LLHD_EntityOp : LLHD_Op<"entity", [
|
||||||
```mlir
|
```mlir
|
||||||
llhd.entity @Foo () -> () {
|
llhd.entity @Foo () -> () {
|
||||||
%0 = llhd.const 0 : i1
|
%0 = llhd.const 0 : i1
|
||||||
%toggle = llhd.sig %0 : i1 -> !llhd.sig<i1>
|
%toggle = llhd.sig %0 : i1 -> !hw.inout<i1>
|
||||||
%1 = llhd.prb %toggle : !llhd.sig<i1> -> i1
|
%1 = llhd.prb %toggle : !hw.inout<i1> -> i1
|
||||||
%2 = llhd.not %1 : i1
|
%2 = llhd.not %1 : i1
|
||||||
%dt = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
|
%dt = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
|
||||||
llhd.drv %toggle, %2, %dt : !llhd.sig<i1>, i1, !llhd.time
|
llhd.drv %toggle, %2, %dt : !hw.inout<i1>, i1, !llhd.time
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
@ -110,8 +110,8 @@ def LLHD_ProcOp : LLHD_Op<"proc", [
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.proc @example(%in0 : !llhd.sig<i64>, %in1 : !llhd.sig<i1>) ->
|
llhd.proc @example(%in0 : !hw.inout<i64>, %in1 : !hw.inout<i1>) ->
|
||||||
(%out2 : !llhd.sig<i1>) {
|
(%out2 : !hw.inout<i1>) {
|
||||||
br ^bb1
|
br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
llhd.halt
|
llhd.halt
|
||||||
|
@ -166,16 +166,16 @@ def LLHD_InstOp : LLHD_Op<"inst", [
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.inst "foo" @empty() -> () : () -> ()
|
llhd.inst "foo" @empty() -> () : () -> ()
|
||||||
llhd.inst "bar" @proc_symbol() -> (%out0) : () -> !llhd.sig<i32>
|
llhd.inst "bar" @proc_symbol() -> (%out0) : () -> !hw.inout<i32>
|
||||||
llhd.inst "baz" @entity_symbol(%in0, %in1) -> (%out0, %out1) :
|
llhd.inst "baz" @entity_symbol(%in0, %in1) -> (%out0, %out1) :
|
||||||
(!llhd.sig<i32>, !llhd.sig<i16>) -> (!llhd.sig<i8>, !llhd.sig<i4>)
|
(!hw.inout<i32>, !hw.inout<i16>) -> (!hw.inout<i8>, !hw.inout<i4>)
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins StrAttr:$name,
|
let arguments = (ins StrAttr:$name,
|
||||||
FlatSymbolRefAttr:$callee,
|
FlatSymbolRefAttr:$callee,
|
||||||
Variadic<LLHD_AnySigType>:$inputs,
|
Variadic<InOutType>:$inputs,
|
||||||
Variadic<LLHD_AnySigType>:$outputs);
|
Variadic<InOutType>:$outputs);
|
||||||
|
|
||||||
let assemblyFormat = [{
|
let assemblyFormat = [{
|
||||||
$name $callee `(` $inputs `)` `->` `(` $outputs `)` attr-dict `:`
|
$name $callee `(` $inputs `)` `->` `(` $outputs `)` attr-dict `:`
|
||||||
|
@ -221,8 +221,8 @@ def LLHD_ConnectOp : LLHD_Op<"con", [
|
||||||
one signal. All driven values on one signal will be reflected on the other.
|
one signal. All driven values on one signal will be reflected on the other.
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins LLHD_AnySigType:$lhs,
|
let arguments = (ins InOutType:$lhs,
|
||||||
LLHD_AnySigType:$rhs);
|
InOutType:$rhs);
|
||||||
|
|
||||||
let assemblyFormat = [{
|
let assemblyFormat = [{
|
||||||
operands attr-dict `:` qualified(type($lhs))
|
operands attr-dict `:` qualified(type($lhs))
|
||||||
|
@ -254,13 +254,13 @@ def LLHD_WaitOp : LLHD_Op<"wait", [
|
||||||
```mlir
|
```mlir
|
||||||
llhd.wait ^bb1
|
llhd.wait ^bb1
|
||||||
llhd.wait for %time, ^bb1(%time : !llhd.time)
|
llhd.wait for %time, ^bb1(%time : !llhd.time)
|
||||||
llhd.wait (%0, %1 : !llhd.sig<i64>, !llhd.sig<i1>), ^bb1(%1 : !llhd.sig<i1>)
|
llhd.wait (%0, %1 : !hw.inout<i64>, !hw.inout<i1>), ^bb1(%1 : !hw.inout<i1>)
|
||||||
llhd.wait for %time, (%0, %1 : !llhd.sig<i64>, !llhd.sig<i1>),
|
llhd.wait for %time, (%0, %1 : !hw.inout<i64>, !hw.inout<i1>),
|
||||||
^bb1(%1, %0 : !llhd.sig<i1>, !llhd.sig<i64>)
|
^bb1(%1, %0 : !hw.inout<i1>, !hw.inout<i64>)
|
||||||
```
|
```
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins Variadic<LLHD_AnySigType>:$obs,
|
let arguments = (ins Variadic<InOutType>:$obs,
|
||||||
Optional<LLHD_TimeType>:$time,
|
Optional<LLHD_TimeType>:$time,
|
||||||
Variadic<AnyType>:$destOps);
|
Variadic<AnyType>:$destOps);
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ def MemoryToBlockArgument : Pass<"llhd-memory-to-block-argument",
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.proc @check_simple(%condsig : !llhd.sig<i1>) -> () {
|
llhd.proc @check_simple(%condsig : !hw.inout<i1>) -> () {
|
||||||
%c5 = llhd.const 5 : i32
|
%c5 = llhd.const 5 : i32
|
||||||
%cond = llhd.prb %condsig : !llhd.sig<i1>
|
%cond = llhd.prb %condsig : !hw.inout<i1>
|
||||||
%ptr = llhd.var %c5 : i32
|
%ptr = llhd.var %c5 : i32
|
||||||
cond_br %cond, ^bb1, ^bb2
|
cond_br %cond, ^bb1, ^bb2
|
||||||
^bb1:
|
^bb1:
|
||||||
|
@ -57,9 +57,9 @@ def MemoryToBlockArgument : Pass<"llhd-memory-to-block-argument",
|
||||||
is transformed to
|
is transformed to
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
llhd.proc @check_simple(%condsig : !llhd.sig<i1>) -> () {
|
llhd.proc @check_simple(%condsig : !hw.inout<i1>) -> () {
|
||||||
%c5 = llhd.const 5 : i32
|
%c5 = llhd.const 5 : i32
|
||||||
%cond = llhd.prb %condsig : !llhd.sig<i1>
|
%cond = llhd.prb %condsig : !hw.inout<i1>
|
||||||
cond_br %cond, ^bb1, ^bb2(%c5 : i32)
|
cond_br %cond, ^bb1, ^bb2(%c5 : i32)
|
||||||
^bb1:
|
^bb1:
|
||||||
%c6 = llhd.const 6 : i32
|
%c6 = llhd.const 6 : i32
|
||||||
|
|
|
@ -19,7 +19,6 @@ add_circt_public_c_api_library(CIRCTCAPIConversion
|
||||||
CIRCTHandshakeToDC
|
CIRCTHandshakeToDC
|
||||||
CIRCTHandshakeToHW
|
CIRCTHandshakeToHW
|
||||||
CIRCTHWArithToHW
|
CIRCTHWArithToHW
|
||||||
CIRCTHWToLLHD
|
|
||||||
CIRCTHWToLLVM
|
CIRCTHWToLLVM
|
||||||
CIRCTHWToBTOR2
|
CIRCTHWToBTOR2
|
||||||
CIRCTHWToSMT
|
CIRCTHWToSMT
|
||||||
|
|
|
@ -29,9 +29,6 @@ MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(LLHD, llhd, circt::llhd::LLHDDialect)
|
||||||
/// Check if a type is a time type.
|
/// Check if a type is a time type.
|
||||||
bool llhdTypeIsATimeType(MlirType type) { return isa<TimeType>(unwrap(type)); }
|
bool llhdTypeIsATimeType(MlirType type) { return isa<TimeType>(unwrap(type)); }
|
||||||
|
|
||||||
/// Check if a type is a signal type.
|
|
||||||
bool llhdTypeIsASignalType(MlirType type) { return isa<SigType>(unwrap(type)); }
|
|
||||||
|
|
||||||
/// Check if a type is a pointer type.
|
/// Check if a type is a pointer type.
|
||||||
bool llhdTypeIsAPointerType(MlirType type) {
|
bool llhdTypeIsAPointerType(MlirType type) {
|
||||||
return isa<PtrType>(unwrap(type));
|
return isa<PtrType>(unwrap(type));
|
||||||
|
@ -42,24 +39,14 @@ MlirType llhdTimeTypeGet(MlirContext ctx) {
|
||||||
return wrap(TimeType::get(unwrap(ctx)));
|
return wrap(TimeType::get(unwrap(ctx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a signal type.
|
|
||||||
MlirType llhdSignalTypeGet(MlirType element) {
|
|
||||||
return wrap(SigType::get(unwrap(element)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a pointer type.
|
/// Create a pointer type.
|
||||||
MlirType llhdPointerTypeGet(MlirType element) {
|
MlirType llhdPointerTypeGet(MlirType element) {
|
||||||
return wrap(PtrType::get(unwrap(element)));
|
return wrap(PtrType::get(unwrap(element)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the inner type of a signal.
|
|
||||||
MlirType llhdSignalTypeGetElementType(MlirType type) {
|
|
||||||
return wrap(cast<SigType>(unwrap(type)).getUnderlyingType());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the inner type of a pointer.
|
/// Get the inner type of a pointer.
|
||||||
MlirType llhdPointerTypeGetElementType(MlirType type) {
|
MlirType llhdPointerTypeGetElementType(MlirType type) {
|
||||||
return wrap(cast<PtrType>(unwrap(type)).getUnderlyingType());
|
return wrap(cast<PtrType>(unwrap(type)).getElementType());
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -15,7 +15,6 @@ add_subdirectory(HandshakeToDC)
|
||||||
add_subdirectory(HandshakeToHW)
|
add_subdirectory(HandshakeToHW)
|
||||||
add_subdirectory(HWArithToHW)
|
add_subdirectory(HWArithToHW)
|
||||||
add_subdirectory(HWToBTOR2)
|
add_subdirectory(HWToBTOR2)
|
||||||
add_subdirectory(HWToLLHD)
|
|
||||||
add_subdirectory(HWToLLVM)
|
add_subdirectory(HWToLLVM)
|
||||||
add_subdirectory(HWToSMT)
|
add_subdirectory(HWToSMT)
|
||||||
add_subdirectory(HWToSV)
|
add_subdirectory(HWToSV)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
add_circt_conversion_library(CIRCTHWToLLHD
|
|
||||||
HWToLLHD.cpp
|
|
||||||
|
|
||||||
DEPENDS
|
|
||||||
CIRCTConversionPassIncGen
|
|
||||||
|
|
||||||
LINK_COMPONENTS
|
|
||||||
Core
|
|
||||||
|
|
||||||
LINK_LIBS PUBLIC
|
|
||||||
CIRCTLLHD
|
|
||||||
CIRCTHW
|
|
||||||
MLIRTransforms
|
|
||||||
)
|
|
|
@ -1,337 +0,0 @@
|
||||||
//===- HWToLLHD.cpp - HW to LLHD Conversion Pass --------------------------===//
|
|
||||||
//
|
|
||||||
// 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 main HW to LLHD Conversion Pass Implementation.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "circt/Conversion/HWToLLHD.h"
|
|
||||||
#include "circt/Dialect/Comb/CombDialect.h"
|
|
||||||
#include "circt/Dialect/Comb/CombOps.h"
|
|
||||||
#include "circt/Dialect/HW/HWDialect.h"
|
|
||||||
#include "circt/Dialect/HW/HWOps.h"
|
|
||||||
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
|
|
||||||
#include "circt/Dialect/LLHD/IR/LLHDOps.h"
|
|
||||||
#include "mlir/IR/BuiltinTypes.h"
|
|
||||||
#include "mlir/Pass/Pass.h"
|
|
||||||
#include "mlir/Transforms/DialectConversion.h"
|
|
||||||
|
|
||||||
namespace circt {
|
|
||||||
#define GEN_PASS_DEF_CONVERTHWTOLLHD
|
|
||||||
#include "circt/Conversion/Passes.h.inc"
|
|
||||||
} // namespace circt
|
|
||||||
|
|
||||||
using namespace circt;
|
|
||||||
using namespace llhd;
|
|
||||||
using namespace hw;
|
|
||||||
using namespace comb;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Convert structure operations
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/// This works on each HW module, creates corresponding entities, moves the
|
|
||||||
/// bodies of the modules into the entities, and converts the bodies.
|
|
||||||
struct ConvertHWModule : public OpConversionPattern<HWModuleOp> {
|
|
||||||
using OpConversionPattern::OpConversionPattern;
|
|
||||||
|
|
||||||
LogicalResult
|
|
||||||
matchAndRewrite(HWModuleOp module, OpAdaptor adaptor,
|
|
||||||
ConversionPatternRewriter &rewriter) const override {
|
|
||||||
// Collect the HW module's port types.
|
|
||||||
unsigned numInputs = module.getNumInputPorts();
|
|
||||||
auto moduleInputs = module.getInputTypes();
|
|
||||||
auto moduleOutputs = module.getOutputTypes();
|
|
||||||
|
|
||||||
// LLHD entities port types are all expressed as block arguments to the op,
|
|
||||||
// so collect all of the types in the expected order (inputs then outputs).
|
|
||||||
SmallVector<Type, 4> entityTypes;
|
|
||||||
entityTypes.append(moduleInputs.begin(), moduleInputs.end());
|
|
||||||
entityTypes.append(moduleOutputs.begin(), moduleOutputs.end());
|
|
||||||
|
|
||||||
// Ensure the input and output types have all been converted already. This
|
|
||||||
// is handled separately by the upstream FunctionLikeTypeConversionPattern.
|
|
||||||
if (!llvm::all_of(entityTypes,
|
|
||||||
[](Type type) { return isa<SigType>(type); }))
|
|
||||||
return rewriter.notifyMatchFailure(module, "Not all ports had SigType");
|
|
||||||
|
|
||||||
// Create the entity. Note that LLHD does not support parameterized
|
|
||||||
// entities, so this conversion does not support parameterized modules.
|
|
||||||
auto entityType = rewriter.getFunctionType(entityTypes, {});
|
|
||||||
auto entity = rewriter.create<EntityOp>(module.getLoc(), entityType,
|
|
||||||
numInputs, /*argAttrs=*/ArrayAttr(),
|
|
||||||
/*resAttrs=*/ArrayAttr());
|
|
||||||
|
|
||||||
// Inline the HW module body into the entity body.
|
|
||||||
Region &entityBodyRegion = entity.getBodyRegion();
|
|
||||||
rewriter.inlineRegionBefore(module.getBodyRegion(), entityBodyRegion,
|
|
||||||
entityBodyRegion.end());
|
|
||||||
|
|
||||||
// Set the entity name attributes. Add block arguments for each output,
|
|
||||||
// since LLHD entity outputs are still block arguments to the op.
|
|
||||||
rewriter.modifyOpInPlace(entity, [&] {
|
|
||||||
entity.setName(module.getName());
|
|
||||||
entityBodyRegion.addArguments(
|
|
||||||
moduleOutputs, SmallVector<Location, 4>(moduleOutputs.size(),
|
|
||||||
rewriter.getUnknownLoc()));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Erase the HW module.
|
|
||||||
rewriter.eraseOp(module);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This works on each output op, creating ops to drive the appropriate results.
|
|
||||||
struct ConvertOutput : public OpConversionPattern<hw::OutputOp> {
|
|
||||||
using OpConversionPattern::OpConversionPattern;
|
|
||||||
|
|
||||||
LogicalResult
|
|
||||||
matchAndRewrite(hw::OutputOp output, OpAdaptor adaptor,
|
|
||||||
ConversionPatternRewriter &rewriter) const override {
|
|
||||||
// Get the number of inputs in the entity to offset into the block args.
|
|
||||||
auto entity = output->getParentOfType<EntityOp>();
|
|
||||||
if (!entity)
|
|
||||||
return rewriter.notifyMatchFailure(output, "parent was not an EntityOp");
|
|
||||||
size_t numInputs = entity.getIns();
|
|
||||||
|
|
||||||
// Drive the results from the mapped operands.
|
|
||||||
Value delta;
|
|
||||||
for (size_t i = 0, e = adaptor.getOperands().size(); i != e; ++i) {
|
|
||||||
// Get the source and destination signals.
|
|
||||||
auto src = adaptor.getOperands()[i];
|
|
||||||
auto dest = entity.getArgument(numInputs + i);
|
|
||||||
if (!src || !dest)
|
|
||||||
return rewriter.notifyMatchFailure(
|
|
||||||
output, "output operand must map to result block arg");
|
|
||||||
|
|
||||||
// Look through probes on the source side and use the signal directly.
|
|
||||||
if (auto prb = src.getDefiningOp<PrbOp>())
|
|
||||||
src = prb.getSignal();
|
|
||||||
|
|
||||||
// No work needed if they already are the same.
|
|
||||||
if (src == dest)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If the source has a signal type, connect it.
|
|
||||||
if (auto sigTy = dyn_cast<SigType>(src.getType())) {
|
|
||||||
rewriter.create<llhd::ConnectOp>(output.getLoc(), dest, src);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, drive the destination block argument value.
|
|
||||||
if (!delta) {
|
|
||||||
delta = rewriter.create<ConstantTimeOp>(output.getLoc(), 0, "ns", 1, 0);
|
|
||||||
}
|
|
||||||
rewriter.create<DrvOp>(output.getLoc(), dest, src, delta, Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the output op.
|
|
||||||
rewriter.eraseOp(output);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This works on each instance op, converting them to the LLHD dialect. If the
|
|
||||||
/// HW instance ops were defined in terms of the CallableOpInterface, we could
|
|
||||||
/// generalize this in terms of the upstream pattern to rewrite call ops' types.
|
|
||||||
struct ConvertInstance : public OpConversionPattern<InstanceOp> {
|
|
||||||
using OpConversionPattern::OpConversionPattern;
|
|
||||||
|
|
||||||
LogicalResult
|
|
||||||
matchAndRewrite(InstanceOp instance, OpAdaptor adaptor,
|
|
||||||
ConversionPatternRewriter &rewriter) const override {
|
|
||||||
Value delta;
|
|
||||||
|
|
||||||
// Materialize signals for instance arguments that are of non-signal type.
|
|
||||||
SmallVector<Value, 4> arguments;
|
|
||||||
unsigned argIdx = 0;
|
|
||||||
for (auto arg : adaptor.getOperands()) {
|
|
||||||
// Connect signals directly.
|
|
||||||
auto argType = arg.getType();
|
|
||||||
if (isa<SigType>(argType)) {
|
|
||||||
arguments.push_back(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look through probes and use the signal directly.
|
|
||||||
if (auto prb = arg.getDefiningOp<PrbOp>()) {
|
|
||||||
arguments.push_back(prb.getSignal());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise materialize a signal.
|
|
||||||
// TODO: This should be a `llhd.buffer` operation. Ultimately we would
|
|
||||||
// want this to be done by the TypeConverter in a materialization
|
|
||||||
// callback. That requires adding the mentioned operation and fleshing out
|
|
||||||
// the semantics of a zero-delay drive in the simulation. Once this is
|
|
||||||
// done, the materializer can insert buffers with no delay and have them
|
|
||||||
// collected in a canonicalization later where appropriate.
|
|
||||||
// See github.com/llvm/circt/pull/988 for a discussion.
|
|
||||||
if (!isa<IntegerType>(argType))
|
|
||||||
return rewriter.notifyMatchFailure(instance, [&](Diagnostic &diag) {
|
|
||||||
diag << "argument type " << argType << " is not supported";
|
|
||||||
});
|
|
||||||
|
|
||||||
auto init = rewriter.create<ConstantOp>(arg.getLoc(), argType, 0);
|
|
||||||
SmallString<8> sigName(instance.getInstanceName());
|
|
||||||
sigName += "_arg_";
|
|
||||||
sigName += std::to_string(argIdx++);
|
|
||||||
auto sig = rewriter.createOrFold<SigOp>(
|
|
||||||
arg.getLoc(), SigType::get(argType), sigName, init);
|
|
||||||
if (!delta) {
|
|
||||||
delta = rewriter.create<ConstantTimeOp>(arg.getLoc(), 0, "ns", 1, 0);
|
|
||||||
}
|
|
||||||
rewriter.create<DrvOp>(arg.getLoc(), sig, arg, delta, Value());
|
|
||||||
arguments.push_back(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// HW instances model output ports as SSA results produced by the op. LLHD
|
|
||||||
// instances model output ports as arguments to the op, so we need to find
|
|
||||||
// or create SSA values. For each output port in the HW instance, try to
|
|
||||||
// find a signal that can be used directly, or else create a new signal.
|
|
||||||
SmallVector<Value, 4> resultSigs;
|
|
||||||
SmallVector<Value, 4> resultValues;
|
|
||||||
for (auto result : instance.getResults()) {
|
|
||||||
auto resultType = result.getType();
|
|
||||||
if (!isa<IntegerType>(resultType))
|
|
||||||
return rewriter.notifyMatchFailure(instance, [&](Diagnostic &diag) {
|
|
||||||
diag << "result type " << resultType << " is not supported";
|
|
||||||
});
|
|
||||||
|
|
||||||
Location loc = result.getLoc();
|
|
||||||
|
|
||||||
// Since we need to have a signal for this result, see if an OutputOp maps
|
|
||||||
// it to an output signal of our parent module. In that case we can just
|
|
||||||
// use that signal.
|
|
||||||
Value sig;
|
|
||||||
for (auto &use : result.getUses()) {
|
|
||||||
if (isa<hw::OutputOp>(use.getOwner())) {
|
|
||||||
auto entity = instance->getParentOfType<EntityOp>();
|
|
||||||
if (!entity)
|
|
||||||
continue;
|
|
||||||
sig = entity.getArgument(entity.getIns() + use.getOperandNumber());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise materialize a signal.
|
|
||||||
// TODO: This should be a `llhd.buffer` operation. Ultimately we would
|
|
||||||
// want this to be done by the TypeConverter in a materialization
|
|
||||||
// callback. That requires adding the mentioned operation and fleshing out
|
|
||||||
// the semantics of a zero-delay drive in the simulation. Once this is
|
|
||||||
// done, the materializer can insert buffers with no delay and have them
|
|
||||||
// collected in a canonicalization later where appropriate.
|
|
||||||
// See github.com/llvm/circt/pull/988 for a discussion.
|
|
||||||
if (!sig) {
|
|
||||||
auto init = rewriter.create<ConstantOp>(loc, resultType, 0);
|
|
||||||
SmallString<8> sigName(instance.getInstanceName());
|
|
||||||
sigName += "_result_";
|
|
||||||
sigName += std::to_string(result.getResultNumber());
|
|
||||||
sig = rewriter.createOrFold<SigOp>(loc, SigType::get(resultType),
|
|
||||||
sigName, init);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make OutputOps directly refer to this signal, which allows them to use
|
|
||||||
// a ConnectOp rather than a PrbOp+DrvOp combo.
|
|
||||||
for (auto &use : llvm::make_early_inc_range(result.getUses())) {
|
|
||||||
if (isa<hw::OutputOp>(use.getOwner())) {
|
|
||||||
rewriter.modifyOpInPlace(use.getOwner(), [&]() { use.set(sig); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Probe the value of the signal such that we end up having a replacement
|
|
||||||
// for the InstanceOp results later on.
|
|
||||||
auto prb = rewriter.create<PrbOp>(loc, resultType, sig);
|
|
||||||
resultSigs.push_back(sig);
|
|
||||||
resultValues.push_back(prb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the LLHD instance from the operands and results. Then mark the
|
|
||||||
// original instance for replacement with the new values probed from the
|
|
||||||
// signals attached to the LLHD instance.
|
|
||||||
rewriter.create<InstOp>(instance.getLoc(), instance.getInstanceName(),
|
|
||||||
instance.getModuleName(), arguments, resultSigs);
|
|
||||||
rewriter.replaceOp(instance, resultValues);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// HW to LLHD Conversion Pass
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct HWToLLHDPass : public circt::impl::ConvertHWToLLHDBase<HWToLLHDPass> {
|
|
||||||
void runOnOperation() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A helper type converter class that automatically populates the relevant
|
|
||||||
/// materializations and type conversions for converting HW to LLHD.
|
|
||||||
struct HWToLLHDTypeConverter : public TypeConverter {
|
|
||||||
HWToLLHDTypeConverter();
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
/// Create a HW to LLHD conversion pass.
|
|
||||||
std::unique_ptr<OperationPass<ModuleOp>> circt::createConvertHWToLLHDPass() {
|
|
||||||
return std::make_unique<HWToLLHDPass>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is the main entrypoint for the HW to LLHD conversion pass.
|
|
||||||
void HWToLLHDPass::runOnOperation() {
|
|
||||||
MLIRContext &context = getContext();
|
|
||||||
ModuleOp module = getOperation();
|
|
||||||
|
|
||||||
// Mark the HW structure ops as illegal such that they get rewritten.
|
|
||||||
ConversionTarget target(context);
|
|
||||||
target.addLegalDialect<LLHDDialect>();
|
|
||||||
target.addLegalDialect<CombDialect>();
|
|
||||||
target.addLegalOp<ConstantOp>();
|
|
||||||
target.addIllegalOp<HWModuleOp>();
|
|
||||||
target.addIllegalOp<hw::OutputOp>();
|
|
||||||
target.addIllegalOp<InstanceOp>();
|
|
||||||
|
|
||||||
// Rewrite `hw.module`, `hw.output`, and `hw.instance`.
|
|
||||||
HWToLLHDTypeConverter typeConverter;
|
|
||||||
RewritePatternSet patterns(&context);
|
|
||||||
populateHWModuleLikeTypeConversionPattern(HWModuleOp::getOperationName(),
|
|
||||||
patterns, typeConverter);
|
|
||||||
patterns.add<ConvertHWModule>(&context);
|
|
||||||
patterns.add<ConvertInstance>(&context);
|
|
||||||
patterns.add<ConvertOutput>(&context);
|
|
||||||
if (failed(applyPartialConversion(module, target, std::move(patterns))))
|
|
||||||
signalPassFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// TypeConverter conversions and materializations
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
HWToLLHDTypeConverter::HWToLLHDTypeConverter() {
|
|
||||||
// Convert any type by just wrapping it in `SigType`.
|
|
||||||
addConversion([](Type type) { return SigType::get(type); });
|
|
||||||
|
|
||||||
// Mark `SigType` legal by converting it to itself.
|
|
||||||
addConversion([](SigType type) { return type; });
|
|
||||||
|
|
||||||
// Materialze probes when arguments are converted from any type to `SigType`.
|
|
||||||
addSourceMaterialization(
|
|
||||||
[](OpBuilder &builder, Type type, ValueRange values, Location loc) {
|
|
||||||
assert(values.size() == 1);
|
|
||||||
auto op = builder.create<PrbOp>(loc, type, values[0]);
|
|
||||||
return op.getResult();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -163,7 +163,7 @@ struct VariableOpConversion : public OpConversionPattern<VariableOp> {
|
||||||
|
|
||||||
if (!init)
|
if (!init)
|
||||||
init = rewriter.create<hw::ConstantOp>(op->getLoc(), resultType, 0);
|
init = rewriter.create<hw::ConstantOp>(op->getLoc(), resultType, 0);
|
||||||
rewriter.replaceOpWithNewOp<llhd::SigOp>(op, llhd::SigType::get(resultType),
|
rewriter.replaceOpWithNewOp<llhd::SigOp>(op, hw::InOutType::get(resultType),
|
||||||
op.getNameAttr(), init);
|
op.getNameAttr(), init);
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,10 +130,10 @@ struct constant_int_all_ones_matcher {
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
unsigned circt::llhd::getLLHDTypeWidth(Type type) {
|
unsigned circt::llhd::getLLHDTypeWidth(Type type) {
|
||||||
if (auto sig = dyn_cast<llhd::SigType>(type))
|
if (auto sig = dyn_cast<hw::InOutType>(type))
|
||||||
type = sig.getUnderlyingType();
|
type = sig.getElementType();
|
||||||
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
|
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
|
||||||
type = ptr.getUnderlyingType();
|
type = ptr.getElementType();
|
||||||
if (auto array = dyn_cast<hw::ArrayType>(type))
|
if (auto array = dyn_cast<hw::ArrayType>(type))
|
||||||
return array.getNumElements();
|
return array.getNumElements();
|
||||||
if (auto tup = dyn_cast<hw::StructType>(type))
|
if (auto tup = dyn_cast<hw::StructType>(type))
|
||||||
|
@ -142,10 +142,10 @@ unsigned circt::llhd::getLLHDTypeWidth(Type type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Type circt::llhd::getLLHDElementType(Type type) {
|
Type circt::llhd::getLLHDElementType(Type type) {
|
||||||
if (auto sig = dyn_cast<llhd::SigType>(type))
|
if (auto sig = dyn_cast<hw::InOutType>(type))
|
||||||
type = sig.getUnderlyingType();
|
type = sig.getElementType();
|
||||||
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
|
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
|
||||||
type = ptr.getUnderlyingType();
|
type = ptr.getElementType();
|
||||||
if (auto array = dyn_cast<hw::ArrayType>(type))
|
if (auto array = dyn_cast<hw::ArrayType>(type))
|
||||||
return array.getElementType();
|
return array.getElementType();
|
||||||
return type;
|
return type;
|
||||||
|
@ -271,7 +271,7 @@ static LogicalResult inferReturnTypesOfStructExtractOp(
|
||||||
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
|
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
|
||||||
Type type =
|
Type type =
|
||||||
cast<hw::StructType>(
|
cast<hw::StructType>(
|
||||||
cast<SigPtrType>(operands[0].getType()).getUnderlyingType())
|
cast<SigPtrType>(operands[0].getType()).getElementType())
|
||||||
.getFieldType(
|
.getFieldType(
|
||||||
cast<StringAttr>(attrs.getNamed("field")->getValue()).getValue());
|
cast<StringAttr>(attrs.getNamed("field")->getValue()).getValue());
|
||||||
if (!type) {
|
if (!type) {
|
||||||
|
@ -288,7 +288,7 @@ LogicalResult llhd::SigStructExtractOp::inferReturnTypes(
|
||||||
MLIRContext *context, std::optional<Location> loc, ValueRange operands,
|
MLIRContext *context, std::optional<Location> loc, ValueRange operands,
|
||||||
DictionaryAttr attrs, mlir::OpaqueProperties properties,
|
DictionaryAttr attrs, mlir::OpaqueProperties properties,
|
||||||
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
|
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
|
||||||
return inferReturnTypesOfStructExtractOp<llhd::SigType>(
|
return inferReturnTypesOfStructExtractOp<hw::InOutType>(
|
||||||
context, loc, operands, attrs, properties, regions, results);
|
context, loc, operands, attrs, properties, regions, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ LogicalResult llhd::EntityOp::verify() {
|
||||||
|
|
||||||
// Check that all block arguments are of signal type
|
// Check that all block arguments are of signal type
|
||||||
for (size_t i = 0; i < numArgs; ++i)
|
for (size_t i = 0; i < numArgs; ++i)
|
||||||
if (!isa<llhd::SigType>(getArgument(i).getType()))
|
if (!isa<hw::InOutType>(getArgument(i).getType()))
|
||||||
return emitError("usage of invalid argument type. Got ")
|
return emitError("usage of invalid argument type. Got ")
|
||||||
<< getArgument(i).getType() << ", expected LLHD signal type";
|
<< getArgument(i).getType() << ", expected LLHD signal type";
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ LogicalResult circt::llhd::EntityOp::verifyType() {
|
||||||
|
|
||||||
// Check that all operands are of signal type
|
// Check that all operands are of signal type
|
||||||
for (Type inputType : type.getInputs())
|
for (Type inputType : type.getInputs())
|
||||||
if (!isa<llhd::SigType>(inputType))
|
if (!isa<hw::InOutType>(inputType))
|
||||||
return emitOpError("usage of invalid argument type. Got ")
|
return emitOpError("usage of invalid argument type. Got ")
|
||||||
<< inputType << ", expected LLHD signal type";
|
<< inputType << ", expected LLHD signal type";
|
||||||
|
|
||||||
|
@ -555,7 +555,7 @@ LogicalResult circt::llhd::ProcOp::verifyType() {
|
||||||
|
|
||||||
// Check that all operands are of signal type
|
// Check that all operands are of signal type
|
||||||
for (int i = 0, e = getNumArguments(); i < e; ++i) {
|
for (int i = 0, e = getNumArguments(); i < e; ++i) {
|
||||||
if (!isa<llhd::SigType>(getArgument(i).getType())) {
|
if (!isa<hw::InOutType>(getArgument(i).getType())) {
|
||||||
return emitOpError("usage of invalid argument type, was ")
|
return emitOpError("usage of invalid argument type, was ")
|
||||||
<< getArgument(i).getType() << ", expected LLHD signal type";
|
<< getArgument(i).getType() << ", expected LLHD signal type";
|
||||||
}
|
}
|
||||||
|
@ -782,16 +782,16 @@ LogicalResult llhd::InstOp::verify() {
|
||||||
|
|
||||||
// Check input types
|
// Check input types
|
||||||
for (size_t i = 0, e = module.getNumInputPorts(); i != e; ++i) {
|
for (size_t i = 0, e = module.getNumInputPorts(); i != e; ++i) {
|
||||||
if (cast<llhd::SigType>(getOperand(i).getType()).getUnderlyingType() !=
|
if (cast<hw::InOutType>(getOperand(i).getType()).getElementType() !=
|
||||||
module.getInputTypes()[i])
|
module.getInputTypes()[i])
|
||||||
return emitOpError("input type mismatch");
|
return emitOpError("input type mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check output types
|
// Check output types
|
||||||
for (size_t i = 0, e = module.getNumOutputPorts(); i != e; ++i) {
|
for (size_t i = 0, e = module.getNumOutputPorts(); i != e; ++i) {
|
||||||
if (cast<llhd::SigType>(
|
if (cast<hw::InOutType>(
|
||||||
getOperand(module.getNumInputPorts() + i).getType())
|
getOperand(module.getNumInputPorts() + i).getType())
|
||||||
.getUnderlyingType() != module.getOutputTypes()[i])
|
.getElementType() != module.getOutputTypes()[i])
|
||||||
return emitOpError("output type mismatch");
|
return emitOpError("output type mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,7 +997,7 @@ LogicalResult llhd::RegOp::verify() {
|
||||||
for (auto val : getValues()) {
|
for (auto val : getValues()) {
|
||||||
if (val.getType() != getSignal().getType() &&
|
if (val.getType() != getSignal().getType() &&
|
||||||
val.getType() !=
|
val.getType() !=
|
||||||
cast<llhd::SigType>(getSignal().getType()).getUnderlyingType()) {
|
cast<hw::InOutType>(getSignal().getType()).getElementType()) {
|
||||||
return emitOpError(
|
return emitOpError(
|
||||||
"type of each 'value' has to be either the same as the "
|
"type of each 'value' has to be either the same as the "
|
||||||
"type of 'signal' or the underlying type of 'signal'");
|
"type of 'signal' or the underlying type of 'signal'");
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "circt/Dialect/LLHD/IR/LLHDTypes.h"
|
#include "circt/Dialect/LLHD/IR/LLHDTypes.h"
|
||||||
|
#include "circt/Dialect/HW/HWTypes.h"
|
||||||
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
|
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
|
||||||
#include "mlir/IR/Builders.h"
|
#include "mlir/IR/Builders.h"
|
||||||
#include "mlir/IR/DialectImplementation.h"
|
#include "mlir/IR/DialectImplementation.h"
|
||||||
|
|
|
@ -142,7 +142,7 @@ void MemoryToBlockArgumentPass::runOnOperation() {
|
||||||
for (Block *jp : joinPoints) {
|
for (Block *jp : joinPoints) {
|
||||||
// Add a block argument for the variable at each join point
|
// Add a block argument for the variable at each join point
|
||||||
BlockArgument phi = jp->addArgument(
|
BlockArgument phi = jp->addArgument(
|
||||||
cast<llhd::PtrType>(var.getType()).getUnderlyingType(), var.getLoc());
|
cast<llhd::PtrType>(var.getType()).getElementType(), var.getLoc());
|
||||||
|
|
||||||
// Add a load at the end of every predecessor and pass the loaded value as
|
// Add a load at the end of every predecessor and pass the loaded value as
|
||||||
// the block argument
|
// the block argument
|
||||||
|
@ -151,7 +151,7 @@ void MemoryToBlockArgumentPass::runOnOperation() {
|
||||||
builder.setInsertionPoint(pred->getTerminator());
|
builder.setInsertionPoint(pred->getTerminator());
|
||||||
Value load = builder.create<llhd::LoadOp>(
|
Value load = builder.create<llhd::LoadOp>(
|
||||||
pred->getTerminator()->getLoc(),
|
pred->getTerminator()->getLoc(),
|
||||||
cast<llhd::PtrType>(var.getType()).getUnderlyingType(), var);
|
cast<llhd::PtrType>(var.getType()).getElementType(), var);
|
||||||
// Add the loaded value as additional block argument
|
// Add the loaded value as additional block argument
|
||||||
addBlockOperandToTerminator(pred->getTerminator(), jp, load);
|
addBlockOperandToTerminator(pred->getTerminator(), jp, load);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct ProcessLoweringPass
|
||||||
/// Backtrack a signal value and make sure that every part of it is in the
|
/// Backtrack a signal value and make sure that every part of it is in the
|
||||||
/// observer list at some point. Assumes that there is no operation that adds
|
/// observer list at some point. Assumes that there is no operation that adds
|
||||||
/// parts to a signal that it does not take as input (e.g. something like
|
/// parts to a signal that it does not take as input (e.g. something like
|
||||||
/// llhd.sig.zext %sig : !llhd.sig<i32> -> !llhd.sig<i64>).
|
/// llhd.sig.zext %sig : !hw.inout<i32> -> !hw.inout<i64>).
|
||||||
static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
|
static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
|
||||||
// If the value in the observer list, we don't need to backtrack further.
|
// If the value in the observer list, we don't need to backtrack further.
|
||||||
if (llvm::is_contained(obs, value))
|
if (llvm::is_contained(obs, value))
|
||||||
|
@ -47,7 +47,7 @@ static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
|
||||||
// last point where it could have been observed. As we've already checked
|
// last point where it could have been observed. As we've already checked
|
||||||
// that, we can fail here. This includes for example llhd.sig
|
// that, we can fail here. This includes for example llhd.sig
|
||||||
if (llvm::none_of(op->getOperands(), [](Value arg) {
|
if (llvm::none_of(op->getOperands(), [](Value arg) {
|
||||||
return isa<llhd::SigType>(arg.getType());
|
return isa<hw::InOutType>(arg.getType());
|
||||||
}))
|
}))
|
||||||
return failure();
|
return failure();
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
|
||||||
// they are covered by that probe. As soon as we find a signal that is not
|
// they are covered by that probe. As soon as we find a signal that is not
|
||||||
// observed no matter how far we backtrack, we fail.
|
// observed no matter how far we backtrack, we fail.
|
||||||
return success(llvm::all_of(op->getOperands(), [&](Value arg) {
|
return success(llvm::all_of(op->getOperands(), [&](Value arg) {
|
||||||
return !isa<llhd::SigType>(arg.getType()) ||
|
return !isa<hw::InOutType>(arg.getType()) ||
|
||||||
succeeded(checkSignalsAreObserved(obs, arg));
|
succeeded(checkSignalsAreObserved(obs, arg));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// RUN: circt-opt -convert-hw-to-llhd -split-input-file -verify-diagnostics %s
|
|
||||||
|
|
||||||
module {
|
|
||||||
// Since HW-to-LLHD needs to construct a zero value for temporary signals,
|
|
||||||
// we don't support non-IntegerType arguments to instances.
|
|
||||||
hw.module @sub(in %in: f16, out out: f16) {
|
|
||||||
hw.output %in: f16
|
|
||||||
}
|
|
||||||
hw.module @test(in %in: f16, out out: f16) {
|
|
||||||
// expected-error @+1 {{failed to legalize operation 'hw.instance'}}
|
|
||||||
%0 = hw.instance "sub1" @sub (in: %in: f16) -> (out: f16)
|
|
||||||
hw.output %0: f16
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
// RUN: circt-opt --convert-hw-to-llhd --verify-diagnostics %s | FileCheck %s
|
|
||||||
|
|
||||||
module {
|
|
||||||
// CHECK-LABEL: llhd.entity @FeedThrough
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) ->
|
|
||||||
// CHECK-SAME: (%[[OUT:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @FeedThrough(in %in: i1, out out: i1) {
|
|
||||||
// CHECK: llhd.con %[[OUT]], %[[IN]]
|
|
||||||
hw.output %in: i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @CombOp
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) ->
|
|
||||||
// CHECK-SAME: (%[[OUT:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @CombOp(in %in : i1, out out: i1) {
|
|
||||||
// CHECK: %[[PRB:.+]] = llhd.prb %[[IN]]
|
|
||||||
// CHECK: %[[ADD:.+]] = comb.add %[[PRB]], %[[PRB]]
|
|
||||||
// CHECK: llhd.drv %[[OUT]], %[[ADD]]
|
|
||||||
%0 = comb.add %in, %in : i1
|
|
||||||
hw.output %0: i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @sub
|
|
||||||
// CHECK-SAME: ({{.+}} : !llhd.sig<i1>) ->
|
|
||||||
// CHECK-SAME: ({{.+}} : !llhd.sig<i1>)
|
|
||||||
hw.module @sub(in %in: i1, out out: i1) {
|
|
||||||
hw.output %in : i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @SimpleInstance
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) ->
|
|
||||||
// CHECK-SAME: (%[[OUT:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @SimpleInstance(in %in: i1, out out: i1) {
|
|
||||||
// CHECK: llhd.inst "sub1" @sub(%[[IN]]) -> (%[[OUT]]) : (!llhd.sig<i1>) -> !llhd.sig<i1>
|
|
||||||
%0 = hw.instance "sub1" @sub (in: %in: i1) -> (out: i1)
|
|
||||||
hw.output %0 : i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @InstanceWithLocalOps
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) ->
|
|
||||||
// CHECK-SAME: (%[[OUT:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @InstanceWithLocalOps(in %in: i1, out out: i1) {
|
|
||||||
// CHECK: %[[PRB:.+]] = llhd.prb %[[IN]]
|
|
||||||
// CHECK: %[[ADD1:.+]] = comb.add %[[PRB]], %[[PRB]]
|
|
||||||
// CHECK: llhd.drv %[[ARG_SIG:.+]], %[[ADD1]]
|
|
||||||
// CHECK: %[[RES_SIG:.+]] = llhd.sig
|
|
||||||
// CHECK: %[[RES:.+]] = llhd.prb %[[RES_SIG]]
|
|
||||||
// CHECK: llhd.inst "sub1" @sub(%[[ARG_SIG]]) -> (%[[RES_SIG]]) : (!llhd.sig<i1>) -> !llhd.sig<i1>
|
|
||||||
// CHECK: %[[ADD2:.+]] = comb.add %[[RES]], %[[RES]]
|
|
||||||
// CHECK: llhd.drv %[[OUT:.+]], %[[ADD2]]
|
|
||||||
%0 = comb.add %in, %in : i1
|
|
||||||
%1 = hw.instance "sub1" @sub (in: %0: i1) -> (out: i1)
|
|
||||||
%2 = comb.add %1, %1 : i1
|
|
||||||
hw.output %2 : i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @InstanceDirectlyDrivingMultipleOutputs
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) -> (
|
|
||||||
// CHECK-SAME: %[[OUT1:.+]] : !llhd.sig<i1>,
|
|
||||||
// CHECK-SAME: %[[OUT2:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @InstanceDirectlyDrivingMultipleOutputs(in %in: i1, out out1: i1, out out2: i1) {
|
|
||||||
// CHECK: llhd.inst "sub1" @sub(%[[IN]]) -> (%[[OUT2]]) : (!llhd.sig<i1>) -> !llhd.sig<i1>
|
|
||||||
// CHECK: llhd.con %[[OUT1]], %[[OUT2]]
|
|
||||||
%0 = hw.instance "sub1" @sub (in: %in: i1) -> (out: i1)
|
|
||||||
hw.output %0, %0 : i1, i1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.entity @InstanceIndirectlyDrivingMultipleOutputs
|
|
||||||
// CHECK-SAME: (%[[IN:.+]] : !llhd.sig<i1>) -> (
|
|
||||||
// CHECK-SAME: %[[OUT1:.+]] : !llhd.sig<i1>,
|
|
||||||
// CHECK-SAME: %[[OUT2:.+]] : !llhd.sig<i1>)
|
|
||||||
hw.module @InstanceIndirectlyDrivingMultipleOutputs(in %in: i1, out out1: i1, out out2: i1) {
|
|
||||||
// CHECK: %[[RES_SIG:.+]] = llhd.sig
|
|
||||||
// CHECK: %[[RES:.+]] = llhd.prb %[[RES_SIG]]
|
|
||||||
// CHECK: llhd.inst "sub1" @sub(%[[IN]]) -> (%[[RES_SIG]]) : (!llhd.sig<i1>) -> !llhd.sig<i1>
|
|
||||||
// CHECK: %[[ADD:.+]] = comb.add %[[RES]], %[[RES]]
|
|
||||||
// CHECK: llhd.drv %[[OUT1:.+]], %[[ADD]]
|
|
||||||
// CHECK: llhd.drv %[[OUT2:.+]], %[[ADD]]
|
|
||||||
%0 = hw.instance "sub1" @sub(in: %in: i1) -> (out: i1)
|
|
||||||
%1 = comb.add %0, %0 : i1
|
|
||||||
hw.output %1, %1 : i1, i1
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -268,7 +268,7 @@ moore.module @Variable() {
|
||||||
// CHECK: [[B:%.+]] = llhd.sig "b1" [[TMP1]] : i8
|
// CHECK: [[B:%.+]] = llhd.sig "b1" [[TMP1]] : i8
|
||||||
%b1 = moore.variable : <i8>
|
%b1 = moore.variable : <i8>
|
||||||
|
|
||||||
// CHECK: [[PRB:%.+]] = llhd.prb [[B]] : !llhd.sig<i8>
|
// CHECK: [[PRB:%.+]] = llhd.prb [[B]] : !hw.inout<i8>
|
||||||
%0 = moore.read %b1 : <i8>
|
%0 = moore.read %b1 : <i8>
|
||||||
// CHECK: llhd.sig "b2" [[PRB]] : i8
|
// CHECK: llhd.sig "b2" [[PRB]] : i8
|
||||||
%b2 = moore.variable %0 : <i8>
|
%b2 = moore.variable %0 : <i8>
|
||||||
|
@ -284,7 +284,7 @@ moore.module @Variable() {
|
||||||
%3 = moore.constant 10 : i32
|
%3 = moore.constant 10 : i32
|
||||||
|
|
||||||
// CHECK: [[TIME:%.+]] = llhd.constant_time <0ns, 0d, 0e>
|
// CHECK: [[TIME:%.+]] = llhd.constant_time <0ns, 0d, 0e>
|
||||||
// CHECK: llhd.drv [[A]], [[TMP2]] after [[TIME]] : !llhd.sig<i32>
|
// CHECK: llhd.drv [[A]], [[TMP2]] after [[TIME]] : !hw.inout<i32>
|
||||||
moore.assign %a, %3 : i32
|
moore.assign %a, %3 : i32
|
||||||
|
|
||||||
// CHECK: hw.output
|
// CHECK: hw.output
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @const_hoisting
|
// CHECK-LABEL: @const_hoisting
|
||||||
// CHECK-SAME: %[[SIG:.*]]: !llhd.sig<i32>
|
// CHECK-SAME: %[[SIG:.*]]: !hw.inout<i32>
|
||||||
func.func @const_hoisting(%sig : !llhd.sig<i32>) {
|
func.func @const_hoisting(%sig : !hw.inout<i32>) {
|
||||||
// CHECK-DAG: %[[C0:.*]] = hw.constant -1 : i32
|
// CHECK-DAG: %[[C0:.*]] = hw.constant -1 : i32
|
||||||
// CHECK-DAG: %[[TIME:.*]] = llhd.constant_time <1ns, 0d, 0e>
|
// CHECK-DAG: %[[TIME:.*]] = llhd.constant_time <1ns, 0d, 0e>
|
||||||
// CHECK-NEXT: cf.br ^[[BB:.*]]
|
// CHECK-NEXT: cf.br ^[[BB:.*]]
|
||||||
|
@ -11,7 +11,7 @@ func.func @const_hoisting(%sig : !llhd.sig<i32>) {
|
||||||
^bb1:
|
^bb1:
|
||||||
%0 = hw.constant -1 : i32
|
%0 = hw.constant -1 : i32
|
||||||
%1 = llhd.constant_time <1ns, 0d, 0e>
|
%1 = llhd.constant_time <1ns, 0d, 0e>
|
||||||
// CHECK-NEXT: llhd.drv %[[SIG]], %[[C0]] after %[[TIME]] : !llhd.sig<i32>
|
// CHECK-NEXT: llhd.drv %[[SIG]], %[[C0]] after %[[TIME]] : !hw.inout<i32>
|
||||||
llhd.drv %sig, %0 after %1 : !llhd.sig<i32>
|
llhd.drv %sig, %0 after %1 : !hw.inout<i32>
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @sigExtractOp
|
// CHECK-LABEL: @sigExtractOp
|
||||||
func.func @sigExtractOp(%arg0 : !llhd.sig<i32>, %arg1: i5) -> (!llhd.sig<i32>, !llhd.sig<i32>) {
|
func.func @sigExtractOp(%arg0 : !hw.inout<i32>, %arg1: i5) -> (!hw.inout<i32>, !hw.inout<i32>) {
|
||||||
%zero = hw.constant 0 : i5
|
%zero = hw.constant 0 : i5
|
||||||
|
|
||||||
// CHECK: %[[EXT:.*]] = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i32>
|
// CHECK: %[[EXT:.*]] = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i32>
|
||||||
%0 = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i32>
|
%0 = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i32>
|
||||||
|
|
||||||
%1 = llhd.sig.extract %arg0 from %zero : (!llhd.sig<i32>) -> !llhd.sig<i32>
|
%1 = llhd.sig.extract %arg0 from %zero : (!hw.inout<i32>) -> !hw.inout<i32>
|
||||||
|
|
||||||
// CHECK-NEXT: return %[[EXT]], %arg0 : !llhd.sig<i32>, !llhd.sig<i32>
|
// CHECK-NEXT: return %[[EXT]], %arg0 : !hw.inout<i32>, !hw.inout<i32>
|
||||||
return %0, %1 : !llhd.sig<i32>, !llhd.sig<i32>
|
return %0, %1 : !hw.inout<i32>, !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @sigArraySlice
|
// CHECK-LABEL: @sigArraySlice
|
||||||
func.func @sigArraySliceOp(%arg0: !llhd.sig<!hw.array<30xi32>>, %arg1: i5)
|
func.func @sigArraySliceOp(%arg0: !hw.inout<array<30xi32>>, %arg1: i5)
|
||||||
-> (!llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<20xi32>>, !llhd.sig<!hw.array<3xi32>>) {
|
-> (!hw.inout<array<30xi32>>, !hw.inout<array<30xi32>>, !hw.inout<array<20xi32>>, !hw.inout<array<3xi32>>) {
|
||||||
%zero = hw.constant 0 : i5
|
%zero = hw.constant 0 : i5
|
||||||
|
|
||||||
// CHECK-NEXT: %c-13_i5 = hw.constant -13 : i5
|
// CHECK-NEXT: %c-13_i5 = hw.constant -13 : i5
|
||||||
|
@ -23,16 +23,16 @@ func.func @sigArraySliceOp(%arg0: !llhd.sig<!hw.array<30xi32>>, %arg1: i5)
|
||||||
%a = hw.constant 3 : i5
|
%a = hw.constant 3 : i5
|
||||||
%b = hw.constant 16 : i5
|
%b = hw.constant 16 : i5
|
||||||
|
|
||||||
// CHECK: %[[EXT:.*]] = llhd.sig.array_slice %arg0 at %arg1 : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<30xi32>>
|
// CHECK: %[[EXT:.*]] = llhd.sig.array_slice %arg0 at %arg1 : (!hw.inout<array<30xi32>>) -> !hw.inout<array<30xi32>>
|
||||||
%ext = llhd.sig.array_slice %arg0 at %arg1 : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<30xi32>>
|
%ext = llhd.sig.array_slice %arg0 at %arg1 : (!hw.inout<array<30xi32>>) -> !hw.inout<array<30xi32>>
|
||||||
|
|
||||||
%identity = llhd.sig.array_slice %arg0 at %zero : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<30xi32>>
|
%identity = llhd.sig.array_slice %arg0 at %zero : (!hw.inout<array<30xi32>>) -> !hw.inout<array<30xi32>>
|
||||||
|
|
||||||
// CHECK-NEXT: %[[RES1:.*]] = llhd.sig.array_slice
|
// CHECK-NEXT: %[[RES1:.*]] = llhd.sig.array_slice
|
||||||
// CHECK-NEXT: %[[RES2:.*]] = llhd.sig.array_slice %arg0 at %c-13_i5 : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<3xi32>>
|
// CHECK-NEXT: %[[RES2:.*]] = llhd.sig.array_slice %arg0 at %c-13_i5 : (!hw.inout<array<30xi32>>) -> !hw.inout<array<3xi32>>
|
||||||
%1 = llhd.sig.array_slice %arg0 at %a : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<20xi32>>
|
%1 = llhd.sig.array_slice %arg0 at %a : (!hw.inout<array<30xi32>>) -> !hw.inout<array<20xi32>>
|
||||||
%2 = llhd.sig.array_slice %1 at %b : (!llhd.sig<!hw.array<20xi32>>) -> !llhd.sig<!hw.array<3xi32>>
|
%2 = llhd.sig.array_slice %1 at %b : (!hw.inout<array<20xi32>>) -> !hw.inout<array<3xi32>>
|
||||||
|
|
||||||
// CHECK-NEXT: return %[[EXT]], %arg0, %[[RES1]], %[[RES2]] : !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<20xi32>>, !llhd.sig<!hw.array<3xi32>>
|
// CHECK-NEXT: return %[[EXT]], %arg0, %[[RES1]], %[[RES2]] : !hw.inout<array<30xi32>>, !hw.inout<array<30xi32>>, !hw.inout<array<20xi32>>, !hw.inout<array<3xi32>>
|
||||||
return %ext, %identity, %1, %2 : !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<20xi32>>, !llhd.sig<!hw.array<3xi32>>
|
return %ext, %identity, %1, %2 : !hw.inout<array<30xi32>>, !hw.inout<array<30xi32>>, !hw.inout<array<20xi32>>, !hw.inout<array<3xi32>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
// RUN: circt-opt %s -cse | FileCheck %s
|
// RUN: circt-opt %s -cse | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @checkPrbDceAndCseIn
|
// CHECK-LABEL: @checkPrbDceAndCseIn
|
||||||
llhd.entity @checkPrbDceAndCseIn(%arg0 : !llhd.sig<i32>) -> (%arg1 : !llhd.sig<i32>, %arg2 : !llhd.sig<i32>) {
|
llhd.entity @checkPrbDceAndCseIn(%arg0 : !hw.inout<i32>) -> (%arg1 : !hw.inout<i32>, %arg2 : !hw.inout<i32>) {
|
||||||
// CHECK-NEXT: llhd.constant_time
|
// CHECK-NEXT: llhd.constant_time
|
||||||
%time = llhd.constant_time <0ns, 1d, 0e>
|
%time = llhd.constant_time <0ns, 1d, 0e>
|
||||||
|
|
||||||
// CHECK-NEXT: [[P0:%.*]] = llhd.prb
|
// CHECK-NEXT: [[P0:%.*]] = llhd.prb
|
||||||
%1 = llhd.prb %arg0 : !llhd.sig<i32>
|
%1 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
%2 = llhd.prb %arg0 : !llhd.sig<i32>
|
%2 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
%3 = llhd.prb %arg0 : !llhd.sig<i32>
|
%3 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.drv %arg1, [[P0]]
|
// CHECK-NEXT: llhd.drv %arg1, [[P0]]
|
||||||
// CHECK-NEXT: llhd.drv %arg2, [[P0]]
|
// CHECK-NEXT: llhd.drv %arg2, [[P0]]
|
||||||
llhd.drv %arg1, %1 after %time : !llhd.sig<i32>
|
llhd.drv %arg1, %1 after %time : !hw.inout<i32>
|
||||||
llhd.drv %arg2, %2 after %time : !llhd.sig<i32>
|
llhd.drv %arg2, %2 after %time : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @checkPrbDceButNotCse
|
// CHECK-LABEL: @checkPrbDceButNotCse
|
||||||
llhd.proc @checkPrbDceButNotCse(%arg0 : !llhd.sig<i32>) -> (%arg1 : !llhd.sig<i32>, %arg2 : !llhd.sig<i32>) {
|
llhd.proc @checkPrbDceButNotCse(%arg0 : !hw.inout<i32>) -> (%arg1 : !hw.inout<i32>, %arg2 : !hw.inout<i32>) {
|
||||||
// CHECK-NEXT: llhd.constant_time
|
// CHECK-NEXT: llhd.constant_time
|
||||||
%time = llhd.constant_time <0ns, 1d, 0e>
|
%time = llhd.constant_time <0ns, 1d, 0e>
|
||||||
|
|
||||||
// CHECK-NEXT: [[P1:%.*]] = llhd.prb
|
// CHECK-NEXT: [[P1:%.*]] = llhd.prb
|
||||||
%1 = llhd.prb %arg0 : !llhd.sig<i32>
|
%1 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
// CHECK-NEXT: llhd.wait
|
// CHECK-NEXT: llhd.wait
|
||||||
llhd.wait (%arg0: !llhd.sig<i32>), ^bb1
|
llhd.wait (%arg0: !hw.inout<i32>), ^bb1
|
||||||
// CHECK-NEXT: ^bb1:
|
// CHECK-NEXT: ^bb1:
|
||||||
^bb1:
|
^bb1:
|
||||||
// CHECK-NEXT: [[P2:%.*]] = llhd.prb
|
// CHECK-NEXT: [[P2:%.*]] = llhd.prb
|
||||||
%2 = llhd.prb %arg0 : !llhd.sig<i32>
|
%2 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
%3 = llhd.prb %arg0 : !llhd.sig<i32>
|
%3 = llhd.prb %arg0 : !hw.inout<i32>
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.drv %arg1, [[P1]]
|
// CHECK-NEXT: llhd.drv %arg1, [[P1]]
|
||||||
// CHECK-NEXT: llhd.drv %arg2, [[P2]]
|
// CHECK-NEXT: llhd.drv %arg2, [[P2]]
|
||||||
llhd.drv %arg1, %1 after %time : !llhd.sig<i32>
|
llhd.drv %arg1, %1 after %time : !hw.inout<i32>
|
||||||
llhd.drv %arg2, %2 after %time : !llhd.sig<i32>
|
llhd.drv %arg2, %2 after %time : !hw.inout<i32>
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @drv_folding
|
// CHECK-LABEL: @drv_folding
|
||||||
// CHECK-SAME: %[[SIG:.*]]: !llhd.sig<i32>
|
// CHECK-SAME: %[[SIG:.*]]: !hw.inout<i32>
|
||||||
// CHECK-SAME: %[[VAL:.*]]: i32
|
// CHECK-SAME: %[[VAL:.*]]: i32
|
||||||
// CHECK-SAME: %[[TIME:.*]]: !llhd.time
|
// CHECK-SAME: %[[TIME:.*]]: !llhd.time
|
||||||
// CHECK-SAME: %[[COND:.*]]: i1
|
// CHECK-SAME: %[[COND:.*]]: i1
|
||||||
func.func @drv_folding(%sig: !llhd.sig<i32>, %val: i32, %time: !llhd.time, %cond: i1) {
|
func.func @drv_folding(%sig: !hw.inout<i32>, %val: i32, %time: !llhd.time, %cond: i1) {
|
||||||
%true = hw.constant 1 : i1
|
%true = hw.constant 1 : i1
|
||||||
%false = hw.constant 0 : i1
|
%false = hw.constant 0 : i1
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] :
|
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] :
|
||||||
llhd.drv %sig, %val after %time : !llhd.sig<i32>
|
llhd.drv %sig, %val after %time : !hw.inout<i32>
|
||||||
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] if %[[COND]] :
|
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] if %[[COND]] :
|
||||||
llhd.drv %sig, %val after %time if %cond : !llhd.sig<i32>
|
llhd.drv %sig, %val after %time if %cond : !hw.inout<i32>
|
||||||
llhd.drv %sig, %val after %time if %false : !llhd.sig<i32>
|
llhd.drv %sig, %val after %time if %false : !hw.inout<i32>
|
||||||
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] :
|
// CHECK-NEXT: llhd.drv %[[SIG]], %[[VAL]] after %[[TIME]] :
|
||||||
llhd.drv %sig, %val after %time if %true : !llhd.sig<i32>
|
llhd.drv %sig, %val after %time if %true : !hw.inout<i32>
|
||||||
|
|
||||||
// CHECK-NEXT: return
|
// CHECK-NEXT: return
|
||||||
return
|
return
|
||||||
|
@ -23,6 +23,6 @@ func.func @drv_folding(%sig: !llhd.sig<i32>, %val: i32, %time: !llhd.time, %cond
|
||||||
|
|
||||||
// CHECK-LABEL: @con_folding
|
// CHECK-LABEL: @con_folding
|
||||||
// CHECK-NOT: llhd.con
|
// CHECK-NOT: llhd.con
|
||||||
llhd.entity @con_folding(%sig: !llhd.sig<i32>) {
|
llhd.entity @con_folding(%sig: !hw.inout<i32>) {
|
||||||
llhd.con %sig, %sig : !llhd.sig<i32>
|
llhd.con %sig, %sig : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
// RUN: circt-opt %s -split-input-file -verify-diagnostics
|
// RUN: circt-opt %s -split-input-file -verify-diagnostics
|
||||||
|
|
||||||
// expected-note @+1 {{prior use here}}
|
// expected-note @+1 {{prior use here}}
|
||||||
llhd.entity @connect_different_types(%in: !llhd.sig<i8>) -> (%out: !llhd.sig<i32>) {
|
llhd.entity @connect_different_types(%in: !hw.inout<i8>) -> (%out: !hw.inout<i32>) {
|
||||||
// expected-error @+1 {{use of value '%out' expects different type}}
|
// expected-error @+1 {{use of value '%out' expects different type}}
|
||||||
llhd.con %in, %out : !llhd.sig<i8>
|
llhd.con %in, %out : !hw.inout<i8>
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
llhd.entity @connect_non_signals(%in: !llhd.sig<i32>) -> (%out: !llhd.sig<i32>) {
|
llhd.entity @connect_non_signals(%in: !hw.inout<i32>) -> (%out: !hw.inout<i32>) {
|
||||||
%0 = llhd.prb %in : !llhd.sig<i32>
|
%0 = llhd.prb %in : !hw.inout<i32>
|
||||||
%1 = llhd.prb %out : !llhd.sig<i32>
|
%1 = llhd.prb %out : !hw.inout<i32>
|
||||||
// expected-error @+1 {{'llhd.con' op operand #0 must be LLHD sig type}}
|
// expected-error @+1 {{'llhd.con' op operand #0 must be InOutType}}
|
||||||
llhd.con %0, %1 : i32
|
llhd.con %0, %1 : i32
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
// CHECK-SAME: (%[[IN:.+]] : [[TYPE:.+]]) ->
|
// CHECK-SAME: (%[[IN:.+]] : [[TYPE:.+]]) ->
|
||||||
// CHECK-SAME: (%[[OUT:.+]] : [[TYPE]])
|
// CHECK-SAME: (%[[OUT:.+]] : [[TYPE]])
|
||||||
// CHECK-NEXT: llhd.con %[[IN]], %[[OUT]] : [[TYPE]]
|
// CHECK-NEXT: llhd.con %[[IN]], %[[OUT]] : [[TYPE]]
|
||||||
llhd.entity @connect_ports(%in: !llhd.sig<i32>) -> (%out: !llhd.sig<i32>) {
|
llhd.entity @connect_ports(%in: !hw.inout<i32>) -> (%out: !hw.inout<i32>) {
|
||||||
llhd.con %in, %out : !llhd.sig<i32>
|
llhd.con %in, %out : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
// RUN: circt-opt %s | circt-opt | FileCheck %s
|
// RUN: circt-opt %s | circt-opt | FileCheck %s
|
||||||
|
|
||||||
// check inputs and outputs, usage
|
// check inputs and outputs, usage
|
||||||
// CHECK: llhd.entity @foo (%[[ARG0:.*]] : !llhd.sig<i64>, %[[ARG1:.*]] : !llhd.sig<i64>) -> (%[[OUT0:.*]] : !llhd.sig<i64>) {
|
// CHECK: llhd.entity @foo (%[[ARG0:.*]] : !hw.inout<i64>, %[[ARG1:.*]] : !hw.inout<i64>) -> (%[[OUT0:.*]] : !hw.inout<i64>) {
|
||||||
"llhd.entity"() ({
|
"llhd.entity"() ({
|
||||||
^body(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>, %out0 : !llhd.sig<i64>):
|
^body(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>, %out0 : !hw.inout<i64>):
|
||||||
// CHECK-NEXT: %[[C0:.*]] = hw.constant 1
|
// CHECK-NEXT: %[[C0:.*]] = hw.constant 1
|
||||||
%0 = hw.constant 1 : i64
|
%0 = hw.constant 1 : i64
|
||||||
// CHECK-NEXT: %[[P0:.*]] = llhd.prb %[[ARG0]]
|
// CHECK-NEXT: %[[P0:.*]] = llhd.prb %[[ARG0]]
|
||||||
%1 = llhd.prb %arg0 : !llhd.sig<i64>
|
%1 = llhd.prb %arg0 : !hw.inout<i64>
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
}) {sym_name="foo", ins=2, function_type=(!llhd.sig<i64>, !llhd.sig<i64>, !llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="foo", ins=2, function_type=(!hw.inout<i64>, !hw.inout<i64>, !hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
||||||
// check 0 inputs, empty body
|
// check 0 inputs, empty body
|
||||||
// CHECK-NEXT: llhd.entity @bar () -> (%{{.*}} : !llhd.sig<i64>) {
|
// CHECK-NEXT: llhd.entity @bar () -> (%{{.*}} : !hw.inout<i64>) {
|
||||||
"llhd.entity"() ({
|
"llhd.entity"() ({
|
||||||
^body(%0 : !llhd.sig<i64>):
|
^body(%0 : !hw.inout<i64>):
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
}) {sym_name="bar", ins=0, function_type=(!llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="bar", ins=0, function_type=(!hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
||||||
// check 0 outputs, empty body
|
// check 0 outputs, empty body
|
||||||
// CHECK-NEXT: llhd.entity @baz (%{{.*}} : !llhd.sig<i64>) -> () {
|
// CHECK-NEXT: llhd.entity @baz (%{{.*}} : !hw.inout<i64>) -> () {
|
||||||
"llhd.entity"() ({
|
"llhd.entity"() ({
|
||||||
^body(%arg0 : !llhd.sig<i64>):
|
^body(%arg0 : !hw.inout<i64>):
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
}) {sym_name="baz", ins=1, function_type=(!llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="baz", ins=1, function_type=(!hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
||||||
//check 0 arguments, empty body
|
//check 0 arguments, empty body
|
||||||
// CHECK-NEXT: llhd.entity @out_of_names () -> () {
|
// CHECK-NEXT: llhd.entity @out_of_names () -> () {
|
||||||
|
|
|
@ -1,53 +1,53 @@
|
||||||
// RUN: circt-opt %s -mlir-print-op-generic -split-input-file -verify-diagnostics
|
// RUN: circt-opt %s -mlir-print-op-generic -split-input-file -verify-diagnostics
|
||||||
|
|
||||||
func.func @illegal_signal_to_array(%sig : !llhd.sig<!hw.array<3xi32>>, %ind: i2) {
|
func.func @illegal_signal_to_array(%sig : !hw.inout<array<3xi32>>, %ind: i2) {
|
||||||
// expected-error @+1 {{'llhd.sig.array_slice' op result #0 must be LLHD sig type of an ArrayType values, but got '!hw.array<3xi32>'}}
|
// expected-error @+1 {{'llhd.sig.array_slice' op result #0 must be InOutType of an ArrayType values, but got '!hw.array<3xi32>'}}
|
||||||
%0 = llhd.sig.array_slice %sig at %ind : (!llhd.sig<!hw.array<3xi32>>) -> !hw.array<3xi32>
|
%0 = llhd.sig.array_slice %sig at %ind : (!hw.inout<array<3xi32>>) -> !hw.array<3xi32>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func.func @illegal_array_element_type_mismatch(%sig : !llhd.sig<!hw.array<3xi32>>, %ind: i2) {
|
func.func @illegal_array_element_type_mismatch(%sig : !hw.inout<array<3xi32>>, %ind: i2) {
|
||||||
// expected-error @+1 {{arrays element type must match}}
|
// expected-error @+1 {{arrays element type must match}}
|
||||||
%0 = llhd.sig.array_slice %sig at %ind : (!llhd.sig<!hw.array<3xi32>>) -> !llhd.sig<!hw.array<2xi1>>
|
%0 = llhd.sig.array_slice %sig at %ind : (!hw.inout<array<3xi32>>) -> !hw.inout<array<2xi1>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func.func @illegal_result_array_too_big(%sig : !llhd.sig<!hw.array<3xi32>>, %ind: i2) {
|
func.func @illegal_result_array_too_big(%sig : !hw.inout<array<3xi32>>, %ind: i2) {
|
||||||
// expected-error @+1 {{width of result type has to be smaller than or equal to the input type}}
|
// expected-error @+1 {{width of result type has to be smaller than or equal to the input type}}
|
||||||
%0 = llhd.sig.array_slice %sig at %ind : (!llhd.sig<!hw.array<3xi32>>) -> !llhd.sig<!hw.array<4xi32>>
|
%0 = llhd.sig.array_slice %sig at %ind : (!hw.inout<array<3xi32>>) -> !hw.inout<array<4xi32>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func.func @illegal_sig_to_int(%s : !llhd.sig<i32>, %ind: i5) {
|
func.func @illegal_sig_to_int(%s : !hw.inout<i32>, %ind: i5) {
|
||||||
// expected-error @+1 {{'llhd.sig.extract' op result #0 must be LLHD sig type of a signless integer bitvector values, but got 'i10'}}
|
// expected-error @+1 {{'llhd.sig.extract' op result #0 must be InOutType of a signless integer bitvector values, but got 'i10'}}
|
||||||
%0 = llhd.sig.extract %s from %ind : (!llhd.sig<i32>) -> i10
|
%0 = llhd.sig.extract %s from %ind : (!hw.inout<i32>) -> i10
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func.func @illegal_sig_to_int_to_wide(%s : !llhd.sig<i32>, %ind: i5) {
|
func.func @illegal_sig_to_int_to_wide(%s : !hw.inout<i32>, %ind: i5) {
|
||||||
// expected-error @+1 {{width of result type has to be smaller than or equal to the input type}}
|
// expected-error @+1 {{width of result type has to be smaller than or equal to the input type}}
|
||||||
%0 = llhd.sig.extract %s from %ind : (!llhd.sig<i32>) -> !llhd.sig<i64>
|
%0 = llhd.sig.extract %s from %ind : (!hw.inout<i32>) -> !hw.inout<i64>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func.func @extract_element_tuple_index_out_of_bounds(%tup : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>) {
|
func.func @extract_element_tuple_index_out_of_bounds(%tup : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>) {
|
||||||
// expected-error @+1 {{invalid field name specified}}
|
// expected-error @+1 {{invalid field name specified}}
|
||||||
%0 = llhd.sig.struct_extract %tup["foobar"] : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>
|
%0 = llhd.sig.struct_extract %tup["foobar"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
// RUN: circt-opt %s -mlir-print-op-generic -split-input-file -verify-diagnostics | circt-opt | circt-opt | FileCheck %s
|
// RUN: circt-opt %s -mlir-print-op-generic -split-input-file -verify-diagnostics | circt-opt | circt-opt | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @sigExtract
|
// CHECK-LABEL: @sigExtract
|
||||||
func.func @sigExtract (%arg0 : !llhd.sig<i32>, %arg1: i5) -> () {
|
func.func @sigExtract (%arg0 : !hw.inout<i32>, %arg1: i5) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i5>
|
// CHECK-NEXT: %{{.*}} = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i5>
|
||||||
%1 = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i5>
|
%1 = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i5>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @sigArray
|
// CHECK-LABEL: @sigArray
|
||||||
func.func @sigArray (%arg0 : !llhd.sig<!hw.array<5xi1>>, %arg1: i3) -> () {
|
func.func @sigArray (%arg0 : !hw.inout<array<5xi1>>, %arg1: i3) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.sig.array_slice %arg0 at %arg1 : (!llhd.sig<!hw.array<5xi1>>) -> !llhd.sig<!hw.array<3xi1>>
|
// CHECK-NEXT: %{{.*}} = llhd.sig.array_slice %arg0 at %arg1 : (!hw.inout<array<5xi1>>) -> !hw.inout<array<3xi1>>
|
||||||
%0 = llhd.sig.array_slice %arg0 at %arg1 : (!llhd.sig<!hw.array<5xi1>>) -> !llhd.sig<!hw.array<3xi1>>
|
%0 = llhd.sig.array_slice %arg0 at %arg1 : (!hw.inout<array<5xi1>>) -> !hw.inout<array<3xi1>>
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.sig.array_get %arg0[%arg1] : !llhd.sig<!hw.array<5xi1>>
|
// CHECK-NEXT: %{{.*}} = llhd.sig.array_get %arg0[%arg1] : !hw.inout<array<5xi1>>
|
||||||
%1 = llhd.sig.array_get %arg0[%arg1] : !llhd.sig<!hw.array<5xi1>>
|
%1 = llhd.sig.array_get %arg0[%arg1] : !hw.inout<array<5xi1>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @sigStructExtract
|
// CHECK-LABEL: @sigStructExtract
|
||||||
func.func @sigStructExtract(%arg0 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>) {
|
func.func @sigStructExtract(%arg0 : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>) {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.sig.struct_extract %arg0["foo"] : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>
|
// CHECK-NEXT: %{{.*}} = llhd.sig.struct_extract %arg0["foo"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
|
||||||
%0 = llhd.sig.struct_extract %arg0["foo"] : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>
|
%0 = llhd.sig.struct_extract %arg0["foo"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.sig.struct_extract %arg0["baz"] : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>
|
// CHECK-NEXT: %{{.*}} = llhd.sig.struct_extract %arg0["baz"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
|
||||||
%1 = llhd.sig.struct_extract %arg0["baz"] : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i3>>
|
%1 = llhd.sig.struct_extract %arg0["baz"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ llhd.proc @fail() -> () {
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
llhd.entity @operand_count_mismatch(%arg : !llhd.sig<i32>) -> () {}
|
llhd.entity @operand_count_mismatch(%arg : !hw.inout<i32>) -> () {}
|
||||||
|
|
||||||
llhd.entity @caller(%arg : !llhd.sig<i32>) -> () {
|
llhd.entity @caller(%arg : !hw.inout<i32>) -> () {
|
||||||
// expected-error @+1 {{incorrect number of inputs for entity instantiation}}
|
// expected-error @+1 {{incorrect number of inputs for entity instantiation}}
|
||||||
llhd.inst "mismatch" @operand_count_mismatch() -> (%arg) : () -> (!llhd.sig<i32>)
|
llhd.inst "mismatch" @operand_count_mismatch() -> (%arg) : () -> (!hw.inout<i32>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
@ -46,9 +46,9 @@ llhd.entity @test_uniqueness() -> () {
|
||||||
|
|
||||||
hw.module @module(in %arg0: i2) {}
|
hw.module @module(in %arg0: i2) {}
|
||||||
|
|
||||||
llhd.entity @moduleTypeMismatch(%arg0: !llhd.sig<i3>) -> () {
|
llhd.entity @moduleTypeMismatch(%arg0: !hw.inout<i3>) -> () {
|
||||||
// expected-error @+1 {{input type mismatch}}
|
// expected-error @+1 {{input type mismatch}}
|
||||||
llhd.inst "inst" @module(%arg0) -> () : (!llhd.sig<i3>) -> ()
|
llhd.inst "inst" @module(%arg0) -> () : (!hw.inout<i3>) -> ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
@ -58,9 +58,9 @@ hw.module @module(out arg0: i2) {
|
||||||
hw.output %0 : i2
|
hw.output %0 : i2
|
||||||
}
|
}
|
||||||
|
|
||||||
llhd.entity @moduleTypeMismatch() -> (%arg0: !llhd.sig<i3>) {
|
llhd.entity @moduleTypeMismatch() -> (%arg0: !hw.inout<i3>) {
|
||||||
// expected-error @+1 {{output type mismatch}}
|
// expected-error @+1 {{output type mismatch}}
|
||||||
llhd.inst "inst" @module() -> (%arg0) : () -> !llhd.sig<i3>
|
llhd.inst "inst" @module() -> (%arg0) : () -> !hw.inout<i3>
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
@ -71,4 +71,4 @@ llhd.proc @empty() -> () {}
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
// expected-error @below {{empty block: expect at least a terminator}}
|
// expected-error @below {{empty block: expect at least a terminator}}
|
||||||
llhd.proc @empty(%a: !llhd.sig<i1>) -> () {}
|
llhd.proc @empty(%a: !hw.inout<i1>) -> () {}
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
llhd.entity @empty_entity() -> () {}
|
llhd.entity @empty_entity() -> () {}
|
||||||
|
|
||||||
// CHECK-LABEL: @one_input_entity
|
// CHECK-LABEL: @one_input_entity
|
||||||
llhd.entity @one_input_entity(%arg : !llhd.sig<i32>) -> () {}
|
llhd.entity @one_input_entity(%arg : !hw.inout<i32>) -> () {}
|
||||||
|
|
||||||
// CHECK-LABEL: @one_output_entity
|
// CHECK-LABEL: @one_output_entity
|
||||||
llhd.entity @one_output_entity() -> (%arg : !llhd.sig<i32>) {}
|
llhd.entity @one_output_entity() -> (%arg : !hw.inout<i32>) {}
|
||||||
|
|
||||||
// CHECK-LABEL: @entity
|
// CHECK-LABEL: @entity
|
||||||
llhd.entity @entity(%arg0 : !llhd.sig<i32>, %arg1 : !llhd.sig<i16>) -> (%out0 : !llhd.sig<i8>, %out1 : !llhd.sig<i4>) {}
|
llhd.entity @entity(%arg0 : !hw.inout<i32>, %arg1 : !hw.inout<i16>) -> (%out0 : !hw.inout<i8>, %out1 : !hw.inout<i4>) {}
|
||||||
|
|
||||||
// CHECK-LABEL: @empty_proc
|
// CHECK-LABEL: @empty_proc
|
||||||
llhd.proc @empty_proc() -> () {
|
llhd.proc @empty_proc() -> () {
|
||||||
|
@ -25,17 +25,17 @@ llhd.proc @empty_proc() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @one_input_proc
|
// CHECK-LABEL: @one_input_proc
|
||||||
llhd.proc @one_input_proc(%arg : !llhd.sig<i32>) -> () {
|
llhd.proc @one_input_proc(%arg : !hw.inout<i32>) -> () {
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @one_output_proc
|
// CHECK-LABEL: @one_output_proc
|
||||||
llhd.proc @one_output_proc() -> (%arg : !llhd.sig<i32>) {
|
llhd.proc @one_output_proc() -> (%arg : !hw.inout<i32>) {
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @proc
|
// CHECK-LABEL: @proc
|
||||||
llhd.proc @proc(%arg0 : !llhd.sig<i32>, %arg1 : !llhd.sig<i16>) -> (%out0 : !llhd.sig<i8>, %out1 : !llhd.sig<i4>) {
|
llhd.proc @proc(%arg0 : !hw.inout<i32>, %arg1 : !hw.inout<i16>) -> (%out0 : !hw.inout<i8>, %out1 : !hw.inout<i4>) {
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,25 +45,25 @@ hw.module @hwModule(in %arg0 : i32, in %arg1 : i16, out arg2: i8) {
|
||||||
hw.output %0 : i8
|
hw.output %0 : i8
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: llhd.entity @caller (%[[ARG0:.*]] : !llhd.sig<i32>, %[[ARG1:.*]] : !llhd.sig<i16>) -> (%[[OUT0:.*]] : !llhd.sig<i8>, %[[OUT1:.*]] : !llhd.sig<i4>) {
|
// CHECK: llhd.entity @caller (%[[ARG0:.*]] : !hw.inout<i32>, %[[ARG1:.*]] : !hw.inout<i16>) -> (%[[OUT0:.*]] : !hw.inout<i8>, %[[OUT1:.*]] : !hw.inout<i4>) {
|
||||||
llhd.entity @caller(%arg0 : !llhd.sig<i32>, %arg1 : !llhd.sig<i16>) -> (%out0 : !llhd.sig<i8>, %out1 : !llhd.sig<i4>) {
|
llhd.entity @caller(%arg0 : !hw.inout<i32>, %arg1 : !hw.inout<i16>) -> (%out0 : !hw.inout<i8>, %out1 : !hw.inout<i4>) {
|
||||||
// CHECK-NEXT: llhd.inst "empty_entity" @empty_entity() -> () : () -> ()
|
// CHECK-NEXT: llhd.inst "empty_entity" @empty_entity() -> () : () -> ()
|
||||||
"llhd.inst"() {callee=@empty_entity, operandSegmentSizes=array<i32: 0,0>, name="empty_entity"} : () -> ()
|
"llhd.inst"() {callee=@empty_entity, operandSegmentSizes=array<i32: 0,0>, name="empty_entity"} : () -> ()
|
||||||
// CHECK-NEXT: llhd.inst "empty_proc" @empty_proc() -> () : () -> ()
|
// CHECK-NEXT: llhd.inst "empty_proc" @empty_proc() -> () : () -> ()
|
||||||
"llhd.inst"() {callee=@empty_proc, operandSegmentSizes=array<i32: 0,0>, name="empty_proc"} : () -> ()
|
"llhd.inst"() {callee=@empty_proc, operandSegmentSizes=array<i32: 0,0>, name="empty_proc"} : () -> ()
|
||||||
// CHECK-NEXT: llhd.inst "one_in_entity" @one_input_entity(%[[ARG0]]) -> () : (!llhd.sig<i32>) -> ()
|
// CHECK-NEXT: llhd.inst "one_in_entity" @one_input_entity(%[[ARG0]]) -> () : (!hw.inout<i32>) -> ()
|
||||||
"llhd.inst"(%arg0) {callee=@one_input_entity, operandSegmentSizes=array<i32: 1,0>, name="one_in_entity"} : (!llhd.sig<i32>) -> ()
|
"llhd.inst"(%arg0) {callee=@one_input_entity, operandSegmentSizes=array<i32: 1,0>, name="one_in_entity"} : (!hw.inout<i32>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "one_in_proc" @one_input_proc(%[[ARG0]]) -> () : (!llhd.sig<i32>) -> ()
|
// CHECK-NEXT: llhd.inst "one_in_proc" @one_input_proc(%[[ARG0]]) -> () : (!hw.inout<i32>) -> ()
|
||||||
"llhd.inst"(%arg0) {callee=@one_input_proc, operandSegmentSizes=array<i32: 1,0>, name="one_in_proc"} : (!llhd.sig<i32>) -> ()
|
"llhd.inst"(%arg0) {callee=@one_input_proc, operandSegmentSizes=array<i32: 1,0>, name="one_in_proc"} : (!hw.inout<i32>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "one_out_entity" @one_output_entity() -> (%[[ARG0]]) : () -> !llhd.sig<i32>
|
// CHECK-NEXT: llhd.inst "one_out_entity" @one_output_entity() -> (%[[ARG0]]) : () -> !hw.inout<i32>
|
||||||
"llhd.inst"(%arg0) {callee=@one_output_entity, operandSegmentSizes=array<i32: 0,1>, name="one_out_entity"} : (!llhd.sig<i32>) -> ()
|
"llhd.inst"(%arg0) {callee=@one_output_entity, operandSegmentSizes=array<i32: 0,1>, name="one_out_entity"} : (!hw.inout<i32>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "one_out_proc" @one_output_proc() -> (%[[ARG0]]) : () -> !llhd.sig<i32>
|
// CHECK-NEXT: llhd.inst "one_out_proc" @one_output_proc() -> (%[[ARG0]]) : () -> !hw.inout<i32>
|
||||||
"llhd.inst"(%arg0) {callee=@one_output_proc, operandSegmentSizes=array<i32: 0,1>, name="one_out_proc"} : (!llhd.sig<i32>) -> ()
|
"llhd.inst"(%arg0) {callee=@one_output_proc, operandSegmentSizes=array<i32: 0,1>, name="one_out_proc"} : (!hw.inout<i32>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "entity" @entity(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!llhd.sig<i32>, !llhd.sig<i16>) -> (!llhd.sig<i8>, !llhd.sig<i4>)
|
// CHECK-NEXT: llhd.inst "entity" @entity(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!hw.inout<i32>, !hw.inout<i16>) -> (!hw.inout<i8>, !hw.inout<i4>)
|
||||||
"llhd.inst"(%arg0, %arg1, %out0, %out1) {callee=@entity, operandSegmentSizes=array<i32: 2,2>, name="entity"} : (!llhd.sig<i32>, !llhd.sig<i16>, !llhd.sig<i8>, !llhd.sig<i4>) -> ()
|
"llhd.inst"(%arg0, %arg1, %out0, %out1) {callee=@entity, operandSegmentSizes=array<i32: 2,2>, name="entity"} : (!hw.inout<i32>, !hw.inout<i16>, !hw.inout<i8>, !hw.inout<i4>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "proc" @proc(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!llhd.sig<i32>, !llhd.sig<i16>) -> (!llhd.sig<i8>, !llhd.sig<i4>)
|
// CHECK-NEXT: llhd.inst "proc" @proc(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!hw.inout<i32>, !hw.inout<i16>) -> (!hw.inout<i8>, !hw.inout<i4>)
|
||||||
"llhd.inst"(%arg0, %arg1, %out0, %out1) {callee=@proc, operandSegmentSizes=array<i32: 2,2>, name="proc"} : (!llhd.sig<i32>, !llhd.sig<i16>, !llhd.sig<i8>, !llhd.sig<i4>) -> ()
|
"llhd.inst"(%arg0, %arg1, %out0, %out1) {callee=@proc, operandSegmentSizes=array<i32: 2,2>, name="proc"} : (!hw.inout<i32>, !hw.inout<i16>, !hw.inout<i8>, !hw.inout<i4>) -> ()
|
||||||
// CHECK-NEXT: llhd.inst "module" @hwModule(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]]) : (!llhd.sig<i32>, !llhd.sig<i16>) -> !llhd.sig<i8>
|
// CHECK-NEXT: llhd.inst "module" @hwModule(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]]) : (!hw.inout<i32>, !hw.inout<i16>) -> !hw.inout<i8>
|
||||||
llhd.inst "module" @hwModule(%arg0, %arg1) -> (%out0) : (!llhd.sig<i32>, !llhd.sig<i16>) -> !llhd.sig<i8>
|
llhd.inst "module" @hwModule(%arg0, %arg1) -> (%out0) : (!hw.inout<i32>, !hw.inout<i16>) -> !hw.inout<i8>
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,28 +9,28 @@
|
||||||
}) {sym_name="empty", ins=0, function_type=()->()} : () -> ()
|
}) {sym_name="empty", ins=0, function_type=()->()} : () -> ()
|
||||||
|
|
||||||
// two inputs, one output
|
// two inputs, one output
|
||||||
// CHECK-NEXT: llhd.proc @inputandoutput(%{{.*}} : !llhd.sig<i64>, %{{.*}} : !llhd.sig<i64>) -> (%{{.*}} : !llhd.sig<i64>) {
|
// CHECK-NEXT: llhd.proc @inputandoutput(%{{.*}} : !hw.inout<i64>, %{{.*}} : !hw.inout<i64>) -> (%{{.*}} : !hw.inout<i64>) {
|
||||||
"llhd.proc"() ({
|
"llhd.proc"() ({
|
||||||
// CHECK-NEXT: llhd.halt
|
// CHECK-NEXT: llhd.halt
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
^body(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>, %out0 : !llhd.sig<i64>):
|
^body(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>, %out0 : !hw.inout<i64>):
|
||||||
"llhd.halt"() {} : () -> ()
|
"llhd.halt"() {} : () -> ()
|
||||||
}) {sym_name="inputandoutput", ins=2, function_type=(!llhd.sig<i64>, !llhd.sig<i64>, !llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="inputandoutput", ins=2, function_type=(!hw.inout<i64>, !hw.inout<i64>, !hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
||||||
// zero inputs, one output
|
// zero inputs, one output
|
||||||
// CHECK-NEXT: llhd.proc @output() -> (%{{.*}} : !llhd.sig<i64>) {
|
// CHECK-NEXT: llhd.proc @output() -> (%{{.*}} : !hw.inout<i64>) {
|
||||||
"llhd.proc"() ({
|
"llhd.proc"() ({
|
||||||
// CHECK-NEXT: llhd.halt
|
// CHECK-NEXT: llhd.halt
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
^body(%0 : !llhd.sig<i64>):
|
^body(%0 : !hw.inout<i64>):
|
||||||
"llhd.halt"() {} : () -> ()
|
"llhd.halt"() {} : () -> ()
|
||||||
}) {sym_name="output", ins=0, function_type=(!llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="output", ins=0, function_type=(!hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
||||||
// one input, zero outputs
|
// one input, zero outputs
|
||||||
// CHECK-NEXT: llhd.proc @input(%{{.*}} : !llhd.sig<i64>) -> () {
|
// CHECK-NEXT: llhd.proc @input(%{{.*}} : !hw.inout<i64>) -> () {
|
||||||
"llhd.proc"() ({
|
"llhd.proc"() ({
|
||||||
// CHECK-NEXT: llhd.halt
|
// CHECK-NEXT: llhd.halt
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
^body(%arg0 : !llhd.sig<i64>):
|
^body(%arg0 : !hw.inout<i64>):
|
||||||
"llhd.halt"() {} : () -> ()
|
"llhd.halt"() {} : () -> ()
|
||||||
}) {sym_name="input", ins=1, function_type=(!llhd.sig<i64>)->()} : () -> ()
|
}) {sym_name="input", ins=1, function_type=(!hw.inout<i64>)->()} : () -> ()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// RUN: circt-opt %s -split-input-file -verify-diagnostics | circt-opt | FileCheck %s
|
// RUN: circt-opt %s -split-input-file -verify-diagnostics | circt-opt | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: @check_reg
|
// CHECK-LABEL: @check_reg
|
||||||
// CHECK-SAME: %[[IN64:.*]] : !llhd.sig<i64>
|
// CHECK-SAME: %[[IN64:.*]] : !hw.inout<i64>
|
||||||
llhd.entity @check_reg (%in64 : !llhd.sig<i64>) -> () {
|
llhd.entity @check_reg (%in64 : !hw.inout<i64>) -> () {
|
||||||
// CHECK: %[[C1:.*]] = hw.constant
|
// CHECK: %[[C1:.*]] = hw.constant
|
||||||
%c1 = hw.constant 0 : i1
|
%c1 = hw.constant 0 : i1
|
||||||
// CHECK-NEXT: %[[C64:.*]] = hw.constant
|
// CHECK-NEXT: %[[C64:.*]] = hw.constant
|
||||||
|
@ -10,14 +10,14 @@ llhd.entity @check_reg (%in64 : !llhd.sig<i64>) -> () {
|
||||||
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
|
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
// one trigger with optional gate
|
// one trigger with optional gate
|
||||||
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] if %[[C1]] : i64) : !llhd.sig<i64>
|
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] if %[[C1]] : i64) : !hw.inout<i64>
|
||||||
"llhd.reg"(%in64, %c64, %c1, %time, %c1) {modes=[0], gateMask=[1], operandSegmentSizes=array<i32: 1,1,1,1,1>} : (!llhd.sig<i64>, i64, i1, !llhd.time, i1) -> ()
|
"llhd.reg"(%in64, %c64, %c1, %time, %c1) {modes=[0], gateMask=[1], operandSegmentSizes=array<i32: 1,1,1,1,1>} : (!hw.inout<i64>, i64, i1, !llhd.time, i1) -> ()
|
||||||
// two triggers with optional gates
|
// two triggers with optional gates
|
||||||
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] if %[[C1]] : i64), (%[[IN64]], "high" %[[C1]] after %[[TIME]] if %[[C1]] : !llhd.sig<i64>) : !llhd.sig<i64>
|
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] if %[[C1]] : i64), (%[[IN64]], "high" %[[C1]] after %[[TIME]] if %[[C1]] : !hw.inout<i64>) : !hw.inout<i64>
|
||||||
"llhd.reg"(%in64, %c64, %in64, %c1, %c1, %time, %time, %c1, %c1) {modes=[0,1], gateMask=[1,2], operandSegmentSizes=array<i32: 1,2,2,2,2>} : (!llhd.sig<i64>, i64, !llhd.sig<i64>, i1, i1, !llhd.time, !llhd.time, i1, i1) -> ()
|
"llhd.reg"(%in64, %c64, %in64, %c1, %c1, %time, %time, %c1, %c1) {modes=[0,1], gateMask=[1,2], operandSegmentSizes=array<i32: 1,2,2,2,2>} : (!hw.inout<i64>, i64, !hw.inout<i64>, i1, i1, !llhd.time, !llhd.time, i1, i1) -> ()
|
||||||
// two triggers with only one optional gate
|
// two triggers with only one optional gate
|
||||||
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] : i64), (%[[IN64]], "high" %[[C1]] after %[[TIME]] if %[[C1]] : !llhd.sig<i64>) : !llhd.sig<i64>
|
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] : i64), (%[[IN64]], "high" %[[C1]] after %[[TIME]] if %[[C1]] : !hw.inout<i64>) : !hw.inout<i64>
|
||||||
"llhd.reg"(%in64, %c64, %in64, %c1, %c1, %time, %time, %c1) {modes=[0,1], gateMask=[0,1], operandSegmentSizes=array<i32: 1,2,2,2,1>} : (!llhd.sig<i64>, i64, !llhd.sig<i64>, i1, i1, !llhd.time, !llhd.time, i1) -> ()
|
"llhd.reg"(%in64, %c64, %in64, %c1, %c1, %time, %time, %c1) {modes=[0,1], gateMask=[0,1], operandSegmentSizes=array<i32: 1,2,2,2,1>} : (!hw.inout<i64>, i64, !hw.inout<i64>, i1, i1, !llhd.time, !llhd.time, i1) -> ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add verification tests in reg-errors.mlir (expected-error tests)
|
// TODO: add verification tests in reg-errors.mlir (expected-error tests)
|
||||||
|
|
|
@ -3,23 +3,23 @@
|
||||||
// expected-error @+3 {{failed to verify that type of 'init' and underlying type of 'signal' have to match.}}
|
// expected-error @+3 {{failed to verify that type of 'init' and underlying type of 'signal' have to match.}}
|
||||||
llhd.entity @check_illegal_sig () -> () {
|
llhd.entity @check_illegal_sig () -> () {
|
||||||
%cI1 = hw.constant 0 : i1
|
%cI1 = hw.constant 0 : i1
|
||||||
%sig1 = "llhd.sig"(%cI1) {name="foo"} : (i1) -> !llhd.sig<i32>
|
%sig1 = "llhd.sig"(%cI1) {name="foo"} : (i1) -> !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
// expected-error @+2 {{failed to verify that type of 'result' and underlying type of 'signal' have to match.}}
|
// expected-error @+2 {{failed to verify that type of 'result' and underlying type of 'signal' have to match.}}
|
||||||
llhd.entity @check_illegal_prb (%sig : !llhd.sig<i1>) -> () {
|
llhd.entity @check_illegal_prb (%sig : !hw.inout<i1>) -> () {
|
||||||
%prb = "llhd.prb"(%sig) {} : (!llhd.sig<i1>) -> i32
|
%prb = "llhd.prb"(%sig) {} : (!hw.inout<i1>) -> i32
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
// expected-error @+4 {{failed to verify that type of 'value' and underlying type of 'signal' have to match.}}
|
// expected-error @+4 {{failed to verify that type of 'value' and underlying type of 'signal' have to match.}}
|
||||||
llhd.entity @check_illegal_drv (%sig : !llhd.sig<i1>) -> () {
|
llhd.entity @check_illegal_drv (%sig : !hw.inout<i1>) -> () {
|
||||||
%c = hw.constant 0 : i32
|
%c = hw.constant 0 : i32
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
"llhd.drv"(%sig, %c, %time) {} : (!llhd.sig<i1>, i32, !llhd.time) -> ()
|
"llhd.drv"(%sig, %c, %time) {} : (!hw.inout<i1>, i32, !llhd.time) -> ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
|
@ -23,15 +23,15 @@ llhd.entity @checkSigInst () -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: checkPrb
|
// CHECK-LABEL: checkPrb
|
||||||
func.func @checkPrb(%arg0 : !llhd.sig<i1>, %arg1 : !llhd.sig<i64>, %arg2 : !llhd.sig<!hw.array<3xi8>>, %arg3 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>) {
|
func.func @checkPrb(%arg0 : !hw.inout<i1>, %arg1 : !hw.inout<i64>, %arg2 : !hw.inout<array<3xi8>>, %arg3 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>) {
|
||||||
// CHECK: %{{.*}} = llhd.prb %arg0 : !llhd.sig<i1>
|
// CHECK: %{{.*}} = llhd.prb %arg0 : !hw.inout<i1>
|
||||||
%0 = llhd.prb %arg0 : !llhd.sig<i1>
|
%0 = llhd.prb %arg0 : !hw.inout<i1>
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb %arg1 : !llhd.sig<i64>
|
// CHECK-NEXT: %{{.*}} = llhd.prb %arg1 : !hw.inout<i64>
|
||||||
%1 = llhd.prb %arg1 : !llhd.sig<i64>
|
%1 = llhd.prb %arg1 : !hw.inout<i64>
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb %arg2 : !llhd.sig<!hw.array<3xi8>>
|
// CHECK-NEXT: %{{.*}} = llhd.prb %arg2 : !hw.inout<array<3xi8>>
|
||||||
%2 = llhd.prb %arg2 : !llhd.sig<!hw.array<3xi8>>
|
%2 = llhd.prb %arg2 : !hw.inout<array<3xi8>>
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb %arg3 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
|
// CHECK-NEXT: %{{.*}} = llhd.prb %arg3 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
|
||||||
%3 = llhd.prb %arg3 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
|
%3 = llhd.prb %arg3 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -47,21 +47,21 @@ func.func @checkOutput(%arg0: i32, %arg1: !llhd.time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: checkDrv
|
// CHECK-LABEL: checkDrv
|
||||||
func.func @checkDrv(%arg0 : !llhd.sig<i1>, %arg1 : !llhd.sig<i64>, %arg2 : i1,
|
func.func @checkDrv(%arg0 : !hw.inout<i1>, %arg1 : !hw.inout<i64>, %arg2 : i1,
|
||||||
%arg3 : i64, %arg4 : !llhd.time, %arg5 : !llhd.sig<!hw.array<3xi8>>,
|
%arg3 : i64, %arg4 : !llhd.time, %arg5 : !hw.inout<array<3xi8>>,
|
||||||
%arg6 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>,
|
%arg6 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>,
|
||||||
%arg7 : !hw.array<3xi8>, %arg8 : !hw.struct<foo: i1, bar: i2, baz: i4>) {
|
%arg7 : !hw.array<3xi8>, %arg8 : !hw.struct<foo: i1, bar: i2, baz: i4>) {
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.drv %arg0, %arg2 after %arg4 : !llhd.sig<i1>
|
// CHECK-NEXT: llhd.drv %arg0, %arg2 after %arg4 : !hw.inout<i1>
|
||||||
llhd.drv %arg0, %arg2 after %arg4 : !llhd.sig<i1>
|
llhd.drv %arg0, %arg2 after %arg4 : !hw.inout<i1>
|
||||||
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 : !llhd.sig<i64>
|
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 : !hw.inout<i64>
|
||||||
llhd.drv %arg1, %arg3 after %arg4 : !llhd.sig<i64>
|
llhd.drv %arg1, %arg3 after %arg4 : !hw.inout<i64>
|
||||||
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !llhd.sig<i64>
|
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !hw.inout<i64>
|
||||||
llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !llhd.sig<i64>
|
llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !hw.inout<i64>
|
||||||
// CHECK-NEXT: llhd.drv %arg5, %arg7 after %arg4 : !llhd.sig<!hw.array<3xi8>>
|
// CHECK-NEXT: llhd.drv %arg5, %arg7 after %arg4 : !hw.inout<array<3xi8>>
|
||||||
llhd.drv %arg5, %arg7 after %arg4 : !llhd.sig<!hw.array<3xi8>>
|
llhd.drv %arg5, %arg7 after %arg4 : !hw.inout<array<3xi8>>
|
||||||
// CHECK-NEXT: llhd.drv %arg6, %arg8 after %arg4 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
|
// CHECK-NEXT: llhd.drv %arg6, %arg8 after %arg4 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
|
||||||
llhd.drv %arg6, %arg8 after %arg4 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
|
llhd.drv %arg6, %arg8 after %arg4 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,22 +26,22 @@ llhd.proc @check_wait_1 () -> () {
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: llhd.proc @check_wait_2(%[[ARG0:.*]] : !llhd.sig<i64>, %[[ARG1:.*]] : !llhd.sig<i1>) -> () {
|
// CHECK: llhd.proc @check_wait_2(%[[ARG0:.*]] : !hw.inout<i64>, %[[ARG1:.*]] : !hw.inout<i1>) -> () {
|
||||||
llhd.proc @check_wait_2 (%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i1>) -> () {
|
llhd.proc @check_wait_2 (%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i1>) -> () {
|
||||||
// CHECK-NEXT: llhd.wait (%[[ARG0]], %[[ARG1]] : !llhd.sig<i64>, !llhd.sig<i1>), ^[[BB:.*]](%[[ARG1]] : !llhd.sig<i1>)
|
// CHECK-NEXT: llhd.wait (%[[ARG0]], %[[ARG1]] : !hw.inout<i64>, !hw.inout<i1>), ^[[BB:.*]](%[[ARG1]] : !hw.inout<i1>)
|
||||||
"llhd.wait"(%arg0, %arg1, %arg1) [^bb1] {operandSegmentSizes=array<i32: 2,0,1>} : (!llhd.sig<i64>, !llhd.sig<i1>, !llhd.sig<i1>) -> ()
|
"llhd.wait"(%arg0, %arg1, %arg1) [^bb1] {operandSegmentSizes=array<i32: 2,0,1>} : (!hw.inout<i64>, !hw.inout<i1>, !hw.inout<i1>) -> ()
|
||||||
// CHECK: ^[[BB]](%[[A:.*]]: !llhd.sig<i1>):
|
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>):
|
||||||
^bb1(%a: !llhd.sig<i1>):
|
^bb1(%a: !hw.inout<i1>):
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: llhd.proc @check_wait_3(%[[ARG0:.*]] : !llhd.sig<i64>, %[[ARG1:.*]] : !llhd.sig<i1>) -> () {
|
// CHECK: llhd.proc @check_wait_3(%[[ARG0:.*]] : !hw.inout<i64>, %[[ARG1:.*]] : !hw.inout<i1>) -> () {
|
||||||
llhd.proc @check_wait_3 (%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i1>) -> () {
|
llhd.proc @check_wait_3 (%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i1>) -> () {
|
||||||
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
|
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
|
||||||
%time = llhd.constant_time #llhd.time<0ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<0ns, 0d, 0e>
|
||||||
// CHECK-NEXT: llhd.wait for %[[TIME]], (%[[ARG0]], %[[ARG1]] : !llhd.sig<i64>, !llhd.sig<i1>), ^[[BB:.*]](%[[ARG1]], %[[ARG0]] : !llhd.sig<i1>, !llhd.sig<i64>)
|
// CHECK-NEXT: llhd.wait for %[[TIME]], (%[[ARG0]], %[[ARG1]] : !hw.inout<i64>, !hw.inout<i1>), ^[[BB:.*]](%[[ARG1]], %[[ARG0]] : !hw.inout<i1>, !hw.inout<i64>)
|
||||||
"llhd.wait"(%arg0, %arg1, %time, %arg1, %arg0) [^bb1] {operandSegmentSizes=array<i32: 2,1,2>} : (!llhd.sig<i64>, !llhd.sig<i1>, !llhd.time, !llhd.sig<i1>, !llhd.sig<i64>) -> ()
|
"llhd.wait"(%arg0, %arg1, %time, %arg1, %arg0) [^bb1] {operandSegmentSizes=array<i32: 2,1,2>} : (!hw.inout<i64>, !hw.inout<i1>, !llhd.time, !hw.inout<i1>, !hw.inout<i64>) -> ()
|
||||||
// CHECK: ^[[BB]](%[[A:.*]]: !llhd.sig<i1>, %[[B:.*]]: !llhd.sig<i64>):
|
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>, %[[B:.*]]: !hw.inout<i64>):
|
||||||
^bb1(%a: !llhd.sig<i1>, %b: !llhd.sig<i64>):
|
^bb1(%a: !hw.inout<i1>, %b: !hw.inout<i64>):
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,12 @@ llhd.entity @root () -> () {
|
||||||
%3 = hw.constant 1 : i5
|
%3 = hw.constant 1 : i5
|
||||||
%4 = hw.constant 4 : i5
|
%4 = hw.constant 4 : i5
|
||||||
%t = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%t = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
%e0 = llhd.sig.extract %s0 from %2 : (!llhd.sig<i32>) -> !llhd.sig<i16>
|
%e0 = llhd.sig.extract %s0 from %2 : (!hw.inout<i32>) -> !hw.inout<i16>
|
||||||
%e1 = llhd.sig.extract %s1 from %4 : (!llhd.sig<i32>) -> !llhd.sig<i8>
|
%e1 = llhd.sig.extract %s1 from %4 : (!hw.inout<i32>) -> !hw.inout<i8>
|
||||||
%e2 = llhd.sig.extract %s2 from %2 : (!llhd.sig<i32>) -> !llhd.sig<i1>
|
%e2 = llhd.sig.extract %s2 from %2 : (!hw.inout<i32>) -> !hw.inout<i1>
|
||||||
%e3 = llhd.sig.extract %s2 from %3 : (!llhd.sig<i32>) -> !llhd.sig<i1>
|
%e3 = llhd.sig.extract %s2 from %3 : (!hw.inout<i32>) -> !hw.inout<i1>
|
||||||
llhd.drv %e0, %c0 after %t : !llhd.sig<i16>
|
llhd.drv %e0, %c0 after %t : !hw.inout<i16>
|
||||||
llhd.drv %e1, %c1 after %t : !llhd.sig<i8>
|
llhd.drv %e1, %c1 after %t : !hw.inout<i8>
|
||||||
llhd.drv %e2, %c2 after %t : !llhd.sig<i1>
|
llhd.drv %e2, %c2 after %t : !hw.inout<i1>
|
||||||
llhd.drv %e3, %c2 after %t : !llhd.sig<i1>
|
llhd.drv %e3, %c2 after %t : !hw.inout<i1>
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ llhd.entity @root () -> () {
|
||||||
|
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
|
|
||||||
llhd.drv %intsig, %con after %time : !llhd.sig<i32>
|
llhd.drv %intsig, %con after %time : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,19 +99,19 @@ llhd.entity @root () -> () {
|
||||||
%0 = hw.constant 1 : i8
|
%0 = hw.constant 1 : i8
|
||||||
%s = llhd.sig "s" %0 : i8
|
%s = llhd.sig "s" %0 : i8
|
||||||
%1 = llhd.sig "1" %0 : i8
|
%1 = llhd.sig "1" %0 : i8
|
||||||
llhd.inst "foo" @foo () -> (%s) : () -> (!llhd.sig<i8>)
|
llhd.inst "foo" @foo () -> (%s) : () -> (!hw.inout<i8>)
|
||||||
}
|
}
|
||||||
|
|
||||||
llhd.proc @foo () -> (%s : !llhd.sig<i8>) {
|
llhd.proc @foo () -> (%s : !hw.inout<i8>) {
|
||||||
cf.br ^entry
|
cf.br ^entry
|
||||||
^entry:
|
^entry:
|
||||||
%1 = llhd.prb %s : !llhd.sig<i8>
|
%1 = llhd.prb %s : !hw.inout<i8>
|
||||||
%2 = comb.add %1, %1 : i8
|
%2 = comb.add %1, %1 : i8
|
||||||
%t0 = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
%t0 = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
||||||
llhd.drv %s, %2 after %t0 : !llhd.sig<i8>
|
llhd.drv %s, %2 after %t0 : !hw.inout<i8>
|
||||||
%3 = comb.add %2, %1 : i8
|
%3 = comb.add %2, %1 : i8
|
||||||
%t1 = llhd.constant_time #llhd.time<0ns, 0d, 2e>
|
%t1 = llhd.constant_time #llhd.time<0ns, 0d, 2e>
|
||||||
llhd.drv %s, %3 after %t1 : !llhd.sig<i8>
|
llhd.drv %s, %3 after %t1 : !hw.inout<i8>
|
||||||
%t2= llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%t2= llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
llhd.wait for %t2, ^entry
|
llhd.wait for %t2, ^entry
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ llhd.entity @root () -> () {
|
||||||
|
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
|
|
||||||
llhd.drv %concatsig, %array after %time : !llhd.sig<!hw.array<4xi8>>
|
llhd.drv %concatsig, %array after %time : !hw.inout<array<4xi8>>
|
||||||
llhd.drv %getsig, %get after %time : !llhd.sig<i8>
|
llhd.drv %getsig, %get after %time : !hw.inout<i8>
|
||||||
llhd.drv %slicesig, %slice after %time : !llhd.sig<!hw.array<2xi8>>
|
llhd.drv %slicesig, %slice after %time : !hw.inout<array<2xi8>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ llhd.entity @root () -> () {
|
||||||
|
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
|
|
||||||
llhd.drv %intsig, %0 after %time : !llhd.sig<!hw.array<2xi16>>
|
llhd.drv %intsig, %0 after %time : !hw.inout<array<2xi16>>
|
||||||
llhd.drv %arrsig, %1 after %time : !llhd.sig<i32>
|
llhd.drv %arrsig, %1 after %time : !hw.inout<i32>
|
||||||
llhd.drv %structsig, %2 after %time : !llhd.sig<i32>
|
llhd.drv %structsig, %2 after %time : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ llhd.entity @root () -> () {
|
||||||
|
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
|
|
||||||
llhd.drv %structsig, %0 after %time : !llhd.sig<i32>
|
llhd.drv %structsig, %0 after %time : !hw.inout<i32>
|
||||||
llhd.drv %extsig, %ext after %time : !llhd.sig<i8>
|
llhd.drv %extsig, %ext after %time : !hw.inout<i8>
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,19 +9,19 @@
|
||||||
llhd.entity @root () -> () {
|
llhd.entity @root () -> () {
|
||||||
%0 = hw.constant 1 : i1
|
%0 = hw.constant 1 : i1
|
||||||
%1 = llhd.sig "toggle" %0 : i1
|
%1 = llhd.sig "toggle" %0 : i1
|
||||||
llhd.inst "proc" @p () -> (%1) : () -> (!llhd.sig<i1>)
|
llhd.inst "proc" @p () -> (%1) : () -> (!hw.inout<i1>)
|
||||||
}
|
}
|
||||||
|
|
||||||
llhd.proc @p () -> (%a : !llhd.sig<i1>) {
|
llhd.proc @p () -> (%a : !hw.inout<i1>) {
|
||||||
cf.br ^wait
|
cf.br ^wait
|
||||||
^wait:
|
^wait:
|
||||||
%1 = llhd.prb %a : !llhd.sig<i1>
|
%1 = llhd.prb %a : !hw.inout<i1>
|
||||||
%allset = hw.constant 1 : i1
|
%allset = hw.constant 1 : i1
|
||||||
%0 = comb.xor %1, %allset : i1
|
%0 = comb.xor %1, %allset : i1
|
||||||
%wt = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%wt = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
llhd.wait for %wt, ^drive
|
llhd.wait for %wt, ^drive
|
||||||
^drive:
|
^drive:
|
||||||
%dt = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
%dt = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
||||||
llhd.drv %a, %0 after %dt : !llhd.sig<i1>
|
llhd.drv %a, %0 after %dt : !hw.inout<i1>
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ llhd.entity @root () -> () {
|
||||||
%s0 = llhd.sig "sig1" %c0 : i32
|
%s0 = llhd.sig "sig1" %c0 : i32
|
||||||
%s1 = llhd.sig "sig2" %c0 : i32
|
%s1 = llhd.sig "sig2" %c0 : i32
|
||||||
%c = llhd.sig "clock" %1 : i1
|
%c = llhd.sig "clock" %1 : i1
|
||||||
%p = llhd.prb %c : !llhd.sig<i1>
|
%p = llhd.prb %c : !hw.inout<i1>
|
||||||
%allset1 = hw.constant 1 : i1
|
%allset1 = hw.constant 1 : i1
|
||||||
%nc = comb.xor %p, %allset1 : i1
|
%nc = comb.xor %p, %allset1 : i1
|
||||||
llhd.drv %c, %nc after %t1 : !llhd.sig<i1>
|
llhd.drv %c, %nc after %t1 : !hw.inout<i1>
|
||||||
llhd.reg %s0, (%c0, "fall" %p after %0 : i32), (%c1, "rise" %p after %0 : i32), (%c2, "low" %p after %0 : i32), (%c3, "high" %p after %0 : i32) : !llhd.sig<i32>
|
llhd.reg %s0, (%c0, "fall" %p after %0 : i32), (%c1, "rise" %p after %0 : i32), (%c2, "low" %p after %0 : i32), (%c3, "high" %p after %0 : i32) : !hw.inout<i32>
|
||||||
%2 = llhd.prb %s1 : !llhd.sig<i32>
|
%2 = llhd.prb %s1 : !hw.inout<i32>
|
||||||
%allset32 = hw.constant -1 : i32
|
%allset32 = hw.constant -1 : i32
|
||||||
%3 = comb.xor %2, %allset32 : i32
|
%3 = comb.xor %2, %allset32 : i32
|
||||||
llhd.reg %s1, (%3, "both" %p after %0 : i32) : !llhd.sig<i32>
|
llhd.reg %s1, (%3, "both" %p after %0 : i32) : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,17 +24,17 @@ llhd.entity @root () -> () {
|
||||||
%amnt = hw.constant 1 : i4
|
%amnt = hw.constant 1 : i4
|
||||||
|
|
||||||
%sig = llhd.sig "shrs" %init : i4
|
%sig = llhd.sig "shrs" %init : i4
|
||||||
%prbd = llhd.prb %sig : !llhd.sig<i4>
|
%prbd = llhd.prb %sig : !hw.inout<i4>
|
||||||
%shrs = comb.shrs %prbd, %amnt : i4
|
%shrs = comb.shrs %prbd, %amnt : i4
|
||||||
llhd.drv %sig, %shrs after %time : !llhd.sig<i4>
|
llhd.drv %sig, %shrs after %time : !hw.inout<i4>
|
||||||
|
|
||||||
%sig1 = llhd.sig "shru" %init : i4
|
%sig1 = llhd.sig "shru" %init : i4
|
||||||
%prbd1 = llhd.prb %sig1 : !llhd.sig<i4>
|
%prbd1 = llhd.prb %sig1 : !hw.inout<i4>
|
||||||
%shru = comb.shru %prbd1, %amnt : i4
|
%shru = comb.shru %prbd1, %amnt : i4
|
||||||
llhd.drv %sig1, %shru after %time : !llhd.sig<i4>
|
llhd.drv %sig1, %shru after %time : !hw.inout<i4>
|
||||||
|
|
||||||
%sig2 = llhd.sig "shl" %init1 : i4
|
%sig2 = llhd.sig "shl" %init1 : i4
|
||||||
%prbd2 = llhd.prb %sig2 : !llhd.sig<i4>
|
%prbd2 = llhd.prb %sig2 : !hw.inout<i4>
|
||||||
%shl = comb.shl %prbd2, %amnt : i4
|
%shl = comb.shl %prbd2, %amnt : i4
|
||||||
llhd.drv %sig2, %shl after %time : !llhd.sig<i4>
|
llhd.drv %sig2, %shl after %time : !hw.inout<i4>
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
llhd.entity @Foo () -> () {
|
llhd.entity @Foo () -> () {
|
||||||
%0 = hw.constant 0 : i1
|
%0 = hw.constant 0 : i1
|
||||||
%toggle = llhd.sig "toggle" %0 : i1
|
%toggle = llhd.sig "toggle" %0 : i1
|
||||||
%1 = llhd.prb %toggle : !llhd.sig<i1>
|
%1 = llhd.prb %toggle : !hw.inout<i1>
|
||||||
%allset = hw.constant 1 : i1
|
%allset = hw.constant 1 : i1
|
||||||
%2 = comb.xor %1, %allset : i1
|
%2 = comb.xor %1, %allset : i1
|
||||||
%dt = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%dt = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
llhd.drv %toggle, %2 after %dt : !llhd.sig<i1>
|
llhd.drv %toggle, %2 after %dt : !hw.inout<i1>
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,10 @@ llhd.entity @root () -> () {
|
||||||
%0 = hw.constant 0 : i32
|
%0 = hw.constant 0 : i32
|
||||||
%1 = llhd.sig "s1" %0 : i32
|
%1 = llhd.sig "s1" %0 : i32
|
||||||
%2 = llhd.sig "s2" %0 : i32
|
%2 = llhd.sig "s2" %0 : i32
|
||||||
llhd.inst "proc" @proc () -> (%1, %2) : () -> (!llhd.sig<i32>, !llhd.sig<i32>)
|
llhd.inst "proc" @proc () -> (%1, %2) : () -> (!hw.inout<i32>, !hw.inout<i32>)
|
||||||
}
|
}
|
||||||
|
|
||||||
llhd.proc @proc () -> (%a : !llhd.sig<i32>, %b : !llhd.sig<i32>) {
|
llhd.proc @proc () -> (%a : !hw.inout<i32>, %b : !hw.inout<i32>) {
|
||||||
cf.br ^timed
|
cf.br ^timed
|
||||||
^timed:
|
^timed:
|
||||||
%t1 = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
%t1 = llhd.constant_time #llhd.time<0ns, 0d, 1e>
|
||||||
|
@ -35,32 +35,32 @@ llhd.proc @proc () -> (%a : !llhd.sig<i32>, %b : !llhd.sig<i32>) {
|
||||||
llhd.wait for %t1, ^observe
|
llhd.wait for %t1, ^observe
|
||||||
^observe:
|
^observe:
|
||||||
%c0 = hw.constant 1 : i32
|
%c0 = hw.constant 1 : i32
|
||||||
%p0 = llhd.prb %b : !llhd.sig<i32>
|
%p0 = llhd.prb %b : !hw.inout<i32>
|
||||||
%a0 = comb.add %c0, %p0 : i32
|
%a0 = comb.add %c0, %p0 : i32
|
||||||
llhd.drv %a, %a0 after %t1 : !llhd.sig<i32>
|
llhd.drv %a, %a0 after %t1 : !hw.inout<i32>
|
||||||
llhd.drv %b, %a0 after %t2 : !llhd.sig<i32>
|
llhd.drv %b, %a0 after %t2 : !hw.inout<i32>
|
||||||
llhd.wait (%b : !llhd.sig<i32>), ^timed_observe
|
llhd.wait (%b : !hw.inout<i32>), ^timed_observe
|
||||||
^timed_observe:
|
^timed_observe:
|
||||||
%p1 = llhd.prb %b : !llhd.sig<i32>
|
%p1 = llhd.prb %b : !hw.inout<i32>
|
||||||
%a1 = comb.add %c0, %p1 : i32
|
%a1 = comb.add %c0, %p1 : i32
|
||||||
llhd.drv %b, %a1 after %t1 : !llhd.sig<i32>
|
llhd.drv %b, %a1 after %t1 : !hw.inout<i32>
|
||||||
llhd.wait for %t2, (%b : !llhd.sig<i32>), ^overlap_invalidated
|
llhd.wait for %t2, (%b : !hw.inout<i32>), ^overlap_invalidated
|
||||||
^overlap_invalidated:
|
^overlap_invalidated:
|
||||||
%p2 = llhd.prb %b : !llhd.sig<i32>
|
%p2 = llhd.prb %b : !hw.inout<i32>
|
||||||
%a2 = comb.add %c0, %p2 : i32
|
%a2 = comb.add %c0, %p2 : i32
|
||||||
llhd.drv %b, %a2 after %t1 : !llhd.sig<i32>
|
llhd.drv %b, %a2 after %t1 : !hw.inout<i32>
|
||||||
llhd.wait for %t2, ^observe_both
|
llhd.wait for %t2, ^observe_both
|
||||||
^observe_both:
|
^observe_both:
|
||||||
%p3 = llhd.prb %b : !llhd.sig<i32>
|
%p3 = llhd.prb %b : !hw.inout<i32>
|
||||||
%a3 = comb.add %c0, %p3 : i32
|
%a3 = comb.add %c0, %p3 : i32
|
||||||
llhd.drv %a, %a3 after %t2 : !llhd.sig<i32>
|
llhd.drv %a, %a3 after %t2 : !hw.inout<i32>
|
||||||
llhd.drv %b, %a3 after %t1 : !llhd.sig<i32>
|
llhd.drv %b, %a3 after %t1 : !hw.inout<i32>
|
||||||
llhd.wait (%a, %b : !llhd.sig<i32>, !llhd.sig<i32>), ^blockArgs
|
llhd.wait (%a, %b : !hw.inout<i32>, !hw.inout<i32>), ^blockArgs
|
||||||
^blockArgs:
|
^blockArgs:
|
||||||
%p4 = llhd.prb %b : !llhd.sig<i32>
|
%p4 = llhd.prb %b : !hw.inout<i32>
|
||||||
%a4 = comb.add %c0, %p4 : i32
|
%a4 = comb.add %c0, %p4 : i32
|
||||||
llhd.wait (%a, %b : !llhd.sig<i32>, !llhd.sig<i32>), ^end(%a4 : i32)
|
llhd.wait (%a, %b : !hw.inout<i32>, !hw.inout<i32>), ^end(%a4 : i32)
|
||||||
^end (%arg : i32):
|
^end (%arg : i32):
|
||||||
llhd.drv %b, %arg after %t2 : !llhd.sig<i32>
|
llhd.drv %b, %arg after %t2 : !hw.inout<i32>
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
// RUN: circt-opt %s -llhd-early-code-motion | FileCheck %s
|
// RUN: circt-opt %s -llhd-early-code-motion | FileCheck %s
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.proc @check_dont_move_sideeffect() -> (
|
// CHECK-LABEL: llhd.proc @check_dont_move_sideeffect() -> (
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i32>) {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i32>) {
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
||||||
// CHECK: %[[VAL_2:.*]] = llhd.constant_time <1ns, 0d, 0e>
|
// CHECK: %[[VAL_2:.*]] = llhd.constant_time <1ns, 0d, 0e>
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb1:
|
// CHECK: ^bb1:
|
||||||
// CHECK: %[[VAL_3:.*]] = llhd.var %[[VAL_1]] : i32
|
// CHECK: %[[VAL_3:.*]] = llhd.var %[[VAL_1]] : i32
|
||||||
// CHECK: llhd.drv %[[VAL_0]], %[[VAL_1]] after %[[VAL_2]] : !llhd.sig<i32>
|
// CHECK: llhd.drv %[[VAL_0]], %[[VAL_1]] after %[[VAL_2]] : !hw.inout<i32>
|
||||||
// CHECK: cf.br ^bb2
|
// CHECK: cf.br ^bb2
|
||||||
// CHECK: ^bb2:
|
// CHECK: ^bb2:
|
||||||
// CHECK: %[[VAL_4:.*]] = llhd.load %[[VAL_3]] : !llhd.ptr<i32>
|
// CHECK: %[[VAL_4:.*]] = llhd.load %[[VAL_3]] : !llhd.ptr<i32>
|
||||||
// CHECK: llhd.store %[[VAL_3]], %[[VAL_1]] : !llhd.ptr<i32>
|
// CHECK: llhd.store %[[VAL_3]], %[[VAL_1]] : !llhd.ptr<i32>
|
||||||
// CHECK: llhd.halt
|
// CHECK: llhd.halt
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @check_dont_move_sideeffect() -> (%sig : !llhd.sig<i32>) {
|
llhd.proc @check_dont_move_sideeffect() -> (%sig : !hw.inout<i32>) {
|
||||||
// TR: -1
|
// TR: -1
|
||||||
%c = hw.constant 4 : i32
|
%c = hw.constant 4 : i32
|
||||||
%time = llhd.constant_time <1ns, 0d, 0e>
|
%time = llhd.constant_time <1ns, 0d, 0e>
|
||||||
|
@ -23,7 +23,7 @@ llhd.proc @check_dont_move_sideeffect() -> (%sig : !llhd.sig<i32>) {
|
||||||
^bb1:
|
^bb1:
|
||||||
// TR: -1
|
// TR: -1
|
||||||
%ptr = llhd.var %c : i32
|
%ptr = llhd.var %c : i32
|
||||||
llhd.drv %sig, %c after %time : !llhd.sig<i32>
|
llhd.drv %sig, %c after %time : !hw.inout<i32>
|
||||||
cf.br ^bb2
|
cf.br ^bb2
|
||||||
^bb2:
|
^bb2:
|
||||||
// TR: -1
|
// TR: -1
|
||||||
|
@ -36,70 +36,70 @@ llhd.proc @check_dont_move_sideeffect() -> (%sig : !llhd.sig<i32>) {
|
||||||
// not if one predecessor has a wait terminator, but side-effect-free operations
|
// not if one predecessor has a wait terminator, but side-effect-free operations
|
||||||
// are moved freely
|
// are moved freely
|
||||||
// CHECK-LABEL: llhd.proc @check_move_prb1(
|
// CHECK-LABEL: llhd.proc @check_move_prb1(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i32>) -> () {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i32>) -> () {
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
||||||
// CHECK: %[[VAL_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
|
// CHECK: %[[VAL_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb1:
|
// CHECK: ^bb1:
|
||||||
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
|
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
|
||||||
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
|
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
|
||||||
// CHECK: cf.br ^bb2
|
// CHECK: cf.br ^bb2
|
||||||
// CHECK: ^bb2:
|
// CHECK: ^bb2:
|
||||||
// CHECK: llhd.wait ^bb1
|
// CHECK: llhd.wait ^bb1
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @check_move_prb1(%sig : !llhd.sig<i32>) -> () {
|
llhd.proc @check_move_prb1(%sig : !hw.inout<i32>) -> () {
|
||||||
// TR: -1
|
// TR: -1
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
%c = hw.constant 4 : i32
|
%c = hw.constant 4 : i32
|
||||||
%prb1 = llhd.prb %sig : !llhd.sig<i32>
|
%prb1 = llhd.prb %sig : !hw.inout<i32>
|
||||||
cf.br ^bb2
|
cf.br ^bb2
|
||||||
^bb2:
|
^bb2:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
%double = comb.add %c, %c : i32
|
%double = comb.add %c, %c : i32
|
||||||
%prb2 = llhd.prb %sig : !llhd.sig<i32>
|
%prb2 = llhd.prb %sig : !hw.inout<i32>
|
||||||
llhd.wait ^bb1
|
llhd.wait ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that prb is not moved to predecessor if not all predecessors are in
|
// Checks that prb is not moved to predecessor if not all predecessors are in
|
||||||
// the same TR, but side-effect-free operations are moved freely
|
// the same TR, but side-effect-free operations are moved freely
|
||||||
// CHECK-LABEL: llhd.proc @check_move_prb2(
|
// CHECK-LABEL: llhd.proc @check_move_prb2(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i32>) -> () {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i32>) -> () {
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
||||||
// CHECK: %[[VAL_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
|
// CHECK: %[[VAL_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb1:
|
// CHECK: ^bb1:
|
||||||
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
|
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
|
||||||
// CHECK: llhd.wait ^bb2
|
// CHECK: llhd.wait ^bb2
|
||||||
// CHECK: ^bb2:
|
// CHECK: ^bb2:
|
||||||
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
|
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @check_move_prb2(%sig : !llhd.sig<i32>) -> () {
|
llhd.proc @check_move_prb2(%sig : !hw.inout<i32>) -> () {
|
||||||
// TR: -1
|
// TR: -1
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
// TR: 1
|
// TR: 1
|
||||||
%c = hw.constant 4 : i32
|
%c = hw.constant 4 : i32
|
||||||
%prb1 = llhd.prb %sig : !llhd.sig<i32>
|
%prb1 = llhd.prb %sig : !hw.inout<i32>
|
||||||
llhd.wait ^bb2
|
llhd.wait ^bb2
|
||||||
^bb2:
|
^bb2:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
%double = comb.add %c, %c : i32
|
%double = comb.add %c, %c : i32
|
||||||
%prb2 = llhd.prb %sig : !llhd.sig<i32>
|
%prb2 = llhd.prb %sig : !hw.inout<i32>
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.proc @check_blockarg(
|
// CHECK-LABEL: llhd.proc @check_blockarg(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i32>) -> () {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i32>) -> () {
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 4 : i32
|
||||||
// CHECK: cf.br ^bb1(%[[VAL_1]] : i32)
|
// CHECK: cf.br ^bb1(%[[VAL_1]] : i32)
|
||||||
// CHECK: ^bb1(%[[VAL_2:.*]]: i32):
|
// CHECK: ^bb1(%[[VAL_2:.*]]: i32):
|
||||||
// CHECK: %[[VAL_3:.*]] = comb.add %[[VAL_2]], %[[VAL_2]] : i32
|
// CHECK: %[[VAL_3:.*]] = comb.add %[[VAL_2]], %[[VAL_2]] : i32
|
||||||
// CHECK: llhd.halt
|
// CHECK: llhd.halt
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
|
llhd.proc @check_blockarg(%sig : !hw.inout<i32>) -> () {
|
||||||
// TR: -1
|
// TR: -1
|
||||||
%c = hw.constant 4 : i32
|
%c = hw.constant 4 : i32
|
||||||
cf.br ^bb1(%c : i32)
|
cf.br ^bb1(%c : i32)
|
||||||
|
@ -110,7 +110,7 @@ llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.proc @loop(
|
// CHECK-LABEL: llhd.proc @loop(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i2>) -> () {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i2>) -> () {
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
||||||
// CHECK: %[[VAL_2:.*]] = hw.constant 2 : i32
|
// CHECK: %[[VAL_2:.*]] = hw.constant 2 : i32
|
||||||
// CHECK: %[[VAL_3:.*]] = hw.constant 0 : i2
|
// CHECK: %[[VAL_3:.*]] = hw.constant 0 : i2
|
||||||
|
@ -122,17 +122,17 @@ llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
|
||||||
// CHECK: ^bb2:
|
// CHECK: ^bb2:
|
||||||
// CHECK: %[[VAL_6:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
|
// CHECK: %[[VAL_6:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
|
||||||
// CHECK: %[[VAL_7:.*]] = comb.icmp ult %[[VAL_6]], %[[VAL_2]] : i32
|
// CHECK: %[[VAL_7:.*]] = comb.icmp ult %[[VAL_6]], %[[VAL_2]] : i32
|
||||||
// CHECK: %[[VAL_8:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i2>
|
// CHECK: %[[VAL_8:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i2>
|
||||||
// CHECK: cf.cond_br %[[VAL_7]], ^bb4, ^bb3
|
// CHECK: cf.cond_br %[[VAL_7]], ^bb4, ^bb3
|
||||||
// CHECK: ^bb3:
|
// CHECK: ^bb3:
|
||||||
// CHECK: llhd.wait (%[[VAL_0]] : !llhd.sig<i2>), ^bb1
|
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^bb1
|
||||||
// CHECK: ^bb4:
|
// CHECK: ^bb4:
|
||||||
// CHECK: %[[VAL_9:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
|
// CHECK: %[[VAL_9:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
|
||||||
// CHECK: %[[VAL_10:.*]] = comb.add %[[VAL_9]], %[[VAL_4]] : i32
|
// CHECK: %[[VAL_10:.*]] = comb.add %[[VAL_9]], %[[VAL_4]] : i32
|
||||||
// CHECK: llhd.store %[[VAL_5]], %[[VAL_10]] : !llhd.ptr<i32>
|
// CHECK: llhd.store %[[VAL_5]], %[[VAL_10]] : !llhd.ptr<i32>
|
||||||
// CHECK: cf.br ^bb2
|
// CHECK: cf.br ^bb2
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
|
llhd.proc @loop(%in_i : !hw.inout<i2>) -> () {
|
||||||
// TR: -1
|
// TR: -1
|
||||||
cf.br ^body
|
cf.br ^body
|
||||||
^body:
|
^body:
|
||||||
|
@ -148,12 +148,12 @@ llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
|
||||||
cf.cond_br %2, ^loop_continue, ^check
|
cf.cond_br %2, ^loop_continue, ^check
|
||||||
^check:
|
^check:
|
||||||
// TR: 1
|
// TR: 1
|
||||||
llhd.wait (%in_i : !llhd.sig<i2>), ^body
|
llhd.wait (%in_i : !hw.inout<i2>), ^body
|
||||||
^loop_continue:
|
^loop_continue:
|
||||||
// TR: 1
|
// TR: 1
|
||||||
%3 = hw.constant 0 : i2
|
%3 = hw.constant 0 : i2
|
||||||
%5 = hw.constant 1 : i32
|
%5 = hw.constant 1 : i32
|
||||||
%prb = llhd.prb %in_i : !llhd.sig<i2>
|
%prb = llhd.prb %in_i : !hw.inout<i2>
|
||||||
%i_ld4 = llhd.load %i : !llhd.ptr<i32>
|
%i_ld4 = llhd.load %i : !llhd.ptr<i32>
|
||||||
%14 = comb.add %i_ld4, %5 : i32
|
%14 = comb.add %i_ld4, %5 : i32
|
||||||
llhd.store %i, %14 : !llhd.ptr<i32>
|
llhd.store %i, %14 : !llhd.ptr<i32>
|
||||||
|
@ -161,74 +161,74 @@ llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.proc @complicated(
|
// CHECK-LABEL: llhd.proc @complicated(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i1>, %[[VAL_1:.*]] : !llhd.sig<i1>, %[[VAL_2:.*]] : !llhd.sig<i1>) -> (%[[VAL_3:.*]] : !llhd.sig<i1>, %[[VAL_4:.*]] : !llhd.sig<i1>) {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i1>, %[[VAL_1:.*]] : !hw.inout<i1>, %[[VAL_2:.*]] : !hw.inout<i1>) -> (%[[VAL_3:.*]] : !hw.inout<i1>, %[[VAL_4:.*]] : !hw.inout<i1>) {
|
||||||
// CHECK: %[[ALLSET:.*]] = hw.constant true
|
// CHECK: %[[ALLSET:.*]] = hw.constant true
|
||||||
// CHECK: %[[VAL_5:.*]] = hw.constant false
|
// CHECK: %[[VAL_5:.*]] = hw.constant false
|
||||||
// CHECK: %[[VAL_6:.*]] = llhd.constant_time <0s, 1d, 0e>
|
// CHECK: %[[VAL_6:.*]] = llhd.constant_time <0s, 1d, 0e>
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb1:
|
// CHECK: ^bb1:
|
||||||
// CHECK: %[[VAL_7:.*]] = llhd.prb %[[VAL_3]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_7:.*]] = llhd.prb %[[VAL_3]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_8:.*]] = llhd.var %[[VAL_7]] : i1
|
// CHECK: %[[VAL_8:.*]] = llhd.var %[[VAL_7]] : i1
|
||||||
// CHECK: cf.br ^bb2
|
// CHECK: cf.br ^bb2
|
||||||
// CHECK: ^bb2:
|
// CHECK: ^bb2:
|
||||||
// CHECK: %[[VAL_9:.*]] = llhd.prb %[[VAL_1]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_9:.*]] = llhd.prb %[[VAL_1]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_10:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_10:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_11:.*]] = comb.icmp eq %[[VAL_9]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_11:.*]] = comb.icmp eq %[[VAL_9]], %[[VAL_5]] : i1
|
||||||
// CHECK: %[[VAL_12:.*]] = comb.icmp ne %[[VAL_10]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_12:.*]] = comb.icmp ne %[[VAL_10]], %[[VAL_5]] : i1
|
||||||
// CHECK: llhd.wait (%[[VAL_1]], %[[VAL_0]] : !llhd.sig<i1>, !llhd.sig<i1>), ^bb3
|
// CHECK: llhd.wait (%[[VAL_1]], %[[VAL_0]] : !hw.inout<i1>, !hw.inout<i1>), ^bb3
|
||||||
// CHECK: ^bb3:
|
// CHECK: ^bb3:
|
||||||
// CHECK: %[[VAL_13:.*]] = llhd.prb %[[VAL_3]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_13:.*]] = llhd.prb %[[VAL_3]] : !hw.inout<i1>
|
||||||
// CHECK: llhd.store %[[VAL_8]], %[[VAL_13]] : !llhd.ptr<i1>
|
// CHECK: llhd.store %[[VAL_8]], %[[VAL_13]] : !llhd.ptr<i1>
|
||||||
// CHECK: llhd.store %[[VAL_8]], %[[VAL_13]] : !llhd.ptr<i1>
|
// CHECK: llhd.store %[[VAL_8]], %[[VAL_13]] : !llhd.ptr<i1>
|
||||||
// CHECK: %[[VAL_14:.*]] = llhd.prb %[[VAL_1]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_14:.*]] = llhd.prb %[[VAL_1]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_15:.*]] = comb.icmp ne %[[VAL_14]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_15:.*]] = comb.icmp ne %[[VAL_14]], %[[VAL_5]] : i1
|
||||||
// CHECK: %[[VAL_16:.*]] = comb.and %[[VAL_11]], %[[VAL_15]] : i1
|
// CHECK: %[[VAL_16:.*]] = comb.and %[[VAL_11]], %[[VAL_15]] : i1
|
||||||
// CHECK: %[[VAL_17:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_17:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_18:.*]] = comb.icmp eq %[[VAL_17]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_18:.*]] = comb.icmp eq %[[VAL_17]], %[[VAL_5]] : i1
|
||||||
// CHECK: %[[VAL_19:.*]] = comb.and %[[VAL_18]], %[[VAL_12]] : i1
|
// CHECK: %[[VAL_19:.*]] = comb.and %[[VAL_18]], %[[VAL_12]] : i1
|
||||||
// CHECK: %[[VAL_20:.*]] = comb.or %[[VAL_16]], %[[VAL_19]] : i1
|
// CHECK: %[[VAL_20:.*]] = comb.or %[[VAL_16]], %[[VAL_19]] : i1
|
||||||
// CHECK: %[[VAL_21:.*]] = comb.icmp ne %[[VAL_17]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_21:.*]] = comb.icmp ne %[[VAL_17]], %[[VAL_5]] : i1
|
||||||
// CHECK: %[[VAL_22:.*]] = comb.xor %[[VAL_21]], %[[ALLSET]] : i1
|
// CHECK: %[[VAL_22:.*]] = comb.xor %[[VAL_21]], %[[ALLSET]] : i1
|
||||||
// CHECK: %[[VAL_23:.*]] = comb.icmp ne %[[VAL_22]], %[[VAL_5]] : i1
|
// CHECK: %[[VAL_23:.*]] = comb.icmp ne %[[VAL_22]], %[[VAL_5]] : i1
|
||||||
// CHECK: %[[VAL_24:.*]] = llhd.prb %[[VAL_2]] : !llhd.sig<i1>
|
// CHECK: %[[VAL_24:.*]] = llhd.prb %[[VAL_2]] : !hw.inout<i1>
|
||||||
// CHECK: cf.cond_br %[[VAL_20]], ^bb4, ^bb2
|
// CHECK: cf.cond_br %[[VAL_20]], ^bb4, ^bb2
|
||||||
// CHECK: ^bb4:
|
// CHECK: ^bb4:
|
||||||
// CHECK: cf.cond_br %[[VAL_23]], ^bb6, ^bb5
|
// CHECK: cf.cond_br %[[VAL_23]], ^bb6, ^bb5
|
||||||
// CHECK: ^bb5:
|
// CHECK: ^bb5:
|
||||||
// CHECK: llhd.drv %[[VAL_3]], %[[VAL_24]] after %[[VAL_6]] : !llhd.sig<i1>
|
// CHECK: llhd.drv %[[VAL_3]], %[[VAL_24]] after %[[VAL_6]] : !hw.inout<i1>
|
||||||
// CHECK: %[[VAL_25:.*]] = llhd.load %[[VAL_8]] : !llhd.ptr<i1>
|
// CHECK: %[[VAL_25:.*]] = llhd.load %[[VAL_8]] : !llhd.ptr<i1>
|
||||||
// CHECK: llhd.drv %[[VAL_4]], %[[VAL_25]] after %[[VAL_6]] : !llhd.sig<i1>
|
// CHECK: llhd.drv %[[VAL_4]], %[[VAL_25]] after %[[VAL_6]] : !hw.inout<i1>
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb6:
|
// CHECK: ^bb6:
|
||||||
// CHECK: llhd.drv %[[VAL_3]], %[[VAL_5]] after %[[VAL_6]] : !llhd.sig<i1>
|
// CHECK: llhd.drv %[[VAL_3]], %[[VAL_5]] after %[[VAL_6]] : !hw.inout<i1>
|
||||||
// CHECK: llhd.drv %[[VAL_4]], %[[VAL_5]] after %[[VAL_6]] : !llhd.sig<i1>
|
// CHECK: llhd.drv %[[VAL_4]], %[[VAL_5]] after %[[VAL_6]] : !hw.inout<i1>
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @complicated(%rst_ni: !llhd.sig<i1>, %clk_i: !llhd.sig<i1>, %async_ack_i: !llhd.sig<i1>) -> (%ack_src_q: !llhd.sig<i1> , %ack_q: !llhd.sig<i1> ) {
|
llhd.proc @complicated(%rst_ni: !hw.inout<i1>, %clk_i: !hw.inout<i1>, %async_ack_i: !hw.inout<i1>) -> (%ack_src_q: !hw.inout<i1> , %ack_q: !hw.inout<i1> ) {
|
||||||
%allset = hw.constant 1 : i1
|
%allset = hw.constant 1 : i1
|
||||||
// TR: -1
|
// TR: -1
|
||||||
cf.br ^0
|
cf.br ^0
|
||||||
^0:
|
^0:
|
||||||
// TR: 1
|
// TR: 1
|
||||||
%1 = llhd.prb %ack_src_q : !llhd.sig<i1>
|
%1 = llhd.prb %ack_src_q : !hw.inout<i1>
|
||||||
%ack_src_q_shadow = llhd.var %1 : i1
|
%ack_src_q_shadow = llhd.var %1 : i1
|
||||||
cf.br ^init
|
cf.br ^init
|
||||||
^init:
|
^init:
|
||||||
// TR: 2
|
// TR: 2
|
||||||
%clk_i_prb = llhd.prb %clk_i : !llhd.sig<i1>
|
%clk_i_prb = llhd.prb %clk_i : !hw.inout<i1>
|
||||||
%rst_ni_prb = llhd.prb %rst_ni : !llhd.sig<i1>
|
%rst_ni_prb = llhd.prb %rst_ni : !hw.inout<i1>
|
||||||
llhd.wait (%clk_i, %rst_ni : !llhd.sig<i1>, !llhd.sig<i1>), ^check
|
llhd.wait (%clk_i, %rst_ni : !hw.inout<i1>, !hw.inout<i1>), ^check
|
||||||
^check:
|
^check:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
%2 = llhd.prb %ack_src_q : !llhd.sig<i1>
|
%2 = llhd.prb %ack_src_q : !hw.inout<i1>
|
||||||
llhd.store %ack_src_q_shadow, %2 : !llhd.ptr<i1>
|
llhd.store %ack_src_q_shadow, %2 : !llhd.ptr<i1>
|
||||||
llhd.store %ack_src_q_shadow, %2 : !llhd.ptr<i1>
|
llhd.store %ack_src_q_shadow, %2 : !llhd.ptr<i1>
|
||||||
%clk_i_prb1 = llhd.prb %clk_i : !llhd.sig<i1>
|
%clk_i_prb1 = llhd.prb %clk_i : !hw.inout<i1>
|
||||||
%3 = hw.constant 0 : i1
|
%3 = hw.constant 0 : i1
|
||||||
%4 = comb.icmp eq %clk_i_prb, %3 : i1
|
%4 = comb.icmp eq %clk_i_prb, %3 : i1
|
||||||
%5 = comb.icmp ne %clk_i_prb1, %3 : i1
|
%5 = comb.icmp ne %clk_i_prb1, %3 : i1
|
||||||
%posedge = comb.and %4, %5 : i1
|
%posedge = comb.and %4, %5 : i1
|
||||||
%rst_ni_prb1 = llhd.prb %rst_ni : !llhd.sig<i1>
|
%rst_ni_prb1 = llhd.prb %rst_ni : !hw.inout<i1>
|
||||||
%6 = comb.icmp ne %rst_ni_prb, %3 : i1
|
%6 = comb.icmp ne %rst_ni_prb, %3 : i1
|
||||||
%7 = comb.icmp eq %rst_ni_prb1, %3 : i1
|
%7 = comb.icmp eq %rst_ni_prb1, %3 : i1
|
||||||
%negedge = comb.and %7, %6 : i1
|
%negedge = comb.and %7, %6 : i1
|
||||||
|
@ -243,14 +243,14 @@ llhd.proc @complicated(%rst_ni: !llhd.sig<i1>, %clk_i: !llhd.sig<i1>, %async_ack
|
||||||
cf.cond_br %10, ^if_true, ^if_false
|
cf.cond_br %10, ^if_true, ^if_false
|
||||||
^if_false:
|
^if_false:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
%async_ack_i_prb = llhd.prb %async_ack_i : !llhd.sig<i1>
|
%async_ack_i_prb = llhd.prb %async_ack_i : !hw.inout<i1>
|
||||||
llhd.drv %ack_src_q, %async_ack_i_prb after %11 : !llhd.sig<i1>
|
llhd.drv %ack_src_q, %async_ack_i_prb after %11 : !hw.inout<i1>
|
||||||
%ack_src_q_shadow_ld = llhd.load %ack_src_q_shadow : !llhd.ptr<i1>
|
%ack_src_q_shadow_ld = llhd.load %ack_src_q_shadow : !llhd.ptr<i1>
|
||||||
llhd.drv %ack_q, %ack_src_q_shadow_ld after %11 : !llhd.sig<i1>
|
llhd.drv %ack_q, %ack_src_q_shadow_ld after %11 : !hw.inout<i1>
|
||||||
cf.br ^0
|
cf.br ^0
|
||||||
^if_true:
|
^if_true:
|
||||||
// TR: 0
|
// TR: 0
|
||||||
llhd.drv %ack_src_q, %3 after %11 : !llhd.sig<i1>
|
llhd.drv %ack_src_q, %3 after %11 : !hw.inout<i1>
|
||||||
llhd.drv %ack_q, %3 after %11 : !llhd.sig<i1>
|
llhd.drv %ack_q, %3 after %11 : !hw.inout<i1>
|
||||||
cf.br ^0
|
cf.br ^0
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,7 @@ llhd.proc @multiple_store_one_block() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: llhd.proc @loop(
|
// CHECK-LABEL: llhd.proc @loop(
|
||||||
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i2>) -> () {
|
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i2>) -> () {
|
||||||
// CHECK: cf.br ^bb1
|
// CHECK: cf.br ^bb1
|
||||||
// CHECK: ^bb1:
|
// CHECK: ^bb1:
|
||||||
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
||||||
|
@ -257,14 +257,14 @@ llhd.proc @multiple_store_one_block() -> () {
|
||||||
// CHECK: %[[VAL_4:.*]] = comb.icmp ult %[[VAL_2]], %[[VAL_3]] : i32
|
// CHECK: %[[VAL_4:.*]] = comb.icmp ult %[[VAL_2]], %[[VAL_3]] : i32
|
||||||
// CHECK: cf.cond_br %[[VAL_4]], ^bb4, ^bb3
|
// CHECK: cf.cond_br %[[VAL_4]], ^bb4, ^bb3
|
||||||
// CHECK: ^bb3:
|
// CHECK: ^bb3:
|
||||||
// CHECK: llhd.wait (%[[VAL_0]] : !llhd.sig<i2>), ^bb1
|
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^bb1
|
||||||
// CHECK: ^bb4:
|
// CHECK: ^bb4:
|
||||||
// CHECK: %[[VAL_5:.*]] = hw.constant 0 : i2
|
// CHECK: %[[VAL_5:.*]] = hw.constant 0 : i2
|
||||||
// CHECK: %[[VAL_6:.*]] = hw.constant 1 : i32
|
// CHECK: %[[VAL_6:.*]] = hw.constant 1 : i32
|
||||||
// CHECK: %[[VAL_7:.*]] = comb.add %[[VAL_2]], %[[VAL_6]] : i32
|
// CHECK: %[[VAL_7:.*]] = comb.add %[[VAL_2]], %[[VAL_6]] : i32
|
||||||
// CHECK: cf.br ^bb2(%[[VAL_7]] : i32)
|
// CHECK: cf.br ^bb2(%[[VAL_7]] : i32)
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
|
llhd.proc @loop(%in_i : !hw.inout<i2>) -> () {
|
||||||
cf.br ^body
|
cf.br ^body
|
||||||
^body:
|
^body:
|
||||||
%0 = hw.constant 0 : i32
|
%0 = hw.constant 0 : i32
|
||||||
|
@ -276,7 +276,7 @@ llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
|
||||||
%2 = comb.icmp ult %i_ld, %1 : i32
|
%2 = comb.icmp ult %i_ld, %1 : i32
|
||||||
cf.cond_br %2, ^loop_continue, ^check
|
cf.cond_br %2, ^loop_continue, ^check
|
||||||
^check:
|
^check:
|
||||||
llhd.wait (%in_i : !llhd.sig<i2>), ^body
|
llhd.wait (%in_i : !hw.inout<i2>), ^body
|
||||||
^loop_continue:
|
^loop_continue:
|
||||||
%3 = hw.constant 0 : i2
|
%3 = hw.constant 0 : i2
|
||||||
%5 = hw.constant 1 : i32
|
%5 = hw.constant 1 : i32
|
||||||
|
|
|
@ -8,8 +8,8 @@ llhd.proc @empty() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that input and output signals are transferred correctly
|
// check that input and output signals are transferred correctly
|
||||||
// CHECK-NEXT: llhd.entity @inputAndOutput (%{{.*}} : !llhd.sig<i64>, %{{.*}} : !llhd.sig<i1>) -> (%{{.*}} : !llhd.sig<i1>) {
|
// CHECK-NEXT: llhd.entity @inputAndOutput (%{{.*}} : !hw.inout<i64>, %{{.*}} : !hw.inout<i1>) -> (%{{.*}} : !hw.inout<i1>) {
|
||||||
llhd.proc @inputAndOutput(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i1>) -> (%arg2 : !llhd.sig<i1>) {
|
llhd.proc @inputAndOutput(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i1>) -> (%arg2 : !hw.inout<i1>) {
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
@ -24,29 +24,29 @@ llhd.proc @simpleWait() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check wait with observing probed signals
|
// Check wait with observing probed signals
|
||||||
// CHECK-NEXT: llhd.entity @prbAndWait (%{{.*}} : !llhd.sig<i64>) -> () {
|
// CHECK-NEXT: llhd.entity @prbAndWait (%{{.*}} : !hw.inout<i64>) -> () {
|
||||||
llhd.proc @prbAndWait(%arg0 : !llhd.sig<i64>) -> () {
|
llhd.proc @prbAndWait(%arg0 : !hw.inout<i64>) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
%0 = llhd.prb %arg0 : !llhd.sig<i64>
|
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||||
llhd.wait (%arg0 : !llhd.sig<i64>), ^bb1
|
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check wait with observing probed signals
|
// Check wait with observing probed signals
|
||||||
// CHECK-NEXT: llhd.entity @prbAndWaitMoreObserved (%{{.*}} : !llhd.sig<i64>, %{{.*}} : !llhd.sig<i64>) -> () {
|
// CHECK-NEXT: llhd.entity @prbAndWaitMoreObserved (%{{.*}} : !hw.inout<i64>, %{{.*}} : !hw.inout<i64>) -> () {
|
||||||
llhd.proc @prbAndWaitMoreObserved(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
|
llhd.proc @prbAndWaitMoreObserved(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
%0 = llhd.prb %arg0 : !llhd.sig<i64>
|
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||||
llhd.wait (%arg0, %arg1 : !llhd.sig<i64>, !llhd.sig<i64>), ^bb1
|
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.entity @muxedSignal
|
// CHECK-NEXT: llhd.entity @muxedSignal
|
||||||
llhd.proc @muxedSignal(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
|
llhd.proc @muxedSignal(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>) -> () {
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||||
|
@ -54,13 +54,13 @@ llhd.proc @muxedSignal(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
%cond = hw.constant true
|
%cond = hw.constant true
|
||||||
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
|
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||||
%0 = llhd.prb %sig : !llhd.sig<i64>
|
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||||
llhd.wait (%arg0, %arg1 : !llhd.sig<i64>, !llhd.sig<i64>), ^bb1
|
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.entity @muxedSignal2
|
// CHECK-NEXT: llhd.entity @muxedSignal2
|
||||||
llhd.proc @muxedSignal2(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
|
llhd.proc @muxedSignal2(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>) -> () {
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||||
|
@ -68,13 +68,13 @@ llhd.proc @muxedSignal2(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
%cond = hw.constant true
|
%cond = hw.constant true
|
||||||
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
|
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||||
%0 = llhd.prb %sig : !llhd.sig<i64>
|
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||||
llhd.wait (%sig : !llhd.sig<i64>), ^bb1
|
llhd.wait (%sig : !hw.inout<i64>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-NEXT: llhd.entity @partialSignal
|
// CHECK-NEXT: llhd.entity @partialSignal
|
||||||
llhd.proc @partialSignal(%arg0 : !llhd.sig<i64>) -> () {
|
llhd.proc @partialSignal(%arg0 : !hw.inout<i64>) -> () {
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||||
|
@ -82,7 +82,7 @@ llhd.proc @partialSignal(%arg0 : !llhd.sig<i64>) -> () {
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
%c = hw.constant 16 : i6
|
%c = hw.constant 16 : i6
|
||||||
%sig = llhd.sig.extract %arg0 from %c : (!llhd.sig<i64>) -> !llhd.sig<i32>
|
%sig = llhd.sig.extract %arg0 from %c : (!hw.inout<i64>) -> !hw.inout<i32>
|
||||||
%0 = llhd.prb %sig : !llhd.sig<i32>
|
%0 = llhd.prb %sig : !hw.inout<i32>
|
||||||
llhd.wait (%arg0 : !llhd.sig<i64>), ^bb1
|
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// RUN: circt-opt %s -llhd-process-lowering -split-input-file -verify-diagnostics
|
// RUN: circt-opt %s -llhd-process-lowering -split-input-file -verify-diagnostics
|
||||||
|
|
||||||
// Check wait with observing probed signals
|
// Check wait with observing probed signals
|
||||||
llhd.proc @prbAndWaitNotObserved(%arg0 : !llhd.sig<i64>) -> () {
|
llhd.proc @prbAndWaitNotObserved(%arg0 : !hw.inout<i64>) -> () {
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
%0 = llhd.prb %arg0 : !llhd.sig<i64>
|
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
||||||
llhd.wait ^bb1
|
llhd.wait ^bb1
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ llhd.proc @prbAndWaitNotObserved(%arg0 : !llhd.sig<i64>) -> () {
|
||||||
|
|
||||||
// Check that block arguments for the second block are not allowed.
|
// Check that block arguments for the second block are not allowed.
|
||||||
// expected-error @+1 {{during process-lowering: the second block (containing the llhd.wait) is not allowed to have arguments}}
|
// expected-error @+1 {{during process-lowering: the second block (containing the llhd.wait) is not allowed to have arguments}}
|
||||||
llhd.proc @blockArgumentsNotAllowed(%arg0 : !llhd.sig<i64>) -> () {
|
llhd.proc @blockArgumentsNotAllowed(%arg0 : !hw.inout<i64>) -> () {
|
||||||
cf.br ^bb1(%arg0 : !llhd.sig<i64>)
|
cf.br ^bb1(%arg0 : !hw.inout<i64>)
|
||||||
^bb1(%a : !llhd.sig<i64>):
|
^bb1(%a : !hw.inout<i64>):
|
||||||
llhd.wait ^bb1(%a : !llhd.sig<i64>)
|
llhd.wait ^bb1(%a : !hw.inout<i64>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
@ -64,12 +64,12 @@ llhd.proc @moreThanTwoBlocksNotAllowed() -> () {
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
llhd.proc @muxedSignal(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>, %arg2 : !llhd.sig<i1>) -> () {
|
llhd.proc @muxedSignal(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>, %arg2 : !hw.inout<i1>) -> () {
|
||||||
cf.br ^bb1
|
cf.br ^bb1
|
||||||
^bb1:
|
^bb1:
|
||||||
%cond = llhd.prb %arg2 : !llhd.sig<i1>
|
%cond = llhd.prb %arg2 : !hw.inout<i1>
|
||||||
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
|
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||||
%0 = llhd.prb %sig : !llhd.sig<i64>
|
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
||||||
llhd.wait (%arg0, %arg2 : !llhd.sig<i64>, !llhd.sig<i1>), ^bb1
|
llhd.wait (%arg0, %arg2 : !hw.inout<i64>, !hw.inout<i1>), ^bb1
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,18 @@ func.func @complex(%flag : i1) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_entity_inline
|
// CHECK-LABEL: @check_entity_inline
|
||||||
llhd.entity @check_entity_inline() -> (%out : !llhd.sig<i32>) {
|
llhd.entity @check_entity_inline() -> (%out : !hw.inout<i32>) {
|
||||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||||
// CHECK-NEXT: %{{.*}} = llhd.constant_time
|
// CHECK-NEXT: %{{.*}} = llhd.constant_time
|
||||||
// CHECK-NEXT: llhd.drv
|
// CHECK-NEXT: llhd.drv
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
%1 = func.call @simple() : () -> i32
|
%1 = func.call @simple() : () -> i32
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
llhd.drv %out, %1 after %time : !llhd.sig<i32>
|
llhd.drv %out, %1 after %time : !hw.inout<i32>
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_proc_inline
|
// CHECK-LABEL: @check_proc_inline
|
||||||
llhd.proc @check_proc_inline(%arg : !llhd.sig<i1>) -> (%out : !llhd.sig<i32>) {
|
llhd.proc @check_proc_inline(%arg : !hw.inout<i1>) -> (%out : !hw.inout<i32>) {
|
||||||
// CHECK-NEXT: %[[PRB:.*]] = llhd.prb
|
// CHECK-NEXT: %[[PRB:.*]] = llhd.prb
|
||||||
// CHECK-NEXT: cf.cond_br %[[PRB]], ^[[BB1:.*]], ^[[BB2:.*]]
|
// CHECK-NEXT: cf.cond_br %[[PRB]], ^[[BB1:.*]], ^[[BB2:.*]]
|
||||||
// CHECK-NEXT: ^[[BB1]]:
|
// CHECK-NEXT: ^[[BB1]]:
|
||||||
|
@ -46,12 +46,12 @@ llhd.proc @check_proc_inline(%arg : !llhd.sig<i1>) -> (%out : !llhd.sig<i32>) {
|
||||||
// CHECK-NEXT: cf.br ^[[BB3]](%[[C1]] : i32)
|
// CHECK-NEXT: cf.br ^[[BB3]](%[[C1]] : i32)
|
||||||
// CHECK-NEXT: ^[[BB3]](%[[A:.*]]: i32):
|
// CHECK-NEXT: ^[[BB3]](%[[A:.*]]: i32):
|
||||||
// CHECK-NEXT: %[[C2:.*]] = llhd.constant_time
|
// CHECK-NEXT: %[[C2:.*]] = llhd.constant_time
|
||||||
// CHECK-NEXT: llhd.drv %{{.*}}, %[[A]] after %[[C2]] : !llhd.sig<i32>
|
// CHECK-NEXT: llhd.drv %{{.*}}, %[[A]] after %[[C2]] : !hw.inout<i32>
|
||||||
// CHECK-NEXT: llhd.halt
|
// CHECK-NEXT: llhd.halt
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
%0 = llhd.prb %arg : !llhd.sig<i1>
|
%0 = llhd.prb %arg : !hw.inout<i1>
|
||||||
%1 = func.call @complex(%0) : (i1) -> i32
|
%1 = func.call @complex(%0) : (i1) -> i32
|
||||||
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
|
||||||
llhd.drv %out, %1 after %time : !llhd.sig<i32>
|
llhd.drv %out, %1 after %time : !hw.inout<i32>
|
||||||
llhd.halt
|
llhd.halt
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ target_link_libraries(circt-opt
|
||||||
CIRCTIbis
|
CIRCTIbis
|
||||||
CIRCTIbisTransforms
|
CIRCTIbisTransforms
|
||||||
CIRCTInteropDialect
|
CIRCTInteropDialect
|
||||||
CIRCTHWToLLHD
|
|
||||||
CIRCTHWToSMT
|
CIRCTHWToSMT
|
||||||
CIRCTHWToSystemC
|
CIRCTHWToSystemC
|
||||||
CIRCTHWToSV
|
CIRCTHWToSV
|
||||||
|
|
Loading…
Reference in New Issue