mirror of https://github.com/llvm/circt.git
[Moore] Distinguish the dynamic and constant extract. (#7340)
Divide the extract into a dynamic extract named moore.dyn_extract and a constant extract named moore.extract, the former has a variable as its low bit like arr[x], but the latter has a constant value as its low bit like arr[1]. Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
This commit is contained in:
parent
10180d3ca2
commit
6a634ae429
|
@ -924,9 +924,10 @@ def ReplicateOp : MooreOp<"replicate", [
|
|||
}];
|
||||
}
|
||||
|
||||
def ExtractOp : MooreOp<"extract"> {
|
||||
let summary = "Addressing operation";
|
||||
def ExtractOp : MooreOp<"extract", [Pure]> {
|
||||
let summary = "Extract a range or single bits from a value";
|
||||
let description = [{
|
||||
It's used to select from a value with a constant low bit.
|
||||
This operation includes the vector bit/part-select, array, and memory
|
||||
addressing.If the address is invalid--out of bounds or has x or z bit--
|
||||
then it will produce x for 4-state or 0 for 2-state.
|
||||
|
@ -952,6 +953,18 @@ def ExtractOp : MooreOp<"extract"> {
|
|||
```
|
||||
See IEEE 1800-2017 § 11.5.2 "Array and memory addressing".
|
||||
}];
|
||||
let arguments = (ins UnpackedType:$input, I32Attr:$lowBit);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
$input `from` $lowBit attr-dict `:` type($input) `->` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
def DynExtractOp : MooreOp<"dyn_extract", [Pure]> {
|
||||
let description = [{
|
||||
It's similar with extract, but it's used to select from a value
|
||||
with a dynamic low bit.
|
||||
}];
|
||||
let arguments = (ins UnpackedType:$input, UnpackedType:$lowBit);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
|
@ -960,8 +973,21 @@ def ExtractOp : MooreOp<"extract"> {
|
|||
}];
|
||||
}
|
||||
|
||||
def ExtractRefOp : MooreOp<"extract_ref"> {
|
||||
let summary = "The copy of extract that explicitly works on the ref type.";
|
||||
def ExtractRefOp : MooreOp<"extract_ref", [Pure]> {
|
||||
let description = [{
|
||||
The copy of extract that explicitly works on the ref type.
|
||||
}];
|
||||
let arguments = (ins RefType:$input, I32Attr:$lowBit);
|
||||
let results = (outs RefType:$result);
|
||||
let assemblyFormat = [{
|
||||
$input `from` $lowBit attr-dict `:` type($input) `->` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
def DynExtractRefOp : MooreOp<"dyn_extract_ref", [Pure]> {
|
||||
let description = [{
|
||||
The copy of dyn_extract that explicitly works on the ref type.
|
||||
}];
|
||||
let arguments = (ins RefType:$input, UnpackedType:$lowBit);
|
||||
let results = (outs RefType:$result);
|
||||
let assemblyFormat = [{
|
||||
|
|
|
@ -440,24 +440,47 @@ struct RvalueExprVisitor {
|
|||
Value visit(const slang::ast::ElementSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertRvalueExpression(expr.value());
|
||||
auto lowBit = context.convertRvalueExpression(expr.selector());
|
||||
|
||||
if (!type || !value || !lowBit)
|
||||
if (!type || !value)
|
||||
return {};
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
if (auto *constValue = expr.selector().constant) {
|
||||
assert(!constValue->hasUnknown());
|
||||
assert(constValue->size() <= 32);
|
||||
|
||||
auto lowBit = constValue->integer().as<uint32_t>().value();
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
}
|
||||
auto lowBit = context.convertRvalueExpression(expr.selector());
|
||||
if (!lowBit)
|
||||
return {};
|
||||
return builder.create<moore::DynExtractOp>(loc, type, value, lowBit);
|
||||
}
|
||||
|
||||
// Handle range bits selections.
|
||||
Value visit(const slang::ast::RangeSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertRvalueExpression(expr.value());
|
||||
Value lowBit;
|
||||
if (!type || !value)
|
||||
return {};
|
||||
|
||||
Value dynLowBit;
|
||||
uint32_t constLowBit;
|
||||
auto *leftConst = expr.left().constant;
|
||||
auto *rightConst = expr.right().constant;
|
||||
if (leftConst) {
|
||||
assert(!leftConst->hasUnknown());
|
||||
assert(leftConst->size() <= 32);
|
||||
}
|
||||
if (rightConst) {
|
||||
assert(!rightConst->hasUnknown());
|
||||
assert(rightConst->size() <= 32);
|
||||
}
|
||||
|
||||
if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
|
||||
if (expr.left().constant && expr.right().constant) {
|
||||
auto lhs = expr.left().constant->integer().as<uint64_t>().value();
|
||||
auto rhs = expr.right().constant->integer().as<uint64_t>().value();
|
||||
lowBit = lhs < rhs ? context.convertRvalueExpression(expr.left())
|
||||
: context.convertRvalueExpression(expr.right());
|
||||
if (leftConst && rightConst) {
|
||||
// Estimate whether is big endian or little endian.
|
||||
auto lhs = leftConst->integer().as<uint32_t>().value();
|
||||
auto rhs = rightConst->integer().as<uint32_t>().value();
|
||||
constLowBit = lhs < rhs ? lhs : rhs;
|
||||
} else {
|
||||
mlir::emitError(loc, "unsupported a variable as the index in the")
|
||||
<< slang::ast::toString(expr.getSelectionKind()) << "kind";
|
||||
|
@ -468,23 +491,33 @@ struct RvalueExprVisitor {
|
|||
// IndexedDown: arr[7-:8]. It's equivalent to arr[7:0] or arr[0:7]
|
||||
// depending on little endian or bit endian. No matter which situation,
|
||||
// the low bit must be "0".
|
||||
auto minuend = context.convertRvalueExpression(expr.left());
|
||||
auto minuendType = cast<moore::UnpackedType>(minuend.getType());
|
||||
auto intType = moore::IntType::get(context.getContext(),
|
||||
minuendType.getBitSize().value(),
|
||||
minuendType.getDomain());
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint64_t>().value() - 1;
|
||||
auto subtraction =
|
||||
builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
|
||||
lowBit = builder.create<moore::SubOp>(loc, minuend, subtraction);
|
||||
} else
|
||||
if (leftConst) {
|
||||
auto subtrahend = leftConst->integer().as<uint32_t>().value();
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint32_t>().value();
|
||||
constLowBit = subtrahend - sliceWidth - 1;
|
||||
} else {
|
||||
auto subtrahend = context.convertRvalueExpression(expr.left());
|
||||
auto subtrahendType = cast<moore::UnpackedType>(subtrahend.getType());
|
||||
auto intType = moore::IntType::get(context.getContext(),
|
||||
subtrahendType.getBitSize().value(),
|
||||
subtrahendType.getDomain());
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint32_t>().value() - 1;
|
||||
auto minuend =
|
||||
builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
|
||||
dynLowBit = builder.create<moore::SubOp>(loc, subtrahend, minuend);
|
||||
}
|
||||
} else {
|
||||
// IndexedUp: arr[0+:8]. "0" is the low bit, "8" is the bits slice width.
|
||||
lowBit = context.convertRvalueExpression(expr.left());
|
||||
|
||||
if (!type || !value || !lowBit)
|
||||
return {};
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
if (leftConst)
|
||||
constLowBit = leftConst->integer().as<uint32_t>().value();
|
||||
else
|
||||
dynLowBit = context.convertRvalueExpression(expr.left());
|
||||
}
|
||||
if (leftConst && rightConst)
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, constLowBit);
|
||||
return builder.create<moore::DynExtractOp>(loc, type, value, dynLowBit);
|
||||
}
|
||||
|
||||
Value visit(const slang::ast::MemberAccessExpression &expr) {
|
||||
|
@ -746,15 +779,94 @@ struct LvalueExprVisitor {
|
|||
Value visit(const slang::ast::ElementSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertLvalueExpression(expr.value());
|
||||
auto lowBit = context.convertRvalueExpression(expr.selector());
|
||||
|
||||
if (!type || !value || !lowBit)
|
||||
if (!type || !value)
|
||||
return {};
|
||||
return builder.create<moore::ExtractRefOp>(
|
||||
if (auto *constValue = expr.selector().constant) {
|
||||
assert(!constValue->hasUnknown());
|
||||
assert(constValue->size() <= 32);
|
||||
|
||||
auto lowBit = constValue->integer().as<uint32_t>().value();
|
||||
return builder.create<moore::ExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(type)), value,
|
||||
lowBit);
|
||||
}
|
||||
auto lowBit = context.convertRvalueExpression(expr.selector());
|
||||
if (!lowBit)
|
||||
return {};
|
||||
return builder.create<moore::DynExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(type)), value,
|
||||
lowBit);
|
||||
}
|
||||
|
||||
// Handle range bits selections.
|
||||
Value visit(const slang::ast::RangeSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertLvalueExpression(expr.value());
|
||||
if (!type || !value)
|
||||
return {};
|
||||
|
||||
Value dynLowBit;
|
||||
uint32_t constLowBit;
|
||||
auto *leftConst = expr.left().constant;
|
||||
auto *rightConst = expr.right().constant;
|
||||
if (leftConst) {
|
||||
assert(!leftConst->hasUnknown());
|
||||
assert(leftConst->size() <= 32);
|
||||
}
|
||||
if (rightConst) {
|
||||
assert(!rightConst->hasUnknown());
|
||||
assert(rightConst->size() <= 32);
|
||||
}
|
||||
|
||||
if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
|
||||
if (leftConst && rightConst) {
|
||||
// Estimate whether is big endian or little endian.
|
||||
auto lhs = leftConst->integer().as<uint32_t>().value();
|
||||
auto rhs = rightConst->integer().as<uint32_t>().value();
|
||||
constLowBit = lhs < rhs ? lhs : rhs;
|
||||
} else {
|
||||
mlir::emitError(loc, "unsupported a variable as the index in the")
|
||||
<< slang::ast::toString(expr.getSelectionKind()) << "kind";
|
||||
return {};
|
||||
}
|
||||
} else if (expr.getSelectionKind() ==
|
||||
slang::ast::RangeSelectionKind::IndexedDown) {
|
||||
// IndexedDown: arr[7-:8]. It's equivalent to arr[7:0] or arr[0:7]
|
||||
// depending on little endian or bit endian. No matter which situation,
|
||||
// the low bit must be "0".
|
||||
if (leftConst) {
|
||||
auto subtrahend = leftConst->integer().as<uint32_t>().value();
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint32_t>().value();
|
||||
constLowBit = subtrahend - sliceWidth - 1;
|
||||
} else {
|
||||
auto subtrahend = context.convertRvalueExpression(expr.left());
|
||||
auto subtrahendType = cast<moore::UnpackedType>(subtrahend.getType());
|
||||
auto intType = moore::IntType::get(context.getContext(),
|
||||
subtrahendType.getBitSize().value(),
|
||||
subtrahendType.getDomain());
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint32_t>().value() - 1;
|
||||
auto minuend =
|
||||
builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
|
||||
dynLowBit = builder.create<moore::SubOp>(loc, subtrahend, minuend);
|
||||
}
|
||||
} else {
|
||||
// IndexedUp: arr[0+:8]. "0" is the low bit, "8" is the bits slice width.
|
||||
if (leftConst)
|
||||
constLowBit = leftConst->integer().as<uint32_t>().value();
|
||||
else
|
||||
dynLowBit = context.convertRvalueExpression(expr.left());
|
||||
}
|
||||
if (leftConst && rightConst)
|
||||
return builder.create<moore::ExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(type)), value,
|
||||
constLowBit);
|
||||
return builder.create<moore::DynExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(type)), value,
|
||||
dynLowBit);
|
||||
}
|
||||
|
||||
Value visit(const slang::ast::MemberAccessExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto valueType = expr.value().type;
|
||||
|
@ -776,48 +888,6 @@ struct LvalueExprVisitor {
|
|||
return {};
|
||||
}
|
||||
|
||||
// Handle range bits selections.
|
||||
Value visit(const slang::ast::RangeSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertLvalueExpression(expr.value());
|
||||
Value lowBit;
|
||||
if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
|
||||
if (expr.left().constant && expr.right().constant) {
|
||||
auto lhs = expr.left().constant->integer().as<uint64_t>().value();
|
||||
auto rhs = expr.right().constant->integer().as<uint64_t>().value();
|
||||
lowBit = lhs < rhs ? context.convertRvalueExpression(expr.left())
|
||||
: context.convertRvalueExpression(expr.right());
|
||||
} else {
|
||||
mlir::emitError(loc, "unsupported a variable as the index in the")
|
||||
<< slang::ast::toString(expr.getSelectionKind()) << "kind";
|
||||
return {};
|
||||
}
|
||||
} else if (expr.getSelectionKind() ==
|
||||
slang::ast::RangeSelectionKind::IndexedDown) {
|
||||
// IndexedDown: arr[7-:8]. It's equivalent to arr[7:0] or arr[0:7]
|
||||
// depending on little endian or bit endian. No matter which situation,
|
||||
// the low bit must be "0".
|
||||
auto minuend = context.convertRvalueExpression(expr.left());
|
||||
auto minuendType = cast<moore::UnpackedType>(minuend.getType());
|
||||
auto intType = moore::IntType::get(context.getContext(),
|
||||
minuendType.getBitSize().value(),
|
||||
minuendType.getDomain());
|
||||
auto sliceWidth =
|
||||
expr.right().constant->integer().as<uint64_t>().value() - 1;
|
||||
auto subtraction =
|
||||
builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
|
||||
lowBit = builder.create<moore::SubOp>(loc, minuend, subtraction);
|
||||
} else
|
||||
// IndexedUp: arr[0+:8]. "0" is the low bit, "8" is the bits slice width.
|
||||
lowBit = context.convertRvalueExpression(expr.left());
|
||||
|
||||
if (!type || !value || !lowBit)
|
||||
return {};
|
||||
return builder.create<moore::ExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(type)), value,
|
||||
lowBit);
|
||||
}
|
||||
|
||||
/// Emit an error for all other expressions.
|
||||
template <typename T>
|
||||
Value visit(T &&node) {
|
||||
|
|
|
@ -300,19 +300,17 @@ struct ModuleVisitor : public BaseVisitor {
|
|||
if (!value)
|
||||
return failure();
|
||||
unsigned offset = 0;
|
||||
auto i32 = moore::IntType::getInt(context.getContext(), 32);
|
||||
for (const auto *port : llvm::reverse(multiPort->ports)) {
|
||||
if (auto *existingPort = moduleLowering->portsBySyntaxNode.lookup(
|
||||
con->port.getSyntax()))
|
||||
port = existingPort;
|
||||
unsigned width = port->getType().getBitWidth();
|
||||
auto index = builder.create<moore::ConstantOp>(loc, i32, offset);
|
||||
auto sliceType = context.convertType(port->getType());
|
||||
if (!sliceType)
|
||||
return failure();
|
||||
Value slice = builder.create<moore::ExtractRefOp>(
|
||||
loc, moore::RefType::get(cast<moore::UnpackedType>(sliceType)),
|
||||
value, index);
|
||||
value, offset);
|
||||
// Read to map to rvalue for input ports.
|
||||
if (port->direction == slang::ast::ArgumentDirection::In)
|
||||
slice = builder.create<moore::ReadOp>(loc, sliceType, slice);
|
||||
|
|
|
@ -244,6 +244,19 @@ struct ExtractOpConversion : public OpConversionPattern<ExtractOp> {
|
|||
matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
|
||||
ConversionPatternRewriter &rewriter) const override {
|
||||
Type resultType = typeConverter->convertType(op.getResult().getType());
|
||||
rewriter.replaceOpWithNewOp<comb::ExtractOp>(
|
||||
op, resultType, adaptor.getInput(), adaptor.getLowBit());
|
||||
return success();
|
||||
}
|
||||
};
|
||||
|
||||
struct DynExtractOpConversion : public OpConversionPattern<DynExtractOp> {
|
||||
using OpConversionPattern::OpConversionPattern;
|
||||
|
||||
LogicalResult
|
||||
matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
|
||||
ConversionPatternRewriter &rewriter) const override {
|
||||
Type resultType = typeConverter->convertType(op.getResult().getType());
|
||||
auto width = typeConverter->convertType(op.getInput().getType())
|
||||
.getIntOrFloatBitWidth();
|
||||
Value amount =
|
||||
|
@ -684,8 +697,8 @@ static void populateOpConversion(RewritePatternSet &patterns,
|
|||
|
||||
// Patterns of miscellaneous operations.
|
||||
ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
|
||||
ExtractOpConversion, ConversionOpConversion, ReadOpConversion,
|
||||
NamedConstantOpConv,
|
||||
ExtractOpConversion, DynExtractOpConversion, ConversionOpConversion,
|
||||
ReadOpConversion, NamedConstantOpConv,
|
||||
|
||||
// Patterns of unary operations.
|
||||
ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
|
||||
|
|
|
@ -64,11 +64,8 @@ struct ConcatRefLowering : public OpConversionPattern<OpTy> {
|
|||
// small or vice versa. Like "logic [7:0] or [0:7]".
|
||||
|
||||
// Only able to correctly handle the situation like "[7:0]" now.
|
||||
auto i32 = moore::IntType::getInt(op.getContext(), 32);
|
||||
auto lowBit =
|
||||
rewriter.create<ConstantOp>(op.getLoc(), i32, srcWidth - width);
|
||||
auto extract =
|
||||
rewriter.create<ExtractOp>(op.getLoc(), type, op.getSrc(), lowBit);
|
||||
auto extract = rewriter.create<ExtractOp>(op.getLoc(), type, op.getSrc(),
|
||||
srcWidth - width);
|
||||
|
||||
// Update the real bit width of RHS of assignment. Like "c" the above
|
||||
// description mentioned.
|
||||
|
|
|
@ -501,33 +501,28 @@ module Expressions;
|
|||
// CHECK: [[TMP2:%.+]] = moore.concat [[TMP1]] : (!moore.i1) -> i1
|
||||
// CHECK: moore.replicate [[TMP2]] : i1 -> i32
|
||||
a = {32{1'b0}};
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 1 : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l3
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 1 : l32 -> l3
|
||||
y = vec_1[3:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 2 : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l2
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 2 : l32 -> l2
|
||||
y = vec_2[2:3];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %d
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i1 -> l1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %d : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x : <i1>
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP2]] : l32, i1 -> l1
|
||||
y = d[x];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : i32, i1 -> i1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a : <i32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x : <i1>
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP2]] : i32, i1 -> i1
|
||||
x = a[x];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 15 : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 15 : l32 -> l1
|
||||
y = vec_1[15];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 15 : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 15 : l32 -> l1
|
||||
y = vec_1[15+:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 0 : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 0 : l32 -> l1
|
||||
y = vec_2[0+:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 1 : i32
|
||||
|
@ -535,39 +530,30 @@ module Expressions;
|
|||
// CHECK: [[TMP4:%.+]] = moore.mul [[TMP2]], [[TMP3]] : i32
|
||||
// CHECK: [[TMP5:%.+]] = moore.constant 0 : i32
|
||||
// CHECK: [[TMP6:%.+]] = moore.sub [[TMP4]], [[TMP5]] : i32
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP6]] : l32, i32 -> l1
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP6]] : l32, i32 -> l1
|
||||
c = vec_1[1*a-:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %arr
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 3 : i32
|
||||
// CHECK: [[TMP3:%.+]] = moore.extract [[TMP1]] from [[TMP2]] : uarray<3 x uarray<6 x i4>>, i32 -> uarray<6 x i4>
|
||||
// CHECK: [[TMP4:%.+]] = moore.constant 7 : i32
|
||||
// CHECK: [[TMP5:%.+]] = moore.extract [[TMP3]] from [[TMP4]] : uarray<6 x i4>, i32 -> i4
|
||||
// CHECK: [[TMP6:%.+]] = moore.constant 3 : i32
|
||||
// CHECK: moore.extract [[TMP5]] from [[TMP6]] : i4, i32 -> i2
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %arr : <uarray<3 x uarray<6 x i4>>>
|
||||
// CHECK: [[TMP3:%.+]] = moore.extract [[TMP1]] from 3 : uarray<3 x uarray<6 x i4>> -> uarray<6 x i4>
|
||||
// CHECK: [[TMP5:%.+]] = moore.extract [[TMP3]] from 7 : uarray<6 x i4> -> i4
|
||||
// CHECK: moore.extract [[TMP5]] from 3 : i4 -> i2
|
||||
c = arr[3][7][4:3];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %c
|
||||
// CHECK: moore.extract [[TMP1]] from [[TMP2]] : l32, i32 -> l1
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %c : <i32>
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP2]] : l32, i32 -> l1
|
||||
y = vec_1[c];
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.constant 1 : i32
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %v from [[TMP1]] : <array<2 x i4>>, i32 -> <i4>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 3 : i32
|
||||
// CHECK: moore.extract_ref [[TMP2]] from [[TMP3]] : <i4>, i32 -> <i1>
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %v from 1 : <array<2 x i4>> -> <i4>
|
||||
// CHECK: moore.extract_ref [[TMP2]] from 3 : <i4> -> <i1>
|
||||
v[1][3] = x;
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.constant 1 : i32
|
||||
// CHECK: moore.extract_ref %vec_1 from [[TMP1]] : <l32>, i32 -> <l2>
|
||||
// CHECK: moore.extract_ref %vec_1 from 1 : <l32> -> <l2>
|
||||
vec_1[2:1] = y;
|
||||
|
||||
// CHECK: [[X_READ:%.+]] = moore.read %x
|
||||
// CHECK: moore.extract_ref %vec_1 from [[X_READ]] : <l32>, i1 -> <l1>
|
||||
// CHECK: [[X_READ:%.+]] = moore.read %x : <i1>
|
||||
// CHECK: moore.dyn_extract_ref %vec_1 from [[X_READ]] : <l32>, i1 -> <l1>
|
||||
vec_1[x] = y;
|
||||
|
||||
// CHECK: [[CONST_15:%.+]] = moore.constant 15 : i32
|
||||
// CHECK: [[CONST_2:%.+]] = moore.constant 2 : i32
|
||||
// CHECK: [[SUB:%.+]] = moore.sub [[CONST_15]], [[CONST_2]] : i32
|
||||
// CHECK: moore.extract_ref %vec_1 from [[SUB]] : <l32>, i32 -> <l3>
|
||||
// CHECK: moore.extract_ref %vec_1 from 11 : <l32> -> <l3>
|
||||
vec_1[15-:3] = y;
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
|
@ -1120,17 +1106,12 @@ module PortsTop;
|
|||
wire [1:0] w3;
|
||||
// CHECK: [[X3:%.+]] = moore.read %x3
|
||||
// CHECK: [[Y3:%.+]] = moore.read %y3
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 0 :
|
||||
// CHECK: [[V2:%.+]] = moore.extract_ref %z3 from [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 :
|
||||
// CHECK: [[V1:%.+]] = moore.extract_ref %z3 from [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 :
|
||||
// CHECK: [[V0:%.+]] = moore.extract_ref %z3 from [[TMP]]
|
||||
// CHECK: [[V2:%.+]] = moore.extract_ref %z3 from 0
|
||||
// CHECK: [[V1:%.+]] = moore.extract_ref %z3 from 1
|
||||
// CHECK: [[V0:%.+]] = moore.extract_ref %z3 from 2
|
||||
// CHECK: [[V0_READ:%.+]] = moore.read [[V0]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 0 :
|
||||
// CHECK: [[C1:%.+]] = moore.extract_ref %w3 from [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 :
|
||||
// CHECK: [[C0:%.+]] = moore.extract_ref %w3 from [[TMP]]
|
||||
// CHECK: [[C1:%.+]] = moore.extract_ref %w3 from 0
|
||||
// CHECK: [[C0:%.+]] = moore.extract_ref %w3 from 1
|
||||
// CHECK: [[C0_READ:%.+]] = moore.read [[C0]]
|
||||
// CHECK: [[V1_VALUE:%.+]], [[C1_VALUE:%.+]] = moore.instance "p3" @MultiPorts(
|
||||
// CHECK-SAME: a0: [[X3]]: !moore.l1
|
||||
|
@ -1258,12 +1239,10 @@ module MultiPorts(
|
|||
input c0;
|
||||
output c1;
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.constant 0 :
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %u from [[TMP1]]
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %u from 0
|
||||
// CHECK: moore.assign [[TMP2]], %a0
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.constant 1 :
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %u from [[TMP1]]
|
||||
// CHECK: [[TMP2:%.+]] = moore.extract_ref %u from 1
|
||||
// CHECK: moore.assign [[TMP2]], %a1
|
||||
|
||||
// CHECK: moore.assign [[V0]], %v0
|
||||
|
|
|
@ -99,25 +99,18 @@ func.func @Expressions(%arg0: !moore.i1, %arg1: !moore.l1, %arg2: !moore.i6, %ar
|
|||
// CHECK-NEXT: %c2_i32 = hw.constant 2 : i32
|
||||
%2 = moore.constant 2 : !moore.i32
|
||||
|
||||
// CHECK-NEXT: [[V16:%.+]] = comb.extract %c2_i32 from 6 : (i32) -> i26
|
||||
// CHECK-NEXT: %c0_i26 = hw.constant 0 : i26
|
||||
// CHECK-NEXT: [[V17:%.+]] = comb.icmp eq [[V16]], %c0_i26 : i26
|
||||
// CHECK-NEXT: [[V18:%.+]] = comb.extract %c2_i32 from 0 : (i32) -> i6
|
||||
// CHECK-NEXT: %c-1_i6 = hw.constant -1 : i6
|
||||
// CHECK-NEXT: [[V19:%.+]] = comb.mux [[V17]], [[V18]], %c-1_i6 : i6
|
||||
// CHECK-NEXT: [[V20:%.+]] = comb.shru %arg2, [[V19]] : i6
|
||||
// CHECK-NEXT: comb.extract [[V20]] from 0 : (i6) -> i2
|
||||
moore.extract %arg2 from %2 : !moore.i6, !moore.i32 -> !moore.i2
|
||||
// CHECK-NEXT: comb.extract %arg2 from 2 : (i6) -> i2
|
||||
moore.extract %arg2 from 2 : !moore.i6 -> !moore.i2
|
||||
|
||||
// CHECK-NEXT: [[V21:%.+]] = comb.extract %c2_i32 from 6 : (i32) -> i26
|
||||
// CHECK-NEXT: %c0_i26_3 = hw.constant 0 : i26
|
||||
// CHECK-NEXT: [[V22:%.+]] = comb.icmp eq [[V21]], %c0_i26_3 : i26
|
||||
// CHECK-NEXT: [[CONST_0:%.+]] = hw.constant 0 : i26
|
||||
// CHECK-NEXT: [[V22:%.+]] = comb.icmp eq [[V21]], [[CONST_0]] : i26
|
||||
// CHECK-NEXT: [[V23:%.+]] = comb.extract %c2_i32 from 0 : (i32) -> i6
|
||||
// CHECK-NEXT: %c-1_i6_4 = hw.constant -1 : i6
|
||||
// CHECK-NEXT: [[V24:%.+]] = comb.mux [[V22]], [[V23]], %c-1_i6_4 : i6
|
||||
// CHECK-NEXT: [[MAX:%.+]] = hw.constant -1 : i6
|
||||
// CHECK-NEXT: [[V24:%.+]] = comb.mux [[V22]], [[V23]], [[MAX]] : i6
|
||||
// CHECK-NEXT: [[V25:%.+]] = comb.shru %arg2, [[V24]] : i6
|
||||
// CHECK-NEXT: comb.extract [[V25]] from 0 : (i6) -> i1
|
||||
moore.extract %arg2 from %2 : !moore.i6, !moore.i32 -> !moore.i1
|
||||
moore.dyn_extract %arg2 from %2 : !moore.i6, !moore.i32 -> !moore.i1
|
||||
|
||||
// CHECK-NEXT: [[V26:%.+]] = hw.constant -1 : i6
|
||||
// CHECK-NEXT: comb.icmp eq %arg2, [[V26]] : i6
|
||||
|
|
|
@ -245,19 +245,19 @@ moore.module @Expressions(
|
|||
// CHECK: moore.replicate [[X]] : i1 -> i4
|
||||
moore.replicate %x : i1 -> i4
|
||||
|
||||
// CHECK: moore.extract [[A]] from [[B]] : i32, i32 -> i1
|
||||
moore.extract %a from %b : i32, i32 -> i1
|
||||
// CHECK: moore.extract [[ARRAY2]] from [[A]] : uarray<2 x uarray<4 x i8>>, i32 -> uarray<4 x i8>
|
||||
moore.extract %array2 from %a : uarray<2 x uarray<4 x i8>>, i32 -> uarray<4 x i8>
|
||||
// CHECK: moore.extract [[ARRAY1]] from [[A]] : uarray<4 x i8>, i32 -> i8
|
||||
moore.extract %array1 from %a : uarray<4 x i8>, i32 -> i8
|
||||
// CHECK: moore.dyn_extract [[A]] from [[B]] : i32, i32 -> i1
|
||||
moore.dyn_extract %a from %b : i32, i32 -> i1
|
||||
// CHECK: moore.dyn_extract [[ARRAY2]] from [[A]] : uarray<2 x uarray<4 x i8>>, i32 -> uarray<4 x i8>
|
||||
moore.dyn_extract %array2 from %a : uarray<2 x uarray<4 x i8>>, i32 -> uarray<4 x i8>
|
||||
// CHECK: moore.dyn_extract [[ARRAY1]] from [[A]] : uarray<4 x i8>, i32 -> i8
|
||||
moore.dyn_extract %array1 from %a : uarray<4 x i8>, i32 -> i8
|
||||
|
||||
// CHECK: moore.extract_ref [[REF_A]] from [[B]] : <i32>, i32 -> <i1>
|
||||
moore.extract_ref %refA from %b : <i32>, i32 -> <i1>
|
||||
// CHECK: moore.extract_ref [[REF_ARRAY2]] from [[A]] : <uarray<2 x uarray<4 x i8>>>, i32 -> <uarray<4 x i8>>
|
||||
moore.extract_ref %refArray2 from %a : <uarray<2 x uarray<4 x i8>>>, i32 -> <uarray<4 x i8>>
|
||||
// CHECK: moore.extract_ref [[REF_ARRAY1]] from [[A]] : <uarray<4 x i8>>, i32 -> <i8>
|
||||
moore.extract_ref %refArray1 from %a : <uarray<4 x i8>>, i32 -> <i8>
|
||||
// CHECK: moore.dyn_extract_ref [[REF_A]] from [[B]] : <i32>, i32 -> <i1>
|
||||
moore.dyn_extract_ref %refA from %b : <i32>, i32 -> <i1>
|
||||
// CHECK: moore.dyn_extract_ref [[REF_ARRAY2]] from [[A]] : <uarray<2 x uarray<4 x i8>>>, i32 -> <uarray<4 x i8>>
|
||||
moore.dyn_extract_ref %refArray2 from %a : <uarray<2 x uarray<4 x i8>>>, i32 -> <uarray<4 x i8>>
|
||||
// CHECK: moore.dyn_extract_ref [[REF_ARRAY1]] from [[A]] : <uarray<4 x i8>>, i32 -> <i8>
|
||||
moore.dyn_extract_ref %refArray1 from %a : <uarray<4 x i8>>, i32 -> <i8>
|
||||
|
||||
// CHECK: moore.conditional [[X]] : i1 -> i32 {
|
||||
// CHECK: moore.yield [[A]] : i32
|
||||
|
|
|
@ -11,24 +11,20 @@
|
|||
|
||||
// CHECK: moore.concat_ref %a, %b
|
||||
%0 = moore.concat_ref %a, %b : (!moore.ref<i8960>, !moore.ref<i42>) -> <i9002>
|
||||
// CHECK: %[[C_READ:.+]] = moore.read %c
|
||||
// CHECK: %[[C_READ:.+]] = moore.read %c : <i9002>
|
||||
%1 = moore.read %c : <i9002>
|
||||
// CHECK: %[[CONST_42:.+]] = moore.constant 42 : i32
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[C_READ]] from %[[CONST_42]] : i9002, i32 -> i8960
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[C_READ]] from 42 : i9002 -> i8960
|
||||
// CHECK: moore.assign %a, %[[TMP1]] : i8960
|
||||
// CHECK: %[[CONST_0:.+]] = moore.constant 0 : i32
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[C_READ]] from %[[CONST_0]] : i9002, i32 -> i42
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[C_READ]] from 0 : i9002 -> i42
|
||||
// CHECK: moore.assign %b, %[[TMP2]] : i42
|
||||
moore.assign %0, %1 : i9002
|
||||
moore.procedure always {
|
||||
// CHECK: moore.concat_ref %u, %v
|
||||
%2 = moore.concat_ref %u, %v : (!moore.ref<l8960>, !moore.ref<l42>) -> <l9002>
|
||||
// CHECK: %[[W_READ:.+]] = moore.read %w
|
||||
// CHECK: %[[CONST_42:.+]] = moore.constant 42 : i32
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[W_READ]] from %[[CONST_42]] : l9002, i32 -> l8960
|
||||
// CHECK: %[[W_READ:.+]] = moore.read %w : <l9002>
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[W_READ]] from 42 : l9002 -> l8960
|
||||
// CHECK: moore.blocking_assign %u, %[[TMP1]] : l8960
|
||||
// CHECK: %[[CONST_0:.+]] = moore.constant 0 : i32
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[W_READ]] from %[[CONST_0]] : l9002, i32 -> l42
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[W_READ]] from 0 : l9002 -> l42
|
||||
// CHECK: moore.blocking_assign %v, %[[TMP2]] : l42
|
||||
%3 = moore.read %w : <l9002>
|
||||
moore.blocking_assign %2, %3 : l9002
|
||||
|
@ -39,13 +35,11 @@
|
|||
scf.if %6 {
|
||||
// CHECK: moore.concat_ref %u, %v
|
||||
%7 = moore.concat_ref %u, %v : (!moore.ref<l8960>, !moore.ref<l42>) -> <l9002>
|
||||
// CHECK: %[[W_READ:.+]] = moore.read %w
|
||||
// CHECK: %[[W_READ:.+]] = moore.read %w : <l9002>
|
||||
%8 = moore.read %w : <l9002>
|
||||
// CHECK: %[[CONST_42:.+]] = moore.constant 42 : i32
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[W_READ]] from %[[CONST_42]] : l9002, i32 -> l8960
|
||||
// CHECK: %[[TMP1:.+]] = moore.extract %[[W_READ]] from 42 : l9002 -> l8960
|
||||
// CHECK: moore.nonblocking_assign %u, %[[TMP1]] : l8960
|
||||
// CHECK: %[[CONST_0:.+]] = moore.constant 0 : i32
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[W_READ]] from %[[CONST_0]] : l9002, i32 -> l42
|
||||
// CHECK: %[[TMP2:.+]] = moore.extract %[[W_READ]] from 0 : l9002 -> l42
|
||||
// CHECK: moore.nonblocking_assign %v, %[[TMP2]] : l42
|
||||
moore.nonblocking_assign %7, %8 : l9002
|
||||
}
|
||||
|
@ -72,14 +66,11 @@ moore.module @Nested() {
|
|||
%2 = moore.concat_ref %y : (!moore.ref<i32>) -> <i32>
|
||||
%3 = moore.concat_ref %1, %2 : (!moore.ref<i64>, !moore.ref<i32>) -> <i96>
|
||||
|
||||
// CHECK: %[[CONST_64:.+]] = moore.constant 64 : i32
|
||||
// CHECK: %[[TMP3:.+]] = moore.extract %[[TMP2]] from %[[CONST_64]] : i96, i32 -> i32
|
||||
// CHECK: %[[TMP3:.+]] = moore.extract %[[TMP2]] from 64 : i96 -> i32
|
||||
// CHECK: moore.blocking_assign %x, %[[TMP3]] : i32
|
||||
// CHECK: %[[CONST_32:.+]] = moore.constant 32 : i32
|
||||
// CHECK: %[[TMP4:.+]] = moore.extract %[[TMP2]] from %[[CONST_32]] : i96, i32 -> i32
|
||||
// CHECK: %[[TMP4:.+]] = moore.extract %[[TMP2]] from 32 : i96 -> i32
|
||||
// CHECK: moore.blocking_assign %x, %[[TMP4]] : i32
|
||||
// CHECK: %[[CONST_0:.+]] = moore.constant 0 : i32
|
||||
// CHECK: %[[TMP5:.+]] = moore.extract %[[TMP2]] from %[[CONST_0]] : i96, i32 -> i32
|
||||
// CHECK: %[[TMP5:.+]] = moore.extract %[[TMP2]] from 0 : i96 -> i32
|
||||
// CHECK: moore.blocking_assign %y, %[[TMP5]] : i32
|
||||
moore.blocking_assign %3, %6 : i96
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue