mirror of https://github.com/llvm/circt.git
[ImportVerilog] Add replicate and extract operations. (#6906)
This commit is contained in:
parent
7598a8e067
commit
80c6602d37
|
@ -656,4 +656,65 @@ def ConcatOp : MooreOp<"concat", [
|
|||
}];
|
||||
}
|
||||
|
||||
def ReplicateOp : MooreOp<"replicate", [
|
||||
Pure
|
||||
]> {
|
||||
let summary = "Multiple concatenation of expressions";
|
||||
let description = [{
|
||||
This operation indicates a joining together of that many copies of the
|
||||
concatenation `{constant{w}}`. Which enclosed together within brace.
|
||||
The 'constant' must a non-negative, non-x, and non-z constant expression.
|
||||
The 'constant' may be a value of zero, but it only exists in parameterized
|
||||
code, and it will be ignored(type is changed to the void).
|
||||
|
||||
Example:
|
||||
```
|
||||
{0{w}} // empty! ignore it.
|
||||
{4{w}} // the same as {w, w, w, w}
|
||||
```
|
||||
See IEEE 1800-2017 §11.4.12 "Concatenation operators".
|
||||
}];
|
||||
let arguments = (ins SimpleBitVectorType:$value);
|
||||
let results = (outs SimpleBitVectorType:$result);
|
||||
let assemblyFormat = [{
|
||||
$value attr-dict `:` functional-type($value, $result)
|
||||
}];
|
||||
}
|
||||
|
||||
def ExtractOp : MooreOp<"extract"> {
|
||||
let summary = "Addressing operation";
|
||||
let description = [{
|
||||
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.
|
||||
Bit-select results are unsigned, regardless of the operands.
|
||||
Part-select results are unsigned, regardless of the operands even if
|
||||
the part-select specifies the entire vector.
|
||||
See IEEE 1800-2017 § 11.8.1 "Rules for expression types"
|
||||
|
||||
Example:
|
||||
```
|
||||
logic v [7:0];
|
||||
v[1]; // the bit-select addressing
|
||||
v[3:0]; // the part-select addressing
|
||||
v[3-:4]; v[0+:4]; // They are equivalent to v[3:0]
|
||||
```
|
||||
See IEEE 1800-2017 § 11.5.1 "Vector bit-select and part-select addressing".
|
||||
|
||||
Example:
|
||||
```
|
||||
// an array of 256-by-256 8-bit elements
|
||||
logic [7:0] twod_array [0:255][0:255];
|
||||
logic [7:0] mem_name [0:1023]; // a memory of 1024 8-bit words
|
||||
```
|
||||
See IEEE 1800-2017 § 11.5.2 "Array and memory addressing".
|
||||
}];
|
||||
let arguments = (ins UnpackedType:$input, UnpackedType:$lowBit);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
$input `from` $lowBit attr-dict `:`
|
||||
type($input) `,` type($lowBit) `->` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
#endif // CIRCT_DIALECT_MOORE_MOOREOPS
|
||||
|
|
|
@ -361,12 +361,60 @@ struct ExprVisitor {
|
|||
for (auto *operand : expr.operands()) {
|
||||
auto value = context.convertExpression(*operand);
|
||||
if (!value)
|
||||
return {};
|
||||
continue;
|
||||
value = convertToSimpleBitVector(value);
|
||||
operands.push_back(value);
|
||||
}
|
||||
return builder.create<moore::ConcatOp>(loc, operands);
|
||||
}
|
||||
|
||||
// Handle replications.
|
||||
Value visit(const slang::ast::ReplicationExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
if (isa<moore::VoidType>(type))
|
||||
return {};
|
||||
|
||||
auto value = context.convertExpression(expr.concat());
|
||||
if (!value)
|
||||
return {};
|
||||
return builder.create<moore::ReplicateOp>(loc, type, value);
|
||||
}
|
||||
|
||||
// Handle single bit selections.
|
||||
Value visit(const slang::ast::ElementSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertExpression(expr.value());
|
||||
auto lowBit = context.convertExpression(expr.selector());
|
||||
|
||||
if (!value || !lowBit)
|
||||
return {};
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
}
|
||||
|
||||
// Handle range bits selections.
|
||||
Value visit(const slang::ast::RangeSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertExpression(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.convertExpression(expr.left())
|
||||
: context.convertExpression(expr.right());
|
||||
} else {
|
||||
mlir::emitError(loc, "unsupported a variable as the index in the")
|
||||
<< slang::ast::toString(expr.getSelectionKind()) << "kind";
|
||||
return {};
|
||||
}
|
||||
} else
|
||||
lowBit = context.convertExpression(expr.left());
|
||||
|
||||
if (!value || !lowBit)
|
||||
return {};
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
}
|
||||
|
||||
/// Emit an error for all other expressions.
|
||||
template <typename T>
|
||||
Value visit(T &&node) {
|
||||
|
|
|
@ -209,6 +209,10 @@ module Expressions;
|
|||
integer d, e, f;
|
||||
bit x;
|
||||
logic y;
|
||||
logic [31:0] vec_1;
|
||||
logic [0:31] vec_2;
|
||||
bit [4:1] arr [1:3][2:7];
|
||||
bit [3:2] s;
|
||||
|
||||
initial begin
|
||||
// CHECK: moore.constant 0 : !moore.packed<range<bit, 31:0>>
|
||||
|
@ -225,6 +229,43 @@ module Expressions;
|
|||
a = {a, b, c};
|
||||
// CHECK: moore.concat %d, %e : (!moore.integer, !moore.integer) -> !moore.packed<range<logic, 63:0>>
|
||||
d = {d, e};
|
||||
// CHECK: %[[VAL_1:.*]] = moore.constant false : !moore.packed<range<bit, 0:0>>
|
||||
// CHECK: %[[VAL_2:.*]] = moore.concat %[[VAL_1]] : (!moore.packed<range<bit, 0:0>>) -> !moore.packed<range<bit, 0:0>>
|
||||
// CHECK: %[[VAL_3:.*]] = moore.replicate %[[VAL_2]] : (!moore.packed<range<bit, 0:0>>) -> !moore.packed<range<bit, 31:0>>
|
||||
a = {32{1'b0}};
|
||||
// CHECK: %[[VAL:.*]] = moore.constant 1 : !moore.int
|
||||
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 3:1>>
|
||||
y = vec_1[3:1];
|
||||
// CHECK: %[[VAL:.*]] = moore.constant 2 : !moore.int
|
||||
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.packed<range<logic, 0:31>>, !moore.int -> !moore.packed<range<logic, 2:3>>
|
||||
y = vec_2[2:3];
|
||||
// CHECK: moore.extract %d from %x : !moore.integer, !moore.bit -> !moore.logic
|
||||
y = d[x];
|
||||
// CHECK: moore.extract %a from %x : !moore.int, !moore.bit -> !moore.bit
|
||||
y = a[x];
|
||||
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.int
|
||||
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.logic
|
||||
y = vec_1[15];
|
||||
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.int
|
||||
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 15:15>>
|
||||
y = vec_1[15+:1];
|
||||
// CHECK: %[[VAL:.*]] = moore.constant 0 : !moore.int
|
||||
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.packed<range<logic, 0:31>>, !moore.int -> !moore.packed<range<logic, 0:0>>
|
||||
y = vec_2[0+:1];
|
||||
// CHECK: %[[VAL_1:.*]] = moore.constant 1 : !moore.int
|
||||
// CHECK: %[[VAL_2:.*]] = moore.mul %[[VAL_1]], %a : !moore.int
|
||||
// CHECK: moore.extract %vec_1 from %[[VAL_2]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 31:31>>
|
||||
y = vec_1[1*a-:1];
|
||||
// CHECK: %[[VAL_1:.*]] = moore.constant 3 : !moore.int
|
||||
// CHECK: %[[VAL_2:.*]] = moore.extract %arr from %[[VAL_1]] : !moore.unpacked<range<range<packed<range<bit, 4:1>>, 2:7>, 1:3>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 4:1>>, 2:7>>
|
||||
// CHECK: %[[VAL_3:.*]] = moore.constant 7 : !moore.int
|
||||
// CHECK: %[[VAL_4:.*]] = moore.extract %[[VAL_2]] from %[[VAL_3]] : !moore.unpacked<range<packed<range<bit, 4:1>>, 2:7>>, !moore.int -> !moore.packed<range<bit, 4:1>>
|
||||
// CHECK: %[[VAL_5:.*]] = moore.constant 3 : !moore.int
|
||||
// CHECK: moore.extract %[[VAL_4]] from %[[VAL_5]] : !moore.packed<range<bit, 4:1>>, !moore.int -> !moore.packed<range<bit, 4:3>>
|
||||
s = arr[3][7][4:3];
|
||||
// CHECK: moore.extract %vec_1 from %s : !moore.packed<range<logic, 31:0>>, !moore.packed<range<bit, 3:2>> -> !moore.logic
|
||||
y = vec_1[s];
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Unary operators
|
||||
|
|
|
@ -102,3 +102,49 @@ module Foo;
|
|||
// expected-error @below {{literals with X or Z bits not supported}}
|
||||
initial x = 'z;
|
||||
endmodule
|
||||
|
||||
// -----
|
||||
|
||||
module Foo;
|
||||
// expected-remark @below {{declared here}}
|
||||
int a, b;
|
||||
initial begin
|
||||
// expected-error @below {{replication constant can only be zero inside of a concatenation}}
|
||||
a = {0{32'd5}};
|
||||
// expected-error @below {{value must be positive}}
|
||||
a = {-1{32'd5}};
|
||||
// expected-error @below {{value must not have any unknown bits}}
|
||||
a = {32'bx{1'b0}};
|
||||
// expected-error @below {{value must not have any unknown bits}}
|
||||
a = {32'bz{1'b0}};
|
||||
// expected-error @below {{reference to non-constant variable 'b' is not allowed in a constant expression}}
|
||||
a = {b{32'd5}};
|
||||
end
|
||||
endmodule
|
||||
|
||||
// -----
|
||||
|
||||
module Foo;
|
||||
bit [3:0] a;
|
||||
bit [1:0] b;
|
||||
// expected-remark @below {{declared here}}
|
||||
bit c;
|
||||
initial begin
|
||||
// expected-error @below {{cannot refer to element 1'bx of 'bit[3:0]' [-Windex-oob]}}
|
||||
c = a[1'bx];
|
||||
// expected-error @below {{endianness of selection must match declared range (type is 'bit[3:0]')}}
|
||||
b = a[0:1];
|
||||
// expected-error @below {{reference to non-constant variable 'c' is not allowed in a constant expression}}
|
||||
b = a[c:1];
|
||||
// expected-error @below {{reference to non-constant variable 'c' is not allowed in a constant expression}}
|
||||
b = a[2-:c];
|
||||
// expected-error @below {{value must not have any unknown bits}}
|
||||
b = a[1'bz:0];
|
||||
// expected-error @below {{value must not have any unknown bits}}
|
||||
b = a[1-:'x];
|
||||
// expected-error @below {{value must be positive}}
|
||||
b = a[1-:0];
|
||||
// expected-error @below {{value must be positive}}
|
||||
b = a[1-:-1];
|
||||
end
|
||||
endmodule
|
||||
|
|
|
@ -47,6 +47,7 @@ moore.module @Expressions {
|
|||
%int2 = moore.variable : !moore.int
|
||||
%integer = moore.variable : !moore.integer
|
||||
%integer2 = moore.variable : !moore.integer
|
||||
%arr = moore.variable : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>
|
||||
|
||||
// CHECK: moore.constant 0 : !moore.int
|
||||
moore.constant 0 : !moore.int
|
||||
|
@ -136,4 +137,23 @@ moore.module @Expressions {
|
|||
moore.concat %b5, %b1 : (!moore.packed<range<bit, 4:0>>, !moore.bit) -> !moore.packed<range<bit, 5:0>>
|
||||
// CHECK: moore.concat %l1, %l1, %l1 : (!moore.logic, !moore.logic, !moore.logic) -> !moore.packed<range<logic, 2:0>>
|
||||
moore.concat %l1, %l1, %l1 : (!moore.logic, !moore.logic, !moore.logic) -> !moore.packed<range<logic, 2:0>>
|
||||
// CHECK: [[VAL:%.*]] = moore.concat %b1 : (!moore.bit) -> !moore.packed<range<bit, 0:0>>
|
||||
// CHECK: moore.replicate [[VAL]] : (!moore.packed<range<bit, 0:0>>) -> !moore.packed<range<bit, 3:0>>
|
||||
%0 = moore.concat %b1 : (!moore.bit) -> !moore.packed<range<bit, 0:0>>
|
||||
moore.replicate %0 : (!moore.packed<range<bit, 0:0>>) -> !moore.packed<range<bit, 3:0>>
|
||||
|
||||
// CHECK: moore.extract %b5 from %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit -> !moore.bit
|
||||
moore.extract %b5 from %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit -> !moore.bit
|
||||
// CHECK: [[VAL1:%.*]] = moore.constant 0 : !moore.int
|
||||
// CHECK: [[VAL2:%.*]] = moore.extract %arr from [[VAL1]] : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>
|
||||
%1 = moore.constant 0 : !moore.int
|
||||
%2 = moore.extract %arr from %1 : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>
|
||||
// CHECK: [[VAL3:%.*]] = moore.constant 3 : !moore.int
|
||||
// CHECK: [[VAL4:%.*]] = moore.extract [[VAL2]] from [[VAL3]] : !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>, !moore.int -> !moore.packed<range<bit, 7:0>>
|
||||
%3 = moore.constant 3 : !moore.int
|
||||
%4 = moore.extract %2 from %3 : !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>, !moore.int -> !moore.packed<range<bit, 7:0>>
|
||||
// CHECK: [[VAL5:%.*]] = moore.constant 2 : !moore.int
|
||||
// CHECK: moore.extract [[VAL4]] from [[VAL5]] : !moore.packed<range<bit, 7:0>>, !moore.int -> !moore.packed<range<bit, 6:2>>
|
||||
%5 = moore.constant 2 : !moore.int
|
||||
moore.extract %4 from %5 : !moore.packed<range<bit, 7:0>>, !moore.int -> !moore.packed<range<bit, 6:2>>
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue