10 #include "slang/syntax/AllSyntax.h"
12 using namespace circt;
13 using namespace ImportVerilog;
22 ExprVisitor(
Context &context, Location loc)
27 Value convertToSimpleBitVector(Value value) {
30 if (isa<moore::IntType>(value.getType()))
32 mlir::emitError(loc,
"expression of type ")
33 << value.getType() <<
" cannot be cast to a simple bit vector";
38 Value convertToBool(Value value) {
41 if (
auto type = dyn_cast_or_null<moore::IntType>(value.getType()))
42 if (type.getBitSize() == 1)
44 if (
auto type = dyn_cast_or_null<moore::UnpackedType>(value.getType()))
45 return builder.create<moore::BoolCastOp>(loc, value);
46 mlir::emitError(loc,
"expression of type ")
47 << value.getType() <<
" cannot be cast to a boolean";
52 Value visit(
const slang::ast::LValueReferenceExpression &expr) {
55 return builder.create<moore::ReadLValueOp>(loc, lvalue);
59 Value visit(
const slang::ast::NamedValueExpression &expr) {
60 if (
auto value = context.
valueSymbols.lookup(&expr.symbol))
62 auto d = mlir::emitError(loc,
"unknown name `") << expr.symbol.name <<
"`";
69 Value visit(
const slang::ast::ConversionExpression &expr) {
76 return builder.create<moore::ConversionOp>(loc, type, operand);
80 Value visit(
const slang::ast::AssignmentExpression &expr) {
88 if (lhs.getType() != rhs.getType())
89 rhs =
builder.create<moore::ConversionOp>(loc, lhs.getType(), rhs);
91 if (expr.timingControl) {
93 mlir::emitError(loc,
"delayed assignments not supported");
97 if (expr.isNonBlocking())
98 builder.create<moore::NonBlockingAssignOp>(loc, lhs, rhs);
100 builder.create<moore::BlockingAssignOp>(loc, lhs, rhs);
106 template <
class ConcreteOp>
107 Value createReduction(Value arg,
bool invert) {
108 arg = convertToSimpleBitVector(arg);
111 Value result =
builder.create<ConcreteOp>(loc, arg);
113 result =
builder.create<moore::NotOp>(loc, result);
118 Value createIncrement(Value arg,
bool isInc,
bool isPost) {
119 auto preValue = convertToSimpleBitVector(arg);
122 preValue =
builder.create<moore::ReadLValueOp>(loc, preValue);
123 auto one =
builder.create<moore::ConstantOp>(
124 loc, cast<moore::IntType>(preValue.getType()), 1);
126 isInc ?
builder.create<moore::AddOp>(loc, preValue, one).getResult()
127 :
builder.create<moore::SubOp>(loc, preValue, one).getResult();
128 builder.create<moore::BlockingAssignOp>(loc, arg, postValue);
129 return isPost ? preValue : postValue;
133 Value visit(
const slang::ast::UnaryExpression &expr) {
138 using slang::ast::UnaryOperator;
142 case UnaryOperator::Plus:
143 return convertToSimpleBitVector(arg);
145 case UnaryOperator::Minus:
146 arg = convertToSimpleBitVector(arg);
149 return builder.create<moore::NegOp>(loc, arg);
151 case UnaryOperator::BitwiseNot:
152 arg = convertToSimpleBitVector(arg);
155 return builder.create<moore::NotOp>(loc, arg);
157 case UnaryOperator::BitwiseAnd:
158 return createReduction<moore::ReduceAndOp>(arg,
false);
159 case UnaryOperator::BitwiseOr:
160 return createReduction<moore::ReduceOrOp>(arg,
false);
161 case UnaryOperator::BitwiseXor:
162 return createReduction<moore::ReduceXorOp>(arg,
false);
163 case UnaryOperator::BitwiseNand:
164 return createReduction<moore::ReduceAndOp>(arg,
true);
165 case UnaryOperator::BitwiseNor:
166 return createReduction<moore::ReduceOrOp>(arg,
true);
167 case UnaryOperator::BitwiseXnor:
168 return createReduction<moore::ReduceXorOp>(arg,
true);
170 case UnaryOperator::LogicalNot:
171 arg = convertToBool(arg);
174 return builder.create<moore::NotOp>(loc, arg);
176 case UnaryOperator::Preincrement:
177 return createIncrement(arg,
true,
false);
178 case UnaryOperator::Predecrement:
179 return createIncrement(arg,
false,
false);
180 case UnaryOperator::Postincrement:
181 return createIncrement(arg,
true,
true);
182 case UnaryOperator::Postdecrement:
183 return createIncrement(arg,
false,
true);
186 mlir::emitError(loc,
"unsupported unary operator");
192 template <
class ConcreteOp>
193 Value createBinary(Value lhs, Value rhs) {
194 lhs = convertToSimpleBitVector(lhs);
195 rhs = convertToSimpleBitVector(rhs);
198 return builder.create<ConcreteOp>(loc, lhs, rhs);
202 Value visit(
const slang::ast::BinaryExpression &expr) {
208 using slang::ast::BinaryOperator;
210 case BinaryOperator::Add:
211 return createBinary<moore::AddOp>(lhs, rhs);
212 case BinaryOperator::Subtract:
213 return createBinary<moore::SubOp>(lhs, rhs);
214 case BinaryOperator::Multiply:
215 return createBinary<moore::MulOp>(lhs, rhs);
216 case BinaryOperator::Divide:
217 if (expr.type->isSigned())
218 return createBinary<moore::DivSOp>(lhs, rhs);
220 return createBinary<moore::DivUOp>(lhs, rhs);
221 case BinaryOperator::Mod:
222 if (expr.type->isSigned())
223 return createBinary<moore::ModSOp>(lhs, rhs);
225 return createBinary<moore::ModUOp>(lhs, rhs);
227 case BinaryOperator::BinaryAnd:
228 return createBinary<moore::AndOp>(lhs, rhs);
229 case BinaryOperator::BinaryOr:
230 return createBinary<moore::OrOp>(lhs, rhs);
231 case BinaryOperator::BinaryXor:
232 return createBinary<moore::XorOp>(lhs, rhs);
233 case BinaryOperator::BinaryXnor: {
234 auto result = createBinary<moore::XorOp>(lhs, rhs);
237 return builder.create<moore::NotOp>(loc, result);
240 case BinaryOperator::Equality:
241 return createBinary<moore::EqOp>(lhs, rhs);
242 case BinaryOperator::Inequality:
243 return createBinary<moore::NeOp>(lhs, rhs);
244 case BinaryOperator::CaseEquality:
245 return createBinary<moore::CaseEqOp>(lhs, rhs);
246 case BinaryOperator::CaseInequality:
247 return createBinary<moore::CaseNeOp>(lhs, rhs);
248 case BinaryOperator::WildcardEquality:
249 return createBinary<moore::WildcardEqOp>(lhs, rhs);
250 case BinaryOperator::WildcardInequality:
251 return createBinary<moore::WildcardNeOp>(lhs, rhs);
253 case BinaryOperator::GreaterThanEqual:
254 if (expr.left().type->isSigned())
255 return createBinary<moore::SgeOp>(lhs, rhs);
257 return createBinary<moore::UgeOp>(lhs, rhs);
258 case BinaryOperator::GreaterThan:
259 if (expr.left().type->isSigned())
260 return createBinary<moore::SgtOp>(lhs, rhs);
262 return createBinary<moore::UgtOp>(lhs, rhs);
263 case BinaryOperator::LessThanEqual:
264 if (expr.left().type->isSigned())
265 return createBinary<moore::SleOp>(lhs, rhs);
267 return createBinary<moore::UleOp>(lhs, rhs);
268 case BinaryOperator::LessThan:
269 if (expr.left().type->isSigned())
270 return createBinary<moore::SltOp>(lhs, rhs);
272 return createBinary<moore::UltOp>(lhs, rhs);
275 case BinaryOperator::LogicalAnd: {
277 lhs = convertToBool(lhs);
278 rhs = convertToBool(rhs);
281 return builder.create<moore::AndOp>(loc, lhs, rhs);
283 case BinaryOperator::LogicalOr: {
285 lhs = convertToBool(lhs);
286 rhs = convertToBool(rhs);
289 return builder.create<moore::OrOp>(loc, lhs, rhs);
291 case BinaryOperator::LogicalImplication: {
293 lhs = convertToBool(lhs);
294 rhs = convertToBool(rhs);
297 auto notLHS =
builder.create<moore::NotOp>(loc, lhs);
298 return builder.create<moore::OrOp>(loc, notLHS, rhs);
300 case BinaryOperator::LogicalEquivalence: {
302 lhs = convertToBool(lhs);
303 rhs = convertToBool(rhs);
306 auto notLHS =
builder.create<moore::NotOp>(loc, lhs);
307 auto notRHS =
builder.create<moore::NotOp>(loc, rhs);
308 auto both =
builder.create<moore::AndOp>(loc, lhs, rhs);
309 auto notBoth =
builder.create<moore::AndOp>(loc, notLHS, notRHS);
310 return builder.create<moore::OrOp>(loc, both, notBoth);
313 case BinaryOperator::LogicalShiftLeft:
314 return createBinary<moore::ShlOp>(lhs, rhs);
315 case BinaryOperator::LogicalShiftRight:
316 return createBinary<moore::ShrOp>(lhs, rhs);
317 case BinaryOperator::ArithmeticShiftLeft:
318 return createBinary<moore::ShlOp>(lhs, rhs);
319 case BinaryOperator::ArithmeticShiftRight: {
322 lhs = convertToSimpleBitVector(lhs);
323 rhs = convertToSimpleBitVector(rhs);
326 if (expr.type->isSigned())
327 return builder.create<moore::AShrOp>(loc, lhs, rhs);
328 return builder.create<moore::ShrOp>(loc, lhs, rhs);
331 case BinaryOperator::Power:
335 mlir::emitError(loc,
"unsupported binary operator");
340 Value convertSVInt(
const slang::SVInt &value, Type type) {
341 if (value.hasUnknown()) {
342 mlir::emitError(loc,
"literals with X or Z bits not supported");
345 if (value.getBitWidth() > 64) {
346 mlir::emitError(loc,
"unsupported bit width: literal is ")
347 << value.getBitWidth() <<
" bits wide; only 64 supported";
350 auto truncValue = value.as<uint64_t>().value();
351 return builder.create<moore::ConstantOp>(loc, cast<moore::IntType>(type),
356 Value visit(
const slang::ast::UnbasedUnsizedIntegerLiteral &expr) {
360 return convertSVInt(expr.getValue(), type);
364 Value visit(
const slang::ast::IntegerLiteral &expr) {
368 return convertSVInt(expr.getValue(), type);
372 Value visit(
const slang::ast::ConcatenationExpression &expr) {
373 SmallVector<Value> operands;
374 for (
auto *operand : expr.operands()) {
378 value = convertToSimpleBitVector(value);
379 operands.push_back(value);
381 return builder.create<moore::ConcatOp>(loc, operands);
385 Value visit(
const slang::ast::ReplicationExpression &expr) {
387 if (isa<moore::VoidType>(type))
393 return builder.create<moore::ReplicateOp>(loc, type, value);
397 Value visit(
const slang::ast::ElementSelectExpression &expr) {
402 if (!value || !lowBit)
404 return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
408 Value visit(
const slang::ast::RangeSelectExpression &expr) {
412 if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
413 if (expr.left().constant && expr.right().constant) {
414 auto lhs = expr.left().constant->integer().as<uint64_t>().value();
415 auto rhs = expr.right().constant->integer().as<uint64_t>().value();
419 mlir::emitError(loc,
"unsupported a variable as the index in the")
426 if (!value || !lowBit)
428 return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
432 template <
typename T>
433 Value visit(T &&node) {
434 mlir::emitError(loc,
"unsupported expression: ")
439 Value visitInvalid(
const slang::ast::Expression &expr) {
440 mlir::emitError(loc,
"invalid expression");
448 return expr.visit(ExprVisitor(*
this, loc));
assert(baseType &&"element must be base type")
constexpr const char * toString(Flow flow)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Value convertExpression(const slang::ast::Expression &expr)
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
ValueSymbols valueSymbols
SmallVector< Value > lvalueStack
A stack of assignment left-hand side values.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.