[LLHD] Use hw.inout instead of llhd.sig (#7353)

This commit is contained in:
Martin Erhart 2024-07-19 21:51:33 +02:00 committed by GitHub
parent 2345382e67
commit c012ab88a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 442 additions and 979 deletions

View File

@ -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_

View File

@ -29,7 +29,6 @@
#include "circt/Conversion/FSMToSV.h"
#include "circt/Conversion/HWArithToHW.h"
#include "circt/Conversion/HWToBTOR2.h"
#include "circt/Conversion/HWToLLHD.h"
#include "circt/Conversion/HWToLLVM.h"
#include "circt/Conversion/HWToSMT.h"
#include "circt/Conversion/HWToSV.h"

View File

@ -545,20 +545,6 @@ def HWArithToHW : Pass<"lower-hwarith-to-hw", "mlir::ModuleOp"> {
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
//===----------------------------------------------------------------------===//

View File

@ -41,6 +41,10 @@ def InOutType : DialectType<HWDialect,
CPred<"::circt::hw::type_isa<circt::hw::InOutType>($_self)">,
"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.
def ArrayType : DialectType<HWDialect,
CPred<"::circt::hw::type_isa<circt::hw::ArrayType>($_self)">,

View File

@ -25,7 +25,7 @@ class SigPtrIndexBitWidthConstraint<string index, string input>
class SigArrayElementTypeConstraint<string result, string input>
: TypesMatchWith<"result must be a signal of the array element type",
input, result,
"llhd::SigType::get(llhd::getLLHDElementType($_self))">;
"hw::InOutType::get(llhd::getLLHDElementType($_self))">;
class PtrArrayElementTypeConstraint<string result, string input>
: 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.
}];
let arguments = (ins LLHD_SigType<[HWIntegerType]>:$input,
let arguments = (ins InOutTypeOf<[HWIntegerType]>:$input,
HWIntegerType:$lowBit);
let results = (outs LLHD_SigType<[HWIntegerType]>: $result);
let results = (outs InOutTypeOf<[HWIntegerType]>: $result);
let assemblyFormat = [{
$input `from` $lowBit attr-dict `:` functional-type($input, $result)
@ -128,13 +128,13 @@ def LLHD_SigArraySliceOp : LLHD_Op<"sig.array_slice",
```mlir
%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);
let results = (outs LLHD_SigType<[ArrayType]>: $result);
let results = (outs InOutTypeOf<[ArrayType]>: $result);
let assemblyFormat = [{
$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 getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
hw::ArrayType getInputArrayType() {
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
getInput().getType()).getUnderlyingType());
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
getInput().getType()).getElementType());
}
hw::ArrayType getResultArrayType() {
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
getResult().getType()).getUnderlyingType());
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
getResult().getType()).getElementType());
}
}];
let hasFolder = true;
@ -196,11 +196,11 @@ def LLHD_PtrArraySliceOp : LLHD_Op<"ptr.array_slice",
unsigned getInputWidth() { return getLLHDTypeWidth(getInput().getType()); }
hw::ArrayType getInputArrayType() {
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
getInput().getType()).getUnderlyingType());
getInput().getType()).getElementType());
}
hw::ArrayType getResultArrayType() {
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::PtrType>(
getResult().getType()).getUnderlyingType());
getResult().getType()).getElementType());
}
}];
let hasFolder = true;
@ -221,20 +221,20 @@ def LLHD_SigArrayGetOp : LLHD_Op<"sig.array_get",
Example:
```mlir
// Returns a !llhd.sig<i8>
%0 = llhd.sig.array_get %arr[%index] : !llhd.sig<!hw.array<4xi8>>
// Returns a !hw.inout<i8>
%0 = llhd.sig.array_get %arr[%index] : !hw.inout<array<4xi8>>
```
}];
let arguments = (ins LLHD_SigType<[ArrayType]>:$input, HWIntegerType:$index);
let results = (outs LLHD_SigType<[HWNonInOutType]>: $result);
let arguments = (ins InOutTypeOf<[ArrayType]>:$input, HWIntegerType:$index);
let results = (outs InOutTypeOf<[HWNonInOutType]>: $result);
let assemblyFormat = "$input `[` $index `]` attr-dict `:` qualified(type($input))";
let extraClassDeclaration = [{
hw::ArrayType getArrayType() {
return llvm::cast<hw::ArrayType>(llvm::cast<llhd::SigType>(
getInput().getType()).getUnderlyingType());
return llvm::cast<hw::ArrayType>(llvm::cast<hw::InOutType>(
getInput().getType()).getElementType());
}
}];
}
@ -266,7 +266,7 @@ def LLHD_PtrArrayGetOp : LLHD_Op<"ptr.array_get",
let extraClassDeclaration = [{
hw::ArrayType getArrayType() {
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:
```mlir
// Returns a !llhd.sig<i8>
// Returns a !hw.inout<i8>
%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 results = (outs LLHD_SigType<[HWNonInOutType]>:$result);
let arguments = (ins InOutTypeOf<[StructType]>:$input, StrAttr:$field);
let results = (outs InOutTypeOf<[HWNonInOutType]>:$result);
let assemblyFormat = "$input `[` $field `]` attr-dict `:` qualified(type($input))";
let extraClassDeclaration = [{
hw::StructType getStructType() {
return llvm::cast<hw::StructType>(llvm::cast<llhd::SigType>(
getInput().getType()).getUnderlyingType());
return llvm::cast<hw::StructType>(llvm::cast<hw::InOutType>(
getInput().getType()).getElementType());
}
}];
}
@ -330,7 +330,7 @@ def LLHD_PtrStructExtractOp : LLHD_Op<"ptr.struct_extract", [Pure,
let extraClassDeclaration = [{
hw::StructType getStructType() {
return llvm::cast<hw::StructType>(llvm::cast<llhd::PtrType>(
getInput().getType()).getUnderlyingType());
getInput().getType()).getElementType());
}
}];
}

View File

@ -13,6 +13,7 @@
#ifndef 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/OpBase.td"
include "mlir/IR/PatternBase.td"
@ -30,6 +31,7 @@ include "mlir/IR/SymbolInterfaces.td"
def LLHD_Dialect : Dialect {
let name = "llhd";
let cppNamespace = "::circt::llhd";
let dependentDialects = ["circt::hw::HWDialect"];
let description = [{
A low-level hardware description dialect in MLIR.
@ -68,28 +70,17 @@ def LLHD_TimeType : DialectType<LLHD_Dialect,
BuildableType<"TimeType::get($_builder.getContext())">;
// Legal underlying types for signals and pointers.
def LLHD_AnyUnderlyingType :
def LLHD_AnyElementType :
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
class LLHD_PtrType<list<Type> allowedTypes>
: 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
class LLHD_SigOrPtrType<list<Type> allowedTypes>
: AnyTypeOf<[LLHD_SigType<allowedTypes>, LLHD_PtrType<allowedTypes>]>;
def LLHD_AnySigOrPtrType : LLHD_SigOrPtrType<[LLHD_AnyUnderlyingType]>;
def LLHD_AnySigOrPtrType : AnyTypeOf<[LLHD_AnyPtrType, InOutType]>;
//===----------------------------------------------------------------------===//
// LLHD op definition

View File

@ -17,26 +17,6 @@ class LLHDType<string name> : TypeDef<LLHD_Dialect, name> { }
// 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++.
def PtrTypeImpl : LLHDType<"Ptr"> {
let summary = "pointer type";
@ -46,12 +26,12 @@ def PtrTypeImpl : LLHDType<"Ptr"> {
}];
let mnemonic = "ptr";
let parameters = (ins "::mlir::Type":$underlyingType);
let assemblyFormat = "`<` $underlyingType `>`";
let parameters = (ins "::mlir::Type":$elementType);
let assemblyFormat = "`<` $elementType `>`";
let builders = [
AttrBuilderWithInferredContext<(ins "::mlir::Type":$underlyingType), [{
return $_get(underlyingType.getContext(), underlyingType);
AttrBuilderWithInferredContext<(ins "::mlir::Type":$elementType), [{
return $_get(elementType.getContext(), elementType);
}]>
];
}

View File

@ -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",
[MemAlloc]>: $result);
@ -42,7 +42,7 @@ def LLHD_VarOp : LLHD_Op<"var", [
def LLHD_LoadOp : LLHD_Op<"load", [
TypesMatchWith<
"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 description = [{
@ -64,7 +64,7 @@ def LLHD_LoadOp : LLHD_Op<"load", [
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to load from",
[MemRead]>: $pointer);
let results = (outs LLHD_AnyUnderlyingType: $result);
let results = (outs LLHD_AnyElementType: $result);
let assemblyFormat = "$pointer attr-dict `:` qualified(type($pointer))";
}
@ -72,7 +72,7 @@ def LLHD_LoadOp : LLHD_Op<"load", [
def LLHD_StoreOp : LLHD_Op<"store", [
TypesMatchWith<
"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 description = [{
@ -94,7 +94,7 @@ def LLHD_StoreOp : LLHD_Op<"store", [
let arguments = (ins Arg<LLHD_AnyPtrType, "the reference to store to",
[MemWrite]>: $pointer,
LLHD_AnyUnderlyingType: $value);
LLHD_AnyElementType: $value);
let assemblyFormat = "$pointer `,` $value attr-dict `:` qualified(type($pointer))";
}

View File

@ -15,7 +15,7 @@ include "mlir/IR/EnumAttr.td"
def LLHD_SigOp : LLHD_Op<"sig", [
TypesMatchWith<
"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 description = [{
@ -45,8 +45,8 @@ def LLHD_SigOp : LLHD_Op<"sig", [
signal named "bar", carrying an `i1` type with initial value of 1.
}];
let arguments = (ins StrAttr: $name, LLHD_AnyUnderlyingType: $init);
let results = (outs LLHD_AnySigType: $result);
let arguments = (ins StrAttr: $name, LLHD_AnyElementType: $init);
let results = (outs InOutType: $result);
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", [
TypesMatchWith<
"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 description = [{
@ -65,7 +65,7 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
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:
@ -73,13 +73,13 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
```mlir
%const_i1 = llhd.const 1 : 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);
let results = (outs LLHD_AnyUnderlyingType: $result);
let results = (outs LLHD_AnyElementType: $result);
let assemblyFormat = "$signal attr-dict `:` qualified(type($signal))";
}
@ -87,7 +87,7 @@ def LLHD_PrbOp : LLHD_Op<"prb", [
def LLHD_OutputOp : LLHD_Op<"output", [
TypesMatchWith<
"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 description = [{
@ -109,15 +109,15 @@ def LLHD_OutputOp : LLHD_Op<"output", [
%value = llhd.const 1 : i1
%time = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
%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,
LLHD_AnyUnderlyingType: $value,
LLHD_AnyElementType: $value,
LLHD_TimeType: $time);
let results = (outs LLHD_AnySigType: $result);
let results = (outs InOutType: $result);
let assemblyFormat = [{
( $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", [
TypesMatchWith<
"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 description = [{
@ -142,7 +142,7 @@ def LLHD_DrvOp : LLHD_Op<"drv", [
```
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:
@ -154,14 +154,14 @@ def LLHD_DrvOp : LLHD_Op<"drv", [
%sig = llhd.sig %init : i1
%new = llhd.not %init : i1
llhd.drv %sig, %new after %time : !llhd.sig<i1>
llhd.drv %sig, %new after %time if %en : !llhd.sig<i1>
llhd.drv %sig, %new after %time : !hw.inout<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,
LLHD_AnyUnderlyingType: $value,
LLHD_AnyElementType: $value,
LLHD_TimeType: $time,
Optional<I1>: $enable);
@ -230,30 +230,30 @@ def LLHD_RegOp : LLHD_Op<"reg", [
A rising, falling, and dual-edge triggered flip-flop:
```mlir
llhd.reg %Q, (%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "fall" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "both" %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 : !hw.inout<i8>) : !hw.inout<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:
```mlir
llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
(%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%init, "low" %RSTB after %T : !hw.inout<i8>),
(%D, "rise" %CLK after %T : !hw.inout<i8>) : !hw.inout<i8>
```
A rising-edge triggered enable flip-flop with active-low reset:
```mlir
llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
(%D, "rise" %CLK after %T if %EN : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%init, "low" %RSTB after %T : !hw.inout<i8>),
(%D, "rise" %CLK after %T if %EN : !hw.inout<i8>) : !hw.inout<i8>
```
A transparent-low and transparent-high latch:
```mlir
llhd.reg %Q, (%D, "low" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "high" %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 : !hw.inout<i8>) : !hw.inout<i8>
```
An SR latch:
@ -261,15 +261,15 @@ def LLHD_RegOp : LLHD_Op<"reg", [
```mlir
%0 = llhd.const 0 : i1
%1 = llhd.const 1 : i1
llhd.reg %Q, (%0, "high" %R after %T : !llhd.sig<i1>),
(%1, "high" %S after %T : !llhd.sig<i1>) : !llhd.sig<i1>
llhd.reg %Q, (%0, "high" %R after %T : !hw.inout<i1>),
(%1, "high" %S after %T : !hw.inout<i1>) : !hw.inout<i1>
```
}];
let arguments = (ins
LLHD_AnySigType: $signal,
InOutType: $signal,
LLHD_RegModeArrayAttr: $modes,
Variadic<AnyTypeOf<[LLHD_AnyUnderlyingType, LLHD_AnySigType]>>: $values,
Variadic<AnyTypeOf<[LLHD_AnyElementType, InOutType]>>: $values,
Variadic<I1>: $triggers,
Variadic<LLHD_TimeType>: $delays,
Variadic<I1>: $gates,

View File

@ -40,11 +40,11 @@ def LLHD_EntityOp : LLHD_Op<"entity", [
```mlir
llhd.entity @Foo () -> () {
%0 = llhd.const 0 : i1
%toggle = llhd.sig %0 : i1 -> !llhd.sig<i1>
%1 = llhd.prb %toggle : !llhd.sig<i1> -> i1
%toggle = llhd.sig %0 : i1 -> !hw.inout<i1>
%1 = llhd.prb %toggle : !hw.inout<i1> -> i1
%2 = llhd.not %1 : i1
%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:
```mlir
llhd.proc @example(%in0 : !llhd.sig<i64>, %in1 : !llhd.sig<i1>) ->
(%out2 : !llhd.sig<i1>) {
llhd.proc @example(%in0 : !hw.inout<i64>, %in1 : !hw.inout<i1>) ->
(%out2 : !hw.inout<i1>) {
br ^bb1
^bb1:
llhd.halt
@ -166,16 +166,16 @@ def LLHD_InstOp : LLHD_Op<"inst", [
```mlir
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.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,
FlatSymbolRefAttr:$callee,
Variadic<LLHD_AnySigType>:$inputs,
Variadic<LLHD_AnySigType>:$outputs);
Variadic<InOutType>:$inputs,
Variadic<InOutType>:$outputs);
let assemblyFormat = [{
$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.
}];
let arguments = (ins LLHD_AnySigType:$lhs,
LLHD_AnySigType:$rhs);
let arguments = (ins InOutType:$lhs,
InOutType:$rhs);
let assemblyFormat = [{
operands attr-dict `:` qualified(type($lhs))
@ -254,13 +254,13 @@ def LLHD_WaitOp : LLHD_Op<"wait", [
```mlir
llhd.wait ^bb1
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 for %time, (%0, %1 : !llhd.sig<i64>, !llhd.sig<i1>),
^bb1(%1, %0 : !llhd.sig<i1>, !llhd.sig<i64>)
llhd.wait (%0, %1 : !hw.inout<i64>, !hw.inout<i1>), ^bb1(%1 : !hw.inout<i1>)
llhd.wait for %time, (%0, %1 : !hw.inout<i64>, !hw.inout<i1>),
^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,
Variadic<AnyType>:$destOps);

View File

@ -38,9 +38,9 @@ def MemoryToBlockArgument : Pass<"llhd-memory-to-block-argument",
Example:
```mlir
llhd.proc @check_simple(%condsig : !llhd.sig<i1>) -> () {
llhd.proc @check_simple(%condsig : !hw.inout<i1>) -> () {
%c5 = llhd.const 5 : i32
%cond = llhd.prb %condsig : !llhd.sig<i1>
%cond = llhd.prb %condsig : !hw.inout<i1>
%ptr = llhd.var %c5 : i32
cond_br %cond, ^bb1, ^bb2
^bb1:
@ -57,9 +57,9 @@ def MemoryToBlockArgument : Pass<"llhd-memory-to-block-argument",
is transformed to
```mlir
llhd.proc @check_simple(%condsig : !llhd.sig<i1>) -> () {
llhd.proc @check_simple(%condsig : !hw.inout<i1>) -> () {
%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)
^bb1:
%c6 = llhd.const 6 : i32

View File

@ -19,7 +19,6 @@ add_circt_public_c_api_library(CIRCTCAPIConversion
CIRCTHandshakeToDC
CIRCTHandshakeToHW
CIRCTHWArithToHW
CIRCTHWToLLHD
CIRCTHWToLLVM
CIRCTHWToBTOR2
CIRCTHWToSMT

View File

@ -29,9 +29,6 @@ MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(LLHD, llhd, circt::llhd::LLHDDialect)
/// Check if a type is a time 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.
bool llhdTypeIsAPointerType(MlirType type) {
return isa<PtrType>(unwrap(type));
@ -42,24 +39,14 @@ MlirType llhdTimeTypeGet(MlirContext 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.
MlirType llhdPointerTypeGet(MlirType 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.
MlirType llhdPointerTypeGetElementType(MlirType type) {
return wrap(cast<PtrType>(unwrap(type)).getUnderlyingType());
return wrap(cast<PtrType>(unwrap(type)).getElementType());
}
//===----------------------------------------------------------------------===//

View File

@ -15,7 +15,6 @@ add_subdirectory(HandshakeToDC)
add_subdirectory(HandshakeToHW)
add_subdirectory(HWArithToHW)
add_subdirectory(HWToBTOR2)
add_subdirectory(HWToLLHD)
add_subdirectory(HWToLLVM)
add_subdirectory(HWToSMT)
add_subdirectory(HWToSV)

View File

@ -1,14 +0,0 @@
add_circt_conversion_library(CIRCTHWToLLHD
HWToLLHD.cpp
DEPENDS
CIRCTConversionPassIncGen
LINK_COMPONENTS
Core
LINK_LIBS PUBLIC
CIRCTLLHD
CIRCTHW
MLIRTransforms
)

View File

@ -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();
});
}

View File

@ -163,7 +163,7 @@ struct VariableOpConversion : public OpConversionPattern<VariableOp> {
if (!init)
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);
return success();
}

View File

@ -130,10 +130,10 @@ struct constant_int_all_ones_matcher {
} // anonymous namespace
unsigned circt::llhd::getLLHDTypeWidth(Type type) {
if (auto sig = dyn_cast<llhd::SigType>(type))
type = sig.getUnderlyingType();
if (auto sig = dyn_cast<hw::InOutType>(type))
type = sig.getElementType();
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
type = ptr.getUnderlyingType();
type = ptr.getElementType();
if (auto array = dyn_cast<hw::ArrayType>(type))
return array.getNumElements();
if (auto tup = dyn_cast<hw::StructType>(type))
@ -142,10 +142,10 @@ unsigned circt::llhd::getLLHDTypeWidth(Type type) {
}
Type circt::llhd::getLLHDElementType(Type type) {
if (auto sig = dyn_cast<llhd::SigType>(type))
type = sig.getUnderlyingType();
if (auto sig = dyn_cast<hw::InOutType>(type))
type = sig.getElementType();
else if (auto ptr = dyn_cast<llhd::PtrType>(type))
type = ptr.getUnderlyingType();
type = ptr.getElementType();
if (auto array = dyn_cast<hw::ArrayType>(type))
return array.getElementType();
return type;
@ -271,7 +271,7 @@ static LogicalResult inferReturnTypesOfStructExtractOp(
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
Type type =
cast<hw::StructType>(
cast<SigPtrType>(operands[0].getType()).getUnderlyingType())
cast<SigPtrType>(operands[0].getType()).getElementType())
.getFieldType(
cast<StringAttr>(attrs.getNamed("field")->getValue()).getValue());
if (!type) {
@ -288,7 +288,7 @@ LogicalResult llhd::SigStructExtractOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> loc, ValueRange operands,
DictionaryAttr attrs, mlir::OpaqueProperties properties,
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
return inferReturnTypesOfStructExtractOp<llhd::SigType>(
return inferReturnTypesOfStructExtractOp<hw::InOutType>(
context, loc, operands, attrs, properties, regions, results);
}
@ -470,7 +470,7 @@ LogicalResult llhd::EntityOp::verify() {
// Check that all block arguments are of signal type
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 ")
<< getArgument(i).getType() << ", expected LLHD signal type";
@ -487,7 +487,7 @@ LogicalResult circt::llhd::EntityOp::verifyType() {
// Check that all operands are of signal type
for (Type inputType : type.getInputs())
if (!isa<llhd::SigType>(inputType))
if (!isa<hw::InOutType>(inputType))
return emitOpError("usage of invalid argument type. Got ")
<< inputType << ", expected LLHD signal type";
@ -555,7 +555,7 @@ LogicalResult circt::llhd::ProcOp::verifyType() {
// Check that all operands are of signal type
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 ")
<< getArgument(i).getType() << ", expected LLHD signal type";
}
@ -782,16 +782,16 @@ LogicalResult llhd::InstOp::verify() {
// Check input types
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])
return emitOpError("input type mismatch");
}
// Check output types
for (size_t i = 0, e = module.getNumOutputPorts(); i != e; ++i) {
if (cast<llhd::SigType>(
if (cast<hw::InOutType>(
getOperand(module.getNumInputPorts() + i).getType())
.getUnderlyingType() != module.getOutputTypes()[i])
.getElementType() != module.getOutputTypes()[i])
return emitOpError("output type mismatch");
}
@ -997,7 +997,7 @@ LogicalResult llhd::RegOp::verify() {
for (auto val : getValues()) {
if (val.getType() != getSignal().getType() &&
val.getType() !=
cast<llhd::SigType>(getSignal().getType()).getUnderlyingType()) {
cast<hw::InOutType>(getSignal().getType()).getElementType()) {
return emitOpError(
"type of each 'value' has to be either the same as the "
"type of 'signal' or the underlying type of 'signal'");

View File

@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "circt/Dialect/LLHD/IR/LLHDTypes.h"
#include "circt/Dialect/HW/HWTypes.h"
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/DialectImplementation.h"

View File

@ -142,7 +142,7 @@ void MemoryToBlockArgumentPass::runOnOperation() {
for (Block *jp : joinPoints) {
// Add a block argument for the variable at each join point
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
// the block argument
@ -151,7 +151,7 @@ void MemoryToBlockArgumentPass::runOnOperation() {
builder.setInsertionPoint(pred->getTerminator());
Value load = builder.create<llhd::LoadOp>(
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
addBlockOperandToTerminator(pred->getTerminator(), jp, load);
}

View File

@ -36,7 +36,7 @@ struct ProcessLoweringPass
/// 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
/// 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) {
// If the value in the observer list, we don't need to backtrack further.
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
// that, we can fail here. This includes for example llhd.sig
if (llvm::none_of(op->getOperands(), [](Value arg) {
return isa<llhd::SigType>(arg.getType());
return isa<hw::InOutType>(arg.getType());
}))
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
// observed no matter how far we backtrack, we fail.
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));
}));
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -268,7 +268,7 @@ moore.module @Variable() {
// CHECK: [[B:%.+]] = llhd.sig "b1" [[TMP1]] : 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>
// CHECK: llhd.sig "b2" [[PRB]] : i8
%b2 = moore.variable %0 : <i8>
@ -284,7 +284,7 @@ moore.module @Variable() {
%3 = moore.constant 10 : i32
// 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
// CHECK: hw.output

View File

@ -1,8 +1,8 @@
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
// CHECK-LABEL: @const_hoisting
// CHECK-SAME: %[[SIG:.*]]: !llhd.sig<i32>
func.func @const_hoisting(%sig : !llhd.sig<i32>) {
// CHECK-SAME: %[[SIG:.*]]: !hw.inout<i32>
func.func @const_hoisting(%sig : !hw.inout<i32>) {
// CHECK-DAG: %[[C0:.*]] = hw.constant -1 : i32
// CHECK-DAG: %[[TIME:.*]] = llhd.constant_time <1ns, 0d, 0e>
// CHECK-NEXT: cf.br ^[[BB:.*]]
@ -11,7 +11,7 @@ func.func @const_hoisting(%sig : !llhd.sig<i32>) {
^bb1:
%0 = hw.constant -1 : i32
%1 = llhd.constant_time <1ns, 0d, 0e>
// CHECK-NEXT: llhd.drv %[[SIG]], %[[C0]] after %[[TIME]] : !llhd.sig<i32>
llhd.drv %sig, %0 after %1 : !llhd.sig<i32>
// CHECK-NEXT: llhd.drv %[[SIG]], %[[C0]] after %[[TIME]] : !hw.inout<i32>
llhd.drv %sig, %0 after %1 : !hw.inout<i32>
cf.br ^bb1
}

View File

@ -1,21 +1,21 @@
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
// 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
// CHECK: %[[EXT:.*]] = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i32>
%0 = 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 : (!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>
return %0, %1 : !llhd.sig<i32>, !llhd.sig<i32>
// CHECK-NEXT: return %[[EXT]], %arg0 : !hw.inout<i32>, !hw.inout<i32>
return %0, %1 : !hw.inout<i32>, !hw.inout<i32>
}
// CHECK-LABEL: @sigArraySlice
func.func @sigArraySliceOp(%arg0: !llhd.sig<!hw.array<30xi32>>, %arg1: i5)
-> (!llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<30xi32>>, !llhd.sig<!hw.array<20xi32>>, !llhd.sig<!hw.array<3xi32>>) {
func.func @sigArraySliceOp(%arg0: !hw.inout<array<30xi32>>, %arg1: i5)
-> (!hw.inout<array<30xi32>>, !hw.inout<array<30xi32>>, !hw.inout<array<20xi32>>, !hw.inout<array<3xi32>>) {
%zero = hw.constant 0 : 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
%b = hw.constant 16 : i5
// CHECK: %[[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 : (!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 : (!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: %[[RES2:.*]] = llhd.sig.array_slice %arg0 at %c-13_i5 : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<3xi32>>
%1 = llhd.sig.array_slice %arg0 at %a : (!llhd.sig<!hw.array<30xi32>>) -> !llhd.sig<!hw.array<20xi32>>
%2 = llhd.sig.array_slice %1 at %b : (!llhd.sig<!hw.array<20xi32>>) -> !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 : (!hw.inout<array<30xi32>>) -> !hw.inout<array<20xi32>>
%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>>
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>>
// 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 : !hw.inout<array<30xi32>>, !hw.inout<array<30xi32>>, !hw.inout<array<20xi32>>, !hw.inout<array<3xi32>>
}

View File

@ -1,39 +1,39 @@
// RUN: circt-opt %s -cse | FileCheck %s
// 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
%time = llhd.constant_time <0ns, 1d, 0e>
// CHECK-NEXT: [[P0:%.*]] = llhd.prb
%1 = llhd.prb %arg0 : !llhd.sig<i32>
%2 = llhd.prb %arg0 : !llhd.sig<i32>
%3 = llhd.prb %arg0 : !llhd.sig<i32>
%1 = llhd.prb %arg0 : !hw.inout<i32>
%2 = llhd.prb %arg0 : !hw.inout<i32>
%3 = llhd.prb %arg0 : !hw.inout<i32>
// CHECK-NEXT: llhd.drv %arg1, [[P0]]
// CHECK-NEXT: llhd.drv %arg2, [[P0]]
llhd.drv %arg1, %1 after %time : !llhd.sig<i32>
llhd.drv %arg2, %2 after %time : !llhd.sig<i32>
llhd.drv %arg1, %1 after %time : !hw.inout<i32>
llhd.drv %arg2, %2 after %time : !hw.inout<i32>
}
// 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
%time = llhd.constant_time <0ns, 1d, 0e>
// CHECK-NEXT: [[P1:%.*]] = llhd.prb
%1 = llhd.prb %arg0 : !llhd.sig<i32>
%1 = llhd.prb %arg0 : !hw.inout<i32>
// CHECK-NEXT: llhd.wait
llhd.wait (%arg0: !llhd.sig<i32>), ^bb1
llhd.wait (%arg0: !hw.inout<i32>), ^bb1
// CHECK-NEXT: ^bb1:
^bb1:
// CHECK-NEXT: [[P2:%.*]] = llhd.prb
%2 = llhd.prb %arg0 : !llhd.sig<i32>
%3 = llhd.prb %arg0 : !llhd.sig<i32>
%2 = llhd.prb %arg0 : !hw.inout<i32>
%3 = llhd.prb %arg0 : !hw.inout<i32>
// CHECK-NEXT: llhd.drv %arg1, [[P1]]
// CHECK-NEXT: llhd.drv %arg2, [[P2]]
llhd.drv %arg1, %1 after %time : !llhd.sig<i32>
llhd.drv %arg2, %2 after %time : !llhd.sig<i32>
llhd.drv %arg1, %1 after %time : !hw.inout<i32>
llhd.drv %arg2, %2 after %time : !hw.inout<i32>
llhd.halt
}

View File

@ -1,21 +1,21 @@
// RUN: circt-opt %s -canonicalize='top-down=true region-simplify=aggressive' | FileCheck %s
// CHECK-LABEL: @drv_folding
// CHECK-SAME: %[[SIG:.*]]: !llhd.sig<i32>
// CHECK-SAME: %[[SIG:.*]]: !hw.inout<i32>
// CHECK-SAME: %[[VAL:.*]]: i32
// CHECK-SAME: %[[TIME:.*]]: !llhd.time
// 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
%false = hw.constant 0 : i1
// 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]] :
llhd.drv %sig, %val after %time if %cond : !llhd.sig<i32>
llhd.drv %sig, %val after %time if %false : !llhd.sig<i32>
llhd.drv %sig, %val after %time if %cond : !hw.inout<i32>
llhd.drv %sig, %val after %time if %false : !hw.inout<i32>
// 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
return
@ -23,6 +23,6 @@ func.func @drv_folding(%sig: !llhd.sig<i32>, %val: i32, %time: !llhd.time, %cond
// CHECK-LABEL: @con_folding
// CHECK-NOT: llhd.con
llhd.entity @con_folding(%sig: !llhd.sig<i32>) {
llhd.con %sig, %sig : !llhd.sig<i32>
llhd.entity @con_folding(%sig: !hw.inout<i32>) {
llhd.con %sig, %sig : !hw.inout<i32>
}

View File

@ -1,16 +1,16 @@
// RUN: circt-opt %s -split-input-file -verify-diagnostics
// 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}}
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>) {
%0 = llhd.prb %in : !llhd.sig<i32>
%1 = llhd.prb %out : !llhd.sig<i32>
// expected-error @+1 {{'llhd.con' op operand #0 must be LLHD sig type}}
llhd.entity @connect_non_signals(%in: !hw.inout<i32>) -> (%out: !hw.inout<i32>) {
%0 = llhd.prb %in : !hw.inout<i32>
%1 = llhd.prb %out : !hw.inout<i32>
// expected-error @+1 {{'llhd.con' op operand #0 must be InOutType}}
llhd.con %0, %1 : i32
}

View File

@ -4,6 +4,6 @@
// CHECK-SAME: (%[[IN:.+]] : [[TYPE:.+]]) ->
// CHECK-SAME: (%[[OUT:.+]] : [[TYPE]])
// CHECK-NEXT: llhd.con %[[IN]], %[[OUT]] : [[TYPE]]
llhd.entity @connect_ports(%in: !llhd.sig<i32>) -> (%out: !llhd.sig<i32>) {
llhd.con %in, %out : !llhd.sig<i32>
llhd.entity @connect_ports(%in: !hw.inout<i32>) -> (%out: !hw.inout<i32>) {
llhd.con %in, %out : !hw.inout<i32>
}

View File

@ -1,29 +1,29 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s
// 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"() ({
^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
%0 = hw.constant 1 : i64
// CHECK-NEXT: %[[P0:.*]] = llhd.prb %[[ARG0]]
%1 = llhd.prb %arg0 : !llhd.sig<i64>
%1 = llhd.prb %arg0 : !hw.inout<i64>
// 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-NEXT: llhd.entity @bar () -> (%{{.*}} : !llhd.sig<i64>) {
// CHECK-NEXT: llhd.entity @bar () -> (%{{.*}} : !hw.inout<i64>) {
"llhd.entity"() ({
^body(%0 : !llhd.sig<i64>):
^body(%0 : !hw.inout<i64>):
// 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-NEXT: llhd.entity @baz (%{{.*}} : !llhd.sig<i64>) -> () {
// CHECK-NEXT: llhd.entity @baz (%{{.*}} : !hw.inout<i64>) -> () {
"llhd.entity"() ({
^body(%arg0 : !llhd.sig<i64>):
^body(%arg0 : !hw.inout<i64>):
// 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-NEXT: llhd.entity @out_of_names () -> () {

View File

@ -1,53 +1,53 @@
// 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) {
// expected-error @+1 {{'llhd.sig.array_slice' op result #0 must be LLHD sig type 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>
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 InOutType of an ArrayType values, but got '!hw.array<3xi32>'}}
%0 = llhd.sig.array_slice %sig at %ind : (!hw.inout<array<3xi32>>) -> !hw.array<3xi32>
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}}
%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
}
// -----
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}}
%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
}
// -----
func.func @illegal_sig_to_int(%s : !llhd.sig<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'}}
%0 = llhd.sig.extract %s from %ind : (!llhd.sig<i32>) -> i10
func.func @illegal_sig_to_int(%s : !hw.inout<i32>, %ind: i5) {
// 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 : (!hw.inout<i32>) -> i10
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}}
%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
}
// -----
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}}
%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
}

View File

@ -1,29 +1,29 @@
// RUN: circt-opt %s -mlir-print-op-generic -split-input-file -verify-diagnostics | circt-opt | circt-opt | FileCheck %s
// CHECK-LABEL: @sigExtract
func.func @sigExtract (%arg0 : !llhd.sig<i32>, %arg1: i5) -> () {
// CHECK-NEXT: %{{.*}} = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i5>
%1 = llhd.sig.extract %arg0 from %arg1 : (!llhd.sig<i32>) -> !llhd.sig<i5>
func.func @sigExtract (%arg0 : !hw.inout<i32>, %arg1: i5) -> () {
// CHECK-NEXT: %{{.*}} = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i5>
%1 = llhd.sig.extract %arg0 from %arg1 : (!hw.inout<i32>) -> !hw.inout<i5>
return
}
// CHECK-LABEL: @sigArray
func.func @sigArray (%arg0 : !llhd.sig<!hw.array<5xi1>>, %arg1: i3) -> () {
// CHECK-NEXT: %{{.*}} = 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 : (!llhd.sig<!hw.array<5xi1>>) -> !llhd.sig<!hw.array<3xi1>>
// CHECK-NEXT: %{{.*}} = llhd.sig.array_get %arg0[%arg1] : !llhd.sig<!hw.array<5xi1>>
%1 = llhd.sig.array_get %arg0[%arg1] : !llhd.sig<!hw.array<5xi1>>
func.func @sigArray (%arg0 : !hw.inout<array<5xi1>>, %arg1: i3) -> () {
// 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 : (!hw.inout<array<5xi1>>) -> !hw.inout<array<3xi1>>
// CHECK-NEXT: %{{.*}} = llhd.sig.array_get %arg0[%arg1] : !hw.inout<array<5xi1>>
%1 = llhd.sig.array_get %arg0[%arg1] : !hw.inout<array<5xi1>>
return
}
// CHECK-LABEL: @sigStructExtract
func.func @sigStructExtract(%arg0 : !llhd.sig<!hw.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>>
%0 = llhd.sig.struct_extract %arg0["foo"] : !llhd.sig<!hw.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>>
%1 = llhd.sig.struct_extract %arg0["baz"] : !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"] : !hw.inout<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"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
%1 = llhd.sig.struct_extract %arg0["baz"] : !hw.inout<struct<foo: i1, bar: i2, baz: i3>>
return
}

View File

@ -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}}
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) {}
llhd.entity @moduleTypeMismatch(%arg0: !llhd.sig<i3>) -> () {
llhd.entity @moduleTypeMismatch(%arg0: !hw.inout<i3>) -> () {
// 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
}
llhd.entity @moduleTypeMismatch() -> (%arg0: !llhd.sig<i3>) {
llhd.entity @moduleTypeMismatch() -> (%arg0: !hw.inout<i3>) {
// 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}}
llhd.proc @empty(%a: !llhd.sig<i1>) -> () {}
llhd.proc @empty(%a: !hw.inout<i1>) -> () {}

View File

@ -11,13 +11,13 @@
llhd.entity @empty_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
llhd.entity @one_output_entity() -> (%arg : !llhd.sig<i32>) {}
llhd.entity @one_output_entity() -> (%arg : !hw.inout<i32>) {}
// 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
llhd.proc @empty_proc() -> () {
@ -25,17 +25,17 @@ llhd.proc @empty_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
}
// 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
}
// 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
}
@ -45,25 +45,25 @@ hw.module @hwModule(in %arg0 : i32, in %arg1 : i16, out arg2: 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>) {
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 : !hw.inout<i32>, %arg1 : !hw.inout<i16>) -> (%out0 : !hw.inout<i8>, %out1 : !hw.inout<i4>) {
// CHECK-NEXT: llhd.inst "empty_entity" @empty_entity() -> () : () -> ()
"llhd.inst"() {callee=@empty_entity, operandSegmentSizes=array<i32: 0,0>, name="empty_entity"} : () -> ()
// CHECK-NEXT: llhd.inst "empty_proc" @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>) -> ()
"llhd.inst"(%arg0) {callee=@one_input_entity, operandSegmentSizes=array<i32: 1,0>, name="one_in_entity"} : (!llhd.sig<i32>) -> ()
// CHECK-NEXT: llhd.inst "one_in_proc" @one_input_proc(%[[ARG0]]) -> () : (!llhd.sig<i32>) -> ()
"llhd.inst"(%arg0) {callee=@one_input_proc, operandSegmentSizes=array<i32: 1,0>, name="one_in_proc"} : (!llhd.sig<i32>) -> ()
// CHECK-NEXT: llhd.inst "one_out_entity" @one_output_entity() -> (%[[ARG0]]) : () -> !llhd.sig<i32>
"llhd.inst"(%arg0) {callee=@one_output_entity, operandSegmentSizes=array<i32: 0,1>, name="one_out_entity"} : (!llhd.sig<i32>) -> ()
// CHECK-NEXT: llhd.inst "one_out_proc" @one_output_proc() -> (%[[ARG0]]) : () -> !llhd.sig<i32>
"llhd.inst"(%arg0) {callee=@one_output_proc, operandSegmentSizes=array<i32: 0,1>, name="one_out_proc"} : (!llhd.sig<i32>) -> ()
// CHECK-NEXT: llhd.inst "entity" @entity(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!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"} : (!llhd.sig<i32>, !llhd.sig<i16>, !llhd.sig<i8>, !llhd.sig<i4>) -> ()
// CHECK-NEXT: llhd.inst "proc" @proc(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]], %[[OUT1]]) : (!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"} : (!llhd.sig<i32>, !llhd.sig<i16>, !llhd.sig<i8>, !llhd.sig<i4>) -> ()
// CHECK-NEXT: llhd.inst "module" @hwModule(%[[ARG0]], %[[ARG1]]) -> (%[[OUT0]]) : (!llhd.sig<i32>, !llhd.sig<i16>) -> !llhd.sig<i8>
llhd.inst "module" @hwModule(%arg0, %arg1) -> (%out0) : (!llhd.sig<i32>, !llhd.sig<i16>) -> !llhd.sig<i8>
// 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"} : (!hw.inout<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"} : (!hw.inout<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"} : (!hw.inout<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"} : (!hw.inout<i32>) -> ()
// 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"} : (!hw.inout<i32>, !hw.inout<i16>, !hw.inout<i8>, !hw.inout<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"} : (!hw.inout<i32>, !hw.inout<i16>, !hw.inout<i8>, !hw.inout<i4>) -> ()
// 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) : (!hw.inout<i32>, !hw.inout<i16>) -> !hw.inout<i8>
// CHECK-NEXT: }
}

View File

@ -9,28 +9,28 @@
}) {sym_name="empty", ins=0, function_type=()->()} : () -> ()
// 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"() ({
// CHECK-NEXT: llhd.halt
// 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"() {} : () -> ()
}) {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
// CHECK-NEXT: llhd.proc @output() -> (%{{.*}} : !llhd.sig<i64>) {
// CHECK-NEXT: llhd.proc @output() -> (%{{.*}} : !hw.inout<i64>) {
"llhd.proc"() ({
// CHECK-NEXT: llhd.halt
// CHECK-NEXT: }
^body(%0 : !llhd.sig<i64>):
^body(%0 : !hw.inout<i64>):
"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
// CHECK-NEXT: llhd.proc @input(%{{.*}} : !llhd.sig<i64>) -> () {
// CHECK-NEXT: llhd.proc @input(%{{.*}} : !hw.inout<i64>) -> () {
"llhd.proc"() ({
// CHECK-NEXT: llhd.halt
// CHECK-NEXT: }
^body(%arg0 : !llhd.sig<i64>):
^body(%arg0 : !hw.inout<i64>):
"llhd.halt"() {} : () -> ()
}) {sym_name="input", ins=1, function_type=(!llhd.sig<i64>)->()} : () -> ()
}) {sym_name="input", ins=1, function_type=(!hw.inout<i64>)->()} : () -> ()

View File

@ -1,8 +1,8 @@
// RUN: circt-opt %s -split-input-file -verify-diagnostics | circt-opt | FileCheck %s
// CHECK-LABEL: @check_reg
// CHECK-SAME: %[[IN64:.*]] : !llhd.sig<i64>
llhd.entity @check_reg (%in64 : !llhd.sig<i64>) -> () {
// CHECK-SAME: %[[IN64:.*]] : !hw.inout<i64>
llhd.entity @check_reg (%in64 : !hw.inout<i64>) -> () {
// CHECK: %[[C1:.*]] = hw.constant
%c1 = hw.constant 0 : i1
// CHECK-NEXT: %[[C64:.*]] = hw.constant
@ -10,14 +10,14 @@ llhd.entity @check_reg (%in64 : !llhd.sig<i64>) -> () {
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
// one trigger with optional gate
// CHECK-NEXT: llhd.reg %[[IN64]], (%[[C64]], "low" %[[C1]] after %[[TIME]] if %[[C1]] : i64) : !llhd.sig<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) -> ()
// 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>} : (!hw.inout<i64>, i64, i1, !llhd.time, i1) -> ()
// 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>
"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) -> ()
// 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>} : (!hw.inout<i64>, i64, !hw.inout<i64>, i1, i1, !llhd.time, !llhd.time, i1, i1) -> ()
// 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>
"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) -> ()
// 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>} : (!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)

View File

@ -3,23 +3,23 @@
// expected-error @+3 {{failed to verify that type of 'init' and underlying type of 'signal' have to match.}}
llhd.entity @check_illegal_sig () -> () {
%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.}}
llhd.entity @check_illegal_prb (%sig : !llhd.sig<i1>) -> () {
%prb = "llhd.prb"(%sig) {} : (!llhd.sig<i1>) -> i32
llhd.entity @check_illegal_prb (%sig : !hw.inout<i1>) -> () {
%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.}}
llhd.entity @check_illegal_drv (%sig : !llhd.sig<i1>) -> () {
llhd.entity @check_illegal_drv (%sig : !hw.inout<i1>) -> () {
%c = hw.constant 0 : i32
%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) -> ()
}
// -----

View File

@ -23,15 +23,15 @@ llhd.entity @checkSigInst () -> () {
}
// 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>>) {
// CHECK: %{{.*}} = llhd.prb %arg0 : !llhd.sig<i1>
%0 = llhd.prb %arg0 : !llhd.sig<i1>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg1 : !llhd.sig<i64>
%1 = llhd.prb %arg1 : !llhd.sig<i64>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg2 : !llhd.sig<!hw.array<3xi8>>
%2 = llhd.prb %arg2 : !llhd.sig<!hw.array<3xi8>>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg3 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
%3 = llhd.prb %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 : !hw.inout<i1>
%0 = llhd.prb %arg0 : !hw.inout<i1>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg1 : !hw.inout<i64>
%1 = llhd.prb %arg1 : !hw.inout<i64>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg2 : !hw.inout<array<3xi8>>
%2 = llhd.prb %arg2 : !hw.inout<array<3xi8>>
// CHECK-NEXT: %{{.*}} = llhd.prb %arg3 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
%3 = llhd.prb %arg3 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
return
}
@ -47,21 +47,21 @@ func.func @checkOutput(%arg0: i32, %arg1: !llhd.time) {
}
// CHECK-LABEL: checkDrv
func.func @checkDrv(%arg0 : !llhd.sig<i1>, %arg1 : !llhd.sig<i64>, %arg2 : i1,
%arg3 : i64, %arg4 : !llhd.time, %arg5 : !llhd.sig<!hw.array<3xi8>>,
%arg6 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>,
func.func @checkDrv(%arg0 : !hw.inout<i1>, %arg1 : !hw.inout<i64>, %arg2 : i1,
%arg3 : i64, %arg4 : !llhd.time, %arg5 : !hw.inout<array<3xi8>>,
%arg6 : !hw.inout<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>
llhd.drv %arg0, %arg2 after %arg4 : !llhd.sig<i1>
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 : !llhd.sig<i64>
llhd.drv %arg1, %arg3 after %arg4 : !llhd.sig<i64>
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !llhd.sig<i64>
llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !llhd.sig<i64>
// CHECK-NEXT: llhd.drv %arg5, %arg7 after %arg4 : !llhd.sig<!hw.array<3xi8>>
llhd.drv %arg5, %arg7 after %arg4 : !llhd.sig<!hw.array<3xi8>>
// CHECK-NEXT: llhd.drv %arg6, %arg8 after %arg4 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
llhd.drv %arg6, %arg8 after %arg4 : !llhd.sig<!hw.struct<foo: i1, bar: i2, baz: i4>>
// CHECK-NEXT: llhd.drv %arg0, %arg2 after %arg4 : !hw.inout<i1>
llhd.drv %arg0, %arg2 after %arg4 : !hw.inout<i1>
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 : !hw.inout<i64>
llhd.drv %arg1, %arg3 after %arg4 : !hw.inout<i64>
// CHECK-NEXT: llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !hw.inout<i64>
llhd.drv %arg1, %arg3 after %arg4 if %arg2 : !hw.inout<i64>
// CHECK-NEXT: llhd.drv %arg5, %arg7 after %arg4 : !hw.inout<array<3xi8>>
llhd.drv %arg5, %arg7 after %arg4 : !hw.inout<array<3xi8>>
// CHECK-NEXT: llhd.drv %arg6, %arg8 after %arg4 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
llhd.drv %arg6, %arg8 after %arg4 : !hw.inout<struct<foo: i1, bar: i2, baz: i4>>
return
}

View File

@ -26,22 +26,22 @@ llhd.proc @check_wait_1 () -> () {
llhd.halt
}
// CHECK: llhd.proc @check_wait_2(%[[ARG0:.*]] : !llhd.sig<i64>, %[[ARG1:.*]] : !llhd.sig<i1>) -> () {
llhd.proc @check_wait_2 (%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i1>) -> () {
// CHECK-NEXT: llhd.wait (%[[ARG0]], %[[ARG1]] : !llhd.sig<i64>, !llhd.sig<i1>), ^[[BB:.*]](%[[ARG1]] : !llhd.sig<i1>)
"llhd.wait"(%arg0, %arg1, %arg1) [^bb1] {operandSegmentSizes=array<i32: 2,0,1>} : (!llhd.sig<i64>, !llhd.sig<i1>, !llhd.sig<i1>) -> ()
// CHECK: ^[[BB]](%[[A:.*]]: !llhd.sig<i1>):
^bb1(%a: !llhd.sig<i1>):
// CHECK: llhd.proc @check_wait_2(%[[ARG0:.*]] : !hw.inout<i64>, %[[ARG1:.*]] : !hw.inout<i1>) -> () {
llhd.proc @check_wait_2 (%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<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>} : (!hw.inout<i64>, !hw.inout<i1>, !hw.inout<i1>) -> ()
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>):
^bb1(%a: !hw.inout<i1>):
llhd.halt
}
// CHECK: llhd.proc @check_wait_3(%[[ARG0:.*]] : !llhd.sig<i64>, %[[ARG1:.*]] : !llhd.sig<i1>) -> () {
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 : !hw.inout<i64>, %arg1 : !hw.inout<i1>) -> () {
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
%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>)
"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>) -> ()
// CHECK: ^[[BB]](%[[A:.*]]: !llhd.sig<i1>, %[[B:.*]]: !llhd.sig<i64>):
^bb1(%a: !llhd.sig<i1>, %b: !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>} : (!hw.inout<i64>, !hw.inout<i1>, !llhd.time, !hw.inout<i1>, !hw.inout<i64>) -> ()
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>, %[[B:.*]]: !hw.inout<i64>):
^bb1(%a: !hw.inout<i1>, %b: !hw.inout<i64>):
llhd.halt
}

View File

@ -20,12 +20,12 @@ llhd.entity @root () -> () {
%3 = hw.constant 1 : i5
%4 = hw.constant 4 : i5
%t = llhd.constant_time #llhd.time<1ns, 0d, 0e>
%e0 = llhd.sig.extract %s0 from %2 : (!llhd.sig<i32>) -> !llhd.sig<i16>
%e1 = llhd.sig.extract %s1 from %4 : (!llhd.sig<i32>) -> !llhd.sig<i8>
%e2 = llhd.sig.extract %s2 from %2 : (!llhd.sig<i32>) -> !llhd.sig<i1>
%e3 = llhd.sig.extract %s2 from %3 : (!llhd.sig<i32>) -> !llhd.sig<i1>
llhd.drv %e0, %c0 after %t : !llhd.sig<i16>
llhd.drv %e1, %c1 after %t : !llhd.sig<i8>
llhd.drv %e2, %c2 after %t : !llhd.sig<i1>
llhd.drv %e3, %c2 after %t : !llhd.sig<i1>
%e0 = llhd.sig.extract %s0 from %2 : (!hw.inout<i32>) -> !hw.inout<i16>
%e1 = llhd.sig.extract %s1 from %4 : (!hw.inout<i32>) -> !hw.inout<i8>
%e2 = llhd.sig.extract %s2 from %2 : (!hw.inout<i32>) -> !hw.inout<i1>
%e3 = llhd.sig.extract %s2 from %3 : (!hw.inout<i32>) -> !hw.inout<i1>
llhd.drv %e0, %c0 after %t : !hw.inout<i16>
llhd.drv %e1, %c1 after %t : !hw.inout<i8>
llhd.drv %e2, %c2 after %t : !hw.inout<i1>
llhd.drv %e3, %c2 after %t : !hw.inout<i1>
}

View File

@ -19,5 +19,5 @@ llhd.entity @root () -> () {
%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>
}

View File

@ -99,19 +99,19 @@ llhd.entity @root () -> () {
%0 = hw.constant 1 : i8
%s = llhd.sig "s" %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
^entry:
%1 = llhd.prb %s : !llhd.sig<i8>
%1 = llhd.prb %s : !hw.inout<i8>
%2 = comb.add %1, %1 : i8
%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
%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>
llhd.wait for %t2, ^entry
}

View File

@ -44,7 +44,7 @@ llhd.entity @root () -> () {
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
llhd.drv %concatsig, %array after %time : !llhd.sig<!hw.array<4xi8>>
llhd.drv %getsig, %get after %time : !llhd.sig<i8>
llhd.drv %slicesig, %slice after %time : !llhd.sig<!hw.array<2xi8>>
llhd.drv %concatsig, %array after %time : !hw.inout<array<4xi8>>
llhd.drv %getsig, %get after %time : !hw.inout<i8>
llhd.drv %slicesig, %slice after %time : !hw.inout<array<2xi8>>
}

View File

@ -35,7 +35,7 @@ llhd.entity @root () -> () {
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
llhd.drv %intsig, %0 after %time : !llhd.sig<!hw.array<2xi16>>
llhd.drv %arrsig, %1 after %time : !llhd.sig<i32>
llhd.drv %structsig, %2 after %time : !llhd.sig<i32>
llhd.drv %intsig, %0 after %time : !hw.inout<array<2xi16>>
llhd.drv %arrsig, %1 after %time : !hw.inout<i32>
llhd.drv %structsig, %2 after %time : !hw.inout<i32>
}

View File

@ -31,6 +31,6 @@ llhd.entity @root () -> () {
%time = llhd.constant_time #llhd.time<1ns, 0d, 0e>
llhd.drv %structsig, %0 after %time : !llhd.sig<i32>
llhd.drv %extsig, %ext after %time : !llhd.sig<i8>
llhd.drv %structsig, %0 after %time : !hw.inout<i32>
llhd.drv %extsig, %ext after %time : !hw.inout<i8>
}

View File

@ -9,19 +9,19 @@
llhd.entity @root () -> () {
%0 = hw.constant 1 : 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
^wait:
%1 = llhd.prb %a : !llhd.sig<i1>
%1 = llhd.prb %a : !hw.inout<i1>
%allset = hw.constant 1 : i1
%0 = comb.xor %1, %allset : i1
%wt = llhd.constant_time #llhd.time<1ns, 0d, 0e>
llhd.wait for %wt, ^drive
^drive:
%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
}

View File

@ -32,13 +32,13 @@ llhd.entity @root () -> () {
%s0 = llhd.sig "sig1" %c0 : i32
%s1 = llhd.sig "sig2" %c0 : i32
%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
%nc = comb.xor %p, %allset1 : i1
llhd.drv %c, %nc after %t1 : !llhd.sig<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>
%2 = llhd.prb %s1 : !llhd.sig<i32>
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) : !hw.inout<i32>
%2 = llhd.prb %s1 : !hw.inout<i32>
%allset32 = hw.constant -1 : 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>
}

View File

@ -24,17 +24,17 @@ llhd.entity @root () -> () {
%amnt = hw.constant 1 : 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
llhd.drv %sig, %shrs after %time : !llhd.sig<i4>
llhd.drv %sig, %shrs after %time : !hw.inout<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
llhd.drv %sig1, %shru after %time : !llhd.sig<i4>
llhd.drv %sig1, %shru after %time : !hw.inout<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
llhd.drv %sig2, %shl after %time : !llhd.sig<i4>
llhd.drv %sig2, %shl after %time : !hw.inout<i4>
}

View File

@ -14,9 +14,9 @@
llhd.entity @Foo () -> () {
%0 = hw.constant 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
%2 = comb.xor %1, %allset : i1
%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>
}

View File

@ -24,10 +24,10 @@ llhd.entity @root () -> () {
%0 = hw.constant 0 : i32
%1 = llhd.sig "s1" %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
^timed:
%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
^observe:
%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
llhd.drv %a, %a0 after %t1 : !llhd.sig<i32>
llhd.drv %b, %a0 after %t2 : !llhd.sig<i32>
llhd.wait (%b : !llhd.sig<i32>), ^timed_observe
llhd.drv %a, %a0 after %t1 : !hw.inout<i32>
llhd.drv %b, %a0 after %t2 : !hw.inout<i32>
llhd.wait (%b : !hw.inout<i32>), ^timed_observe
^timed_observe:
%p1 = llhd.prb %b : !llhd.sig<i32>
%p1 = llhd.prb %b : !hw.inout<i32>
%a1 = comb.add %c0, %p1 : i32
llhd.drv %b, %a1 after %t1 : !llhd.sig<i32>
llhd.wait for %t2, (%b : !llhd.sig<i32>), ^overlap_invalidated
llhd.drv %b, %a1 after %t1 : !hw.inout<i32>
llhd.wait for %t2, (%b : !hw.inout<i32>), ^overlap_invalidated
^overlap_invalidated:
%p2 = llhd.prb %b : !llhd.sig<i32>
%p2 = llhd.prb %b : !hw.inout<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
^observe_both:
%p3 = llhd.prb %b : !llhd.sig<i32>
%p3 = llhd.prb %b : !hw.inout<i32>
%a3 = comb.add %c0, %p3 : i32
llhd.drv %a, %a3 after %t2 : !llhd.sig<i32>
llhd.drv %b, %a3 after %t1 : !llhd.sig<i32>
llhd.wait (%a, %b : !llhd.sig<i32>, !llhd.sig<i32>), ^blockArgs
llhd.drv %a, %a3 after %t2 : !hw.inout<i32>
llhd.drv %b, %a3 after %t1 : !hw.inout<i32>
llhd.wait (%a, %b : !hw.inout<i32>, !hw.inout<i32>), ^blockArgs
^blockArgs:
%p4 = llhd.prb %b : !llhd.sig<i32>
%p4 = llhd.prb %b : !hw.inout<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):
llhd.drv %b, %arg after %t2 : !llhd.sig<i32>
llhd.drv %b, %arg after %t2 : !hw.inout<i32>
llhd.halt
}

View File

@ -2,20 +2,20 @@
// RUN: circt-opt %s -llhd-early-code-motion | FileCheck %s
// 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_2:.*]] = llhd.constant_time <1ns, 0d, 0e>
// CHECK: cf.br ^bb1
// CHECK: ^bb1:
// 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: ^bb2:
// CHECK: %[[VAL_4:.*]] = llhd.load %[[VAL_3]] : !llhd.ptr<i32>
// CHECK: llhd.store %[[VAL_3]], %[[VAL_1]] : !llhd.ptr<i32>
// CHECK: llhd.halt
// CHECK: }
llhd.proc @check_dont_move_sideeffect() -> (%sig : !llhd.sig<i32>) {
llhd.proc @check_dont_move_sideeffect() -> (%sig : !hw.inout<i32>) {
// TR: -1
%c = hw.constant 4 : i32
%time = llhd.constant_time <1ns, 0d, 0e>
@ -23,7 +23,7 @@ llhd.proc @check_dont_move_sideeffect() -> (%sig : !llhd.sig<i32>) {
^bb1:
// TR: -1
%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
^bb2:
// 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
// are moved freely
// 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_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
// CHECK: cf.br ^bb1
// CHECK: ^bb1:
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i32>
// CHECK: %[[VAL_3:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
// CHECK: %[[VAL_4:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i32>
// CHECK: cf.br ^bb2
// CHECK: ^bb2:
// CHECK: llhd.wait ^bb1
// CHECK: }
llhd.proc @check_move_prb1(%sig : !llhd.sig<i32>) -> () {
llhd.proc @check_move_prb1(%sig : !hw.inout<i32>) -> () {
// TR: -1
cf.br ^bb1
^bb1:
// TR: 0
%c = hw.constant 4 : i32
%prb1 = llhd.prb %sig : !llhd.sig<i32>
%prb1 = llhd.prb %sig : !hw.inout<i32>
cf.br ^bb2
^bb2:
// TR: 0
%double = comb.add %c, %c : i32
%prb2 = llhd.prb %sig : !llhd.sig<i32>
%prb2 = llhd.prb %sig : !hw.inout<i32>
llhd.wait ^bb1
}
// 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
// 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_2:.*]] = comb.add %[[VAL_1]], %[[VAL_1]] : i32
// CHECK: cf.br ^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: ^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: }
llhd.proc @check_move_prb2(%sig : !llhd.sig<i32>) -> () {
llhd.proc @check_move_prb2(%sig : !hw.inout<i32>) -> () {
// TR: -1
cf.br ^bb1
^bb1:
// TR: 1
%c = hw.constant 4 : i32
%prb1 = llhd.prb %sig : !llhd.sig<i32>
%prb1 = llhd.prb %sig : !hw.inout<i32>
llhd.wait ^bb2
^bb2:
// TR: 0
%double = comb.add %c, %c : i32
%prb2 = llhd.prb %sig : !llhd.sig<i32>
%prb2 = llhd.prb %sig : !hw.inout<i32>
cf.br ^bb1
}
// 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: cf.br ^bb1(%[[VAL_1]] : i32)
// CHECK: ^bb1(%[[VAL_2:.*]]: i32):
// CHECK: %[[VAL_3:.*]] = comb.add %[[VAL_2]], %[[VAL_2]] : i32
// CHECK: llhd.halt
// CHECK: }
llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
llhd.proc @check_blockarg(%sig : !hw.inout<i32>) -> () {
// TR: -1
%c = hw.constant 4 : i32
cf.br ^bb1(%c : i32)
@ -110,7 +110,7 @@ llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
}
// 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_2:.*]] = hw.constant 2 : i32
// CHECK: %[[VAL_3:.*]] = hw.constant 0 : i2
@ -122,17 +122,17 @@ llhd.proc @check_blockarg(%sig : !llhd.sig<i32>) -> () {
// CHECK: ^bb2:
// CHECK: %[[VAL_6:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<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: ^bb3:
// CHECK: llhd.wait (%[[VAL_0]] : !llhd.sig<i2>), ^bb1
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^bb1
// CHECK: ^bb4:
// CHECK: %[[VAL_9:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
// CHECK: %[[VAL_10:.*]] = comb.add %[[VAL_9]], %[[VAL_4]] : i32
// CHECK: llhd.store %[[VAL_5]], %[[VAL_10]] : !llhd.ptr<i32>
// CHECK: cf.br ^bb2
// CHECK: }
llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
llhd.proc @loop(%in_i : !hw.inout<i2>) -> () {
// TR: -1
cf.br ^body
^body:
@ -148,12 +148,12 @@ llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
cf.cond_br %2, ^loop_continue, ^check
^check:
// TR: 1
llhd.wait (%in_i : !llhd.sig<i2>), ^body
llhd.wait (%in_i : !hw.inout<i2>), ^body
^loop_continue:
// TR: 1
%3 = hw.constant 0 : i2
%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>
%14 = comb.add %i_ld4, %5 : 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-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: %[[VAL_5:.*]] = hw.constant false
// CHECK: %[[VAL_6:.*]] = llhd.constant_time <0s, 1d, 0e>
// CHECK: cf.br ^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: cf.br ^bb2
// CHECK: ^bb2:
// CHECK: %[[VAL_9:.*]] = llhd.prb %[[VAL_1]] : !llhd.sig<i1>
// CHECK: %[[VAL_10:.*]] = llhd.prb %[[VAL_0]] : !llhd.sig<i1>
// CHECK: %[[VAL_9:.*]] = llhd.prb %[[VAL_1]] : !hw.inout<i1>
// CHECK: %[[VAL_10:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i1>
// CHECK: %[[VAL_11:.*]] = comb.icmp eq %[[VAL_9]], %[[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: %[[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: %[[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_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_19:.*]] = comb.and %[[VAL_18]], %[[VAL_12]] : i1
// CHECK: %[[VAL_20:.*]] = comb.or %[[VAL_16]], %[[VAL_19]] : i1
// CHECK: %[[VAL_21:.*]] = comb.icmp ne %[[VAL_17]], %[[VAL_5]] : i1
// CHECK: %[[VAL_22:.*]] = comb.xor %[[VAL_21]], %[[ALLSET]] : 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: ^bb4:
// CHECK: cf.cond_br %[[VAL_23]], ^bb6, ^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: 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: ^bb6:
// CHECK: llhd.drv %[[VAL_3]], %[[VAL_5]] after %[[VAL_6]] : !llhd.sig<i1>
// CHECK: llhd.drv %[[VAL_4]], %[[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]] : !hw.inout<i1>
// CHECK: cf.br ^bb1
// 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
// TR: -1
cf.br ^0
^0:
// 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
cf.br ^init
^init:
// TR: 2
%clk_i_prb = llhd.prb %clk_i : !llhd.sig<i1>
%rst_ni_prb = llhd.prb %rst_ni : !llhd.sig<i1>
llhd.wait (%clk_i, %rst_ni : !llhd.sig<i1>, !llhd.sig<i1>), ^check
%clk_i_prb = llhd.prb %clk_i : !hw.inout<i1>
%rst_ni_prb = llhd.prb %rst_ni : !hw.inout<i1>
llhd.wait (%clk_i, %rst_ni : !hw.inout<i1>, !hw.inout<i1>), ^check
^check:
// 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>
%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
%4 = comb.icmp eq %clk_i_prb, %3 : i1
%5 = comb.icmp ne %clk_i_prb1, %3 : 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
%7 = comb.icmp eq %rst_ni_prb1, %3 : 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
^if_false:
// TR: 0
%async_ack_i_prb = llhd.prb %async_ack_i : !llhd.sig<i1>
llhd.drv %ack_src_q, %async_ack_i_prb after %11 : !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 : !hw.inout<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
^if_true:
// TR: 0
llhd.drv %ack_src_q, %3 after %11 : !llhd.sig<i1>
llhd.drv %ack_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 : !hw.inout<i1>
cf.br ^0
}

View File

@ -247,7 +247,7 @@ llhd.proc @multiple_store_one_block() -> () {
}
// CHECK-LABEL: llhd.proc @loop(
// CHECK-SAME: %[[VAL_0:.*]] : !llhd.sig<i2>) -> () {
// CHECK-SAME: %[[VAL_0:.*]] : !hw.inout<i2>) -> () {
// CHECK: cf.br ^bb1
// CHECK: ^bb1:
// 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: cf.cond_br %[[VAL_4]], ^bb4, ^bb3
// CHECK: ^bb3:
// CHECK: llhd.wait (%[[VAL_0]] : !llhd.sig<i2>), ^bb1
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^bb1
// CHECK: ^bb4:
// CHECK: %[[VAL_5:.*]] = hw.constant 0 : i2
// CHECK: %[[VAL_6:.*]] = hw.constant 1 : i32
// CHECK: %[[VAL_7:.*]] = comb.add %[[VAL_2]], %[[VAL_6]] : i32
// CHECK: cf.br ^bb2(%[[VAL_7]] : i32)
// CHECK: }
llhd.proc @loop(%in_i : !llhd.sig<i2>) -> () {
llhd.proc @loop(%in_i : !hw.inout<i2>) -> () {
cf.br ^body
^body:
%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
cf.cond_br %2, ^loop_continue, ^check
^check:
llhd.wait (%in_i : !llhd.sig<i2>), ^body
llhd.wait (%in_i : !hw.inout<i2>), ^body
^loop_continue:
%3 = hw.constant 0 : i2
%5 = hw.constant 1 : i32

View File

@ -8,8 +8,8 @@ llhd.proc @empty() -> () {
}
// check that input and output signals are transferred correctly
// CHECK-NEXT: llhd.entity @inputAndOutput (%{{.*}} : !llhd.sig<i64>, %{{.*}} : !llhd.sig<i1>) -> (%{{.*}} : !llhd.sig<i1>) {
llhd.proc @inputAndOutput(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i1>) -> (%arg2 : !llhd.sig<i1>) {
// CHECK-NEXT: llhd.entity @inputAndOutput (%{{.*}} : !hw.inout<i64>, %{{.*}} : !hw.inout<i1>) -> (%{{.*}} : !hw.inout<i1>) {
llhd.proc @inputAndOutput(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i1>) -> (%arg2 : !hw.inout<i1>) {
// CHECK-NEXT: }
llhd.halt
}
@ -24,29 +24,29 @@ llhd.proc @simpleWait() -> () {
}
// Check wait with observing probed signals
// CHECK-NEXT: llhd.entity @prbAndWait (%{{.*}} : !llhd.sig<i64>) -> () {
llhd.proc @prbAndWait(%arg0 : !llhd.sig<i64>) -> () {
// CHECK-NEXT: llhd.entity @prbAndWait (%{{.*}} : !hw.inout<i64>) -> () {
llhd.proc @prbAndWait(%arg0 : !hw.inout<i64>) -> () {
// CHECK-NEXT: %{{.*}} = llhd.prb
// CHECK-NEXT: }
cf.br ^bb1
^bb1:
%0 = llhd.prb %arg0 : !llhd.sig<i64>
llhd.wait (%arg0 : !llhd.sig<i64>), ^bb1
%0 = llhd.prb %arg0 : !hw.inout<i64>
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
}
// Check wait with observing probed signals
// CHECK-NEXT: llhd.entity @prbAndWaitMoreObserved (%{{.*}} : !llhd.sig<i64>, %{{.*}} : !llhd.sig<i64>) -> () {
llhd.proc @prbAndWaitMoreObserved(%arg0 : !llhd.sig<i64>, %arg1 : !llhd.sig<i64>) -> () {
// CHECK-NEXT: llhd.entity @prbAndWaitMoreObserved (%{{.*}} : !hw.inout<i64>, %{{.*}} : !hw.inout<i64>) -> () {
llhd.proc @prbAndWaitMoreObserved(%arg0 : !hw.inout<i64>, %arg1 : !hw.inout<i64>) -> () {
// CHECK-NEXT: %{{.*}} = llhd.prb
// CHECK-NEXT: }
cf.br ^bb1
^bb1:
%0 = llhd.prb %arg0 : !llhd.sig<i64>
llhd.wait (%arg0, %arg1 : !llhd.sig<i64>, !llhd.sig<i64>), ^bb1
%0 = llhd.prb %arg0 : !hw.inout<i64>
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
}
// 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
^bb1:
// 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: }
%cond = hw.constant true
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
%0 = llhd.prb %sig : !llhd.sig<i64>
llhd.wait (%arg0, %arg1 : !llhd.sig<i64>, !llhd.sig<i64>), ^bb1
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
%0 = llhd.prb %sig : !hw.inout<i64>
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
}
// 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
^bb1:
// 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: }
%cond = hw.constant true
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
%0 = llhd.prb %sig : !llhd.sig<i64>
llhd.wait (%sig : !llhd.sig<i64>), ^bb1
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
%0 = llhd.prb %sig : !hw.inout<i64>
llhd.wait (%sig : !hw.inout<i64>), ^bb1
}
// CHECK-NEXT: llhd.entity @partialSignal
llhd.proc @partialSignal(%arg0 : !llhd.sig<i64>) -> () {
llhd.proc @partialSignal(%arg0 : !hw.inout<i64>) -> () {
cf.br ^bb1
^bb1:
// CHECK-NEXT: %{{.*}} = hw.constant
@ -82,7 +82,7 @@ llhd.proc @partialSignal(%arg0 : !llhd.sig<i64>) -> () {
// CHECK-NEXT: %{{.*}} = llhd.prb
// CHECK-NEXT: }
%c = hw.constant 16 : i6
%sig = llhd.sig.extract %arg0 from %c : (!llhd.sig<i64>) -> !llhd.sig<i32>
%0 = llhd.prb %sig : !llhd.sig<i32>
llhd.wait (%arg0 : !llhd.sig<i64>), ^bb1
%sig = llhd.sig.extract %arg0 from %c : (!hw.inout<i64>) -> !hw.inout<i32>
%0 = llhd.prb %sig : !hw.inout<i32>
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
}

View File

@ -1,10 +1,10 @@
// RUN: circt-opt %s -llhd-process-lowering -split-input-file -verify-diagnostics
// Check wait with observing probed signals
llhd.proc @prbAndWaitNotObserved(%arg0 : !llhd.sig<i64>) -> () {
llhd.proc @prbAndWaitNotObserved(%arg0 : !hw.inout<i64>) -> () {
cf.br ^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}}
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.
// 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>) -> () {
cf.br ^bb1(%arg0 : !llhd.sig<i64>)
^bb1(%a : !llhd.sig<i64>):
llhd.wait ^bb1(%a : !llhd.sig<i64>)
llhd.proc @blockArgumentsNotAllowed(%arg0 : !hw.inout<i64>) -> () {
cf.br ^bb1(%arg0 : !hw.inout<i64>)
^bb1(%a : !hw.inout<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
^bb1:
%cond = llhd.prb %arg2 : !llhd.sig<i1>
%sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig<i64>
%0 = llhd.prb %sig : !llhd.sig<i64>
%cond = llhd.prb %arg2 : !hw.inout<i1>
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<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}}
llhd.wait (%arg0, %arg2 : !llhd.sig<i64>, !llhd.sig<i1>), ^bb1
llhd.wait (%arg0, %arg2 : !hw.inout<i64>, !hw.inout<i1>), ^bb1
}

View File

@ -24,18 +24,18 @@ func.func @complex(%flag : i1) -> i32 {
}
// 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: %{{.*}} = llhd.constant_time
// CHECK-NEXT: llhd.drv
// CHECK-NEXT: }
%1 = func.call @simple() : () -> i32
%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
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: cf.cond_br %[[PRB]], ^[[BB1:.*]], ^[[BB2:.*]]
// 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: ^[[BB3]](%[[A:.*]]: i32):
// 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: }
%0 = llhd.prb %arg : !llhd.sig<i1>
%0 = llhd.prb %arg : !hw.inout<i1>
%1 = func.call @complex(%0) : (i1) -> i32
%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
}

View File

@ -62,7 +62,6 @@ target_link_libraries(circt-opt
CIRCTIbis
CIRCTIbisTransforms
CIRCTInteropDialect
CIRCTHWToLLHD
CIRCTHWToSMT
CIRCTHWToSystemC
CIRCTHWToSV