10 #include "slang/ast/SystemSubroutine.h"
11 #include "slang/syntax/AllSyntax.h"
13 using namespace circt;
14 using namespace ImportVerilog;
19 if (svint.hasUnknown()) {
20 unsigned numWords = svint.getNumWords() / 2;
21 auto value = ArrayRef<uint64_t>(svint.getRawPtr(), numWords);
22 auto unknown = ArrayRef<uint64_t>(svint.getRawPtr() + numWords, numWords);
23 return FVInt(APInt(svint.getBitWidth(), value),
24 APInt(svint.getBitWidth(), unknown));
26 auto value = ArrayRef<uint64_t>(svint.getRawPtr(), svint.getNumWords());
27 return FVInt(APInt(svint.getBitWidth(), value));
32 struct RvalueExprVisitor {
37 RvalueExprVisitor(
Context &context, Location loc)
38 : context(context), loc(loc), builder(context.builder) {}
41 Value visit(
const slang::ast::LValueReferenceExpression &expr) {
44 return builder.create<moore::ReadOp>(loc, lvalue);
48 Value visit(
const slang::ast::NamedValueExpression &expr) {
49 if (
auto value = context.
valueSymbols.lookup(&expr.symbol)) {
50 if (isa<moore::RefType>(value.getType())) {
51 auto readOp = builder.create<moore::ReadOp>(loc, value);
54 value = readOp.getResult();
66 auto d = mlir::emitError(loc,
"unknown name `") << expr.symbol.name <<
"`";
73 Value visit(
const slang::ast::ConversionExpression &expr) {
81 Value visit(
const slang::ast::AssignmentExpression &expr) {
88 expr.right(), cast<moore::RefType>(lhs.getType()).getNestedType());
93 if (expr.timingControl) {
95 mlir::emitError(loc,
"delayed assignments not supported");
99 if (expr.isNonBlocking())
100 builder.create<moore::NonBlockingAssignOp>(loc, lhs, rhs);
102 builder.create<moore::BlockingAssignOp>(loc, lhs, rhs);
108 template <
class ConcreteOp>
109 Value createReduction(Value arg,
bool invert) {
113 Value result = builder.create<ConcreteOp>(loc, arg);
115 result = builder.create<moore::NotOp>(loc, result);
120 Value createIncrement(Value arg,
bool isInc,
bool isPost) {
121 auto preValue = builder.create<moore::ReadOp>(loc, arg);
122 auto one = builder.create<moore::ConstantOp>(
123 loc, cast<moore::IntType>(preValue.getType()), 1);
125 isInc ? builder.create<moore::AddOp>(loc, preValue, one).getResult()
126 : builder.create<moore::SubOp>(loc, preValue, one).getResult();
127 builder.create<moore::BlockingAssignOp>(loc, arg, postValue);
134 Value visit(
const slang::ast::UnaryExpression &expr) {
135 using slang::ast::UnaryOperator;
137 if (expr.op == UnaryOperator::Preincrement ||
138 expr.op == UnaryOperator::Predecrement ||
139 expr.op == UnaryOperator::Postincrement ||
140 expr.op == UnaryOperator::Postdecrement)
150 case UnaryOperator::Plus:
153 case UnaryOperator::Minus:
157 return builder.create<moore::NegOp>(loc, arg);
159 case UnaryOperator::BitwiseNot:
163 return builder.create<moore::NotOp>(loc, arg);
165 case UnaryOperator::BitwiseAnd:
166 return createReduction<moore::ReduceAndOp>(arg,
false);
167 case UnaryOperator::BitwiseOr:
168 return createReduction<moore::ReduceOrOp>(arg,
false);
169 case UnaryOperator::BitwiseXor:
170 return createReduction<moore::ReduceXorOp>(arg,
false);
171 case UnaryOperator::BitwiseNand:
172 return createReduction<moore::ReduceAndOp>(arg,
true);
173 case UnaryOperator::BitwiseNor:
174 return createReduction<moore::ReduceOrOp>(arg,
true);
175 case UnaryOperator::BitwiseXnor:
176 return createReduction<moore::ReduceXorOp>(arg,
true);
178 case UnaryOperator::LogicalNot:
182 return builder.create<moore::NotOp>(loc, arg);
184 case UnaryOperator::Preincrement:
185 return createIncrement(arg,
true,
false);
186 case UnaryOperator::Predecrement:
187 return createIncrement(arg,
false,
false);
188 case UnaryOperator::Postincrement:
189 return createIncrement(arg,
true,
true);
190 case UnaryOperator::Postdecrement:
191 return createIncrement(arg,
false,
true);
194 mlir::emitError(loc,
"unsupported unary operator");
200 template <
class ConcreteOp>
201 Value createBinary(Value lhs, Value rhs) {
208 return builder.create<ConcreteOp>(loc, lhs, rhs);
212 Value visit(
const slang::ast::BinaryExpression &expr) {
221 Domain domain = Domain::TwoValued;
222 if (expr.type->isFourState() || expr.left().type->isFourState() ||
223 expr.right().type->isFourState())
224 domain = Domain::FourValued;
226 using slang::ast::BinaryOperator;
228 case BinaryOperator::Add:
229 return createBinary<moore::AddOp>(lhs, rhs);
230 case BinaryOperator::Subtract:
231 return createBinary<moore::SubOp>(lhs, rhs);
232 case BinaryOperator::Multiply:
233 return createBinary<moore::MulOp>(lhs, rhs);
234 case BinaryOperator::Divide:
235 if (expr.type->isSigned())
236 return createBinary<moore::DivSOp>(lhs, rhs);
238 return createBinary<moore::DivUOp>(lhs, rhs);
239 case BinaryOperator::Mod:
240 if (expr.type->isSigned())
241 return createBinary<moore::ModSOp>(lhs, rhs);
243 return createBinary<moore::ModUOp>(lhs, rhs);
244 case BinaryOperator::Power: {
250 builder.create<moore::ConversionOp>(loc, lhs.getType(), rhs);
251 if (expr.type->isSigned())
252 return createBinary<moore::PowSOp>(lhs, rhsCast);
254 return createBinary<moore::PowUOp>(lhs, rhsCast);
257 case BinaryOperator::BinaryAnd:
258 return createBinary<moore::AndOp>(lhs, rhs);
259 case BinaryOperator::BinaryOr:
260 return createBinary<moore::OrOp>(lhs, rhs);
261 case BinaryOperator::BinaryXor:
262 return createBinary<moore::XorOp>(lhs, rhs);
263 case BinaryOperator::BinaryXnor: {
264 auto result = createBinary<moore::XorOp>(lhs, rhs);
267 return builder.create<moore::NotOp>(loc, result);
270 case BinaryOperator::Equality:
271 return createBinary<moore::EqOp>(lhs, rhs);
272 case BinaryOperator::Inequality:
273 return createBinary<moore::NeOp>(lhs, rhs);
274 case BinaryOperator::CaseEquality:
275 return createBinary<moore::CaseEqOp>(lhs, rhs);
276 case BinaryOperator::CaseInequality:
277 return createBinary<moore::CaseNeOp>(lhs, rhs);
278 case BinaryOperator::WildcardEquality:
279 return createBinary<moore::WildcardEqOp>(lhs, rhs);
280 case BinaryOperator::WildcardInequality:
281 return createBinary<moore::WildcardNeOp>(lhs, rhs);
283 case BinaryOperator::GreaterThanEqual:
284 if (expr.left().type->isSigned())
285 return createBinary<moore::SgeOp>(lhs, rhs);
287 return createBinary<moore::UgeOp>(lhs, rhs);
288 case BinaryOperator::GreaterThan:
289 if (expr.left().type->isSigned())
290 return createBinary<moore::SgtOp>(lhs, rhs);
292 return createBinary<moore::UgtOp>(lhs, rhs);
293 case BinaryOperator::LessThanEqual:
294 if (expr.left().type->isSigned())
295 return createBinary<moore::SleOp>(lhs, rhs);
297 return createBinary<moore::UleOp>(lhs, rhs);
298 case BinaryOperator::LessThan:
299 if (expr.left().type->isSigned())
300 return createBinary<moore::SltOp>(lhs, rhs);
302 return createBinary<moore::UltOp>(lhs, rhs);
305 case BinaryOperator::LogicalAnd: {
314 return builder.create<moore::AndOp>(loc, lhs, rhs);
316 case BinaryOperator::LogicalOr: {
325 return builder.create<moore::OrOp>(loc, lhs, rhs);
327 case BinaryOperator::LogicalImplication: {
335 auto notLHS = builder.create<moore::NotOp>(loc, lhs);
336 return builder.create<moore::OrOp>(loc, notLHS, rhs);
338 case BinaryOperator::LogicalEquivalence: {
346 auto notLHS = builder.create<moore::NotOp>(loc, lhs);
347 auto notRHS = builder.create<moore::NotOp>(loc, rhs);
348 auto both = builder.create<moore::AndOp>(loc, lhs, rhs);
349 auto notBoth = builder.create<moore::AndOp>(loc, notLHS, notRHS);
350 return builder.create<moore::OrOp>(loc, both, notBoth);
353 case BinaryOperator::LogicalShiftLeft:
354 return createBinary<moore::ShlOp>(lhs, rhs);
355 case BinaryOperator::LogicalShiftRight:
356 return createBinary<moore::ShrOp>(lhs, rhs);
357 case BinaryOperator::ArithmeticShiftLeft:
358 return createBinary<moore::ShlOp>(lhs, rhs);
359 case BinaryOperator::ArithmeticShiftRight: {
366 if (expr.type->isSigned())
367 return builder.create<moore::AShrOp>(loc, lhs, rhs);
368 return builder.create<moore::ShrOp>(loc, lhs, rhs);
372 mlir::emitError(loc,
"unsupported binary operator");
377 Value visit(
const slang::ast::UnbasedUnsizedIntegerLiteral &expr) {
382 Value visit(
const slang::ast::IntegerLiteral &expr) {
387 Value visit(
const slang::ast::ConcatenationExpression &expr) {
388 SmallVector<Value> operands;
389 for (
auto *operand : expr.operands()) {
394 operands.push_back(value);
396 return builder.create<moore::ConcatOp>(loc, operands);
400 Value visit(
const slang::ast::ReplicationExpression &expr) {
402 if (isa<moore::VoidType>(type))
408 return builder.create<moore::ReplicateOp>(loc, type, value);
412 Value visit(
const slang::ast::ElementSelectExpression &expr) {
417 if (
auto *constValue = expr.selector().constant) {
418 assert(!constValue->hasUnknown());
419 assert(constValue->size() <= 32);
421 auto lowBit = constValue->integer().as<uint32_t>().value();
422 return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
427 return builder.create<moore::DynExtractOp>(loc, type, value, lowBit);
431 Value visit(
const slang::ast::RangeSelectExpression &expr) {
438 uint32_t constLowBit;
439 auto *leftConst = expr.left().constant;
440 auto *rightConst = expr.right().constant;
442 assert(!leftConst->hasUnknown());
443 assert(leftConst->size() <= 32);
446 assert(!rightConst->hasUnknown());
447 assert(rightConst->size() <= 32);
450 if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
451 if (leftConst && rightConst) {
453 auto lhs = leftConst->integer().as<uint32_t>().value();
454 auto rhs = rightConst->integer().as<uint32_t>().value();
455 constLowBit = lhs < rhs ? lhs : rhs;
457 mlir::emitError(loc,
"unsupported a variable as the index in the")
461 }
else if (expr.getSelectionKind() ==
462 slang::ast::RangeSelectionKind::IndexedDown) {
467 auto subtrahend = leftConst->integer().as<uint32_t>().value();
469 expr.right().constant->integer().as<uint32_t>().value();
470 constLowBit = subtrahend - sliceWidth - 1;
473 auto subtrahendType = cast<moore::UnpackedType>(subtrahend.getType());
475 subtrahendType.getBitSize().value(),
476 subtrahendType.getDomain());
478 expr.right().constant->integer().as<uint32_t>().value() - 1;
480 builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
481 dynLowBit = builder.create<moore::SubOp>(loc, subtrahend, minuend);
486 constLowBit = leftConst->integer().as<uint32_t>().value();
490 if (leftConst && rightConst)
491 return builder.create<moore::ExtractOp>(loc, type, value, constLowBit);
492 return builder.create<moore::DynExtractOp>(loc, type, value, dynLowBit);
495 Value visit(
const slang::ast::MemberAccessExpression &expr) {
497 auto valueType = expr.value().type;
501 if (valueType->isStruct()) {
502 return builder.create<moore::StructExtractOp>(
503 loc, type, builder.getStringAttr(expr.member.name), value);
505 if (valueType->isPackedUnion() || valueType->isUnpackedUnion()) {
506 return builder.create<moore::UnionExtractOp>(
507 loc, type, builder.getStringAttr(expr.member.name), value);
509 mlir::emitError(loc,
"expression of type ")
510 << value.getType() <<
" cannot be accessed";
515 Value visit(
const slang::ast::InsideExpression &expr) {
521 SmallVector<Value> conditions;
524 for (
const auto *listExpr : expr.rangeList()) {
528 if (
const auto *openRange =
529 listExpr->as_if<slang::ast::OpenRangeExpression>()) {
535 if (!lowBound || !highBound)
537 Value leftValue, rightValue;
540 if (openRange->left().type->isSigned() ||
541 expr.left().type->isSigned()) {
542 leftValue = builder.create<moore::SgeOp>(loc, lhs, lowBound);
544 leftValue = builder.create<moore::UgeOp>(loc, lhs, lowBound);
546 if (openRange->right().type->isSigned() ||
547 expr.left().type->isSigned()) {
548 rightValue = builder.create<moore::SleOp>(loc, lhs, highBound);
550 rightValue = builder.create<moore::UleOp>(loc, lhs, highBound);
552 cond = builder.create<moore::AndOp>(loc, leftValue, rightValue);
555 if (!listExpr->type->isSimpleBitVector()) {
556 if (listExpr->type->isUnpackedArray()) {
558 loc,
"unpacked arrays in 'inside' expressions not supported");
562 loc,
"only simple bit vectors supported in 'inside' expressions");
569 cond = builder.create<moore::WildcardEqOp>(loc, lhs, value);
571 conditions.push_back(cond);
575 auto result = conditions.back();
576 conditions.pop_back();
577 while (!conditions.empty()) {
578 result = builder.create<moore::OrOp>(loc, conditions.back(), result);
579 conditions.pop_back();
585 Value visit(
const slang::ast::ConditionalExpression &expr) {
589 if (expr.conditions.size() > 1) {
591 <<
"unsupported conditional expression with more than one condition";
594 const auto &cond = expr.conditions[0];
596 mlir::emitError(loc) <<
"unsupported conditional expression with pattern";
603 auto conditionalOp = builder.create<moore::ConditionalOp>(loc, type, value);
606 auto &trueBlock = conditionalOp.getTrueRegion().emplaceBlock();
607 auto &falseBlock = conditionalOp.getFalseRegion().emplaceBlock();
609 OpBuilder::InsertionGuard g(builder);
612 builder.setInsertionPointToStart(&trueBlock);
616 builder.create<moore::YieldOp>(loc, trueValue);
619 builder.setInsertionPointToStart(&falseBlock);
623 builder.create<moore::YieldOp>(loc, falseValue);
625 return conditionalOp.getResult();
629 Value visit(
const slang::ast::CallExpression &expr) {
631 if (expr.thisClass()) {
632 mlir::emitError(loc,
"unsupported class method call");
642 [&](
auto &subroutine) {
return visitCall(expr, subroutine); },
647 Value visitCall(
const slang::ast::CallExpression &expr,
648 const slang::ast::SubroutineSymbol *subroutine) {
656 SmallVector<Value> arguments;
657 for (
auto [callArg, declArg] :
658 llvm::zip(expr.arguments(), subroutine->getArguments())) {
662 auto *expr = callArg;
663 if (
const auto *assign = expr->as_if<slang::ast::AssignmentExpression>())
664 expr = &assign->left();
667 if (declArg->direction == slang::ast::ArgumentDirection::In)
673 arguments.push_back(value);
678 builder.create<mlir::func::CallOp>(loc, lowering->op, arguments);
683 if (callOp.getNumResults() == 0)
685 .create<mlir::UnrealizedConversionCastOp>(
689 return callOp.getResult(0);
693 Value visitCall(
const slang::ast::CallExpression &expr,
694 const slang::ast::CallExpression::SystemCallInfo &info) {
695 const auto &subroutine = *info.subroutine;
696 auto args = expr.arguments();
698 if (subroutine.name ==
"$signed" || subroutine.name ==
"$unsigned")
701 if (subroutine.name ==
"$clog2") {
706 return builder.create<moore::Clog2BIOp>(loc, value);
709 mlir::emitError(loc) <<
"unsupported system call `" << subroutine.name
715 Value visit(
const slang::ast::StringLiteral &expr) {
717 return builder.create<moore::StringConstantOp>(loc, type, expr.getValue());
721 Value visitAssignmentPattern(
722 const slang::ast::AssignmentPatternExpressionBase &expr,
723 unsigned replCount = 1) {
727 auto elementCount = expr.elements().size();
728 SmallVector<Value> elements;
729 elements.reserve(replCount * elementCount);
730 for (
auto elementExpr : expr.elements()) {
734 elements.push_back(value);
736 for (
unsigned replIdx = 1; replIdx < replCount; ++replIdx)
737 for (
unsigned elementIdx = 0; elementIdx < elementCount; ++elementIdx)
738 elements.push_back(elements[elementIdx]);
741 if (
auto intType = dyn_cast<moore::IntType>(type)) {
742 assert(intType.getWidth() == elements.size());
743 std::reverse(elements.begin(), elements.end());
744 return builder.create<moore::ConcatOp>(loc, intType, elements);
748 if (
auto structType = dyn_cast<moore::StructType>(type)) {
749 assert(structType.getMembers().size() == elements.size());
750 return builder.create<moore::StructCreateOp>(loc, structType, elements);
754 if (
auto structType = dyn_cast<moore::UnpackedStructType>(type)) {
755 assert(structType.getMembers().size() == elements.size());
756 return builder.create<moore::StructCreateOp>(loc, structType, elements);
760 if (
auto arrayType = dyn_cast<moore::ArrayType>(type)) {
761 assert(arrayType.getSize() == elements.size());
762 return builder.create<moore::ArrayCreateOp>(loc, arrayType, elements);
766 if (
auto arrayType = dyn_cast<moore::UnpackedArrayType>(type)) {
767 assert(arrayType.getSize() == elements.size());
768 return builder.create<moore::ArrayCreateOp>(loc, arrayType, elements);
771 mlir::emitError(loc) <<
"unsupported assignment pattern with type " << type;
775 Value visit(
const slang::ast::SimpleAssignmentPatternExpression &expr) {
776 return visitAssignmentPattern(expr);
779 Value visit(
const slang::ast::StructuredAssignmentPatternExpression &expr) {
780 return visitAssignmentPattern(expr);
783 Value visit(
const slang::ast::ReplicatedAssignmentPatternExpression &expr) {
786 assert(count &&
"Slang guarantees constant non-zero replication count");
787 return visitAssignmentPattern(expr, *count);
791 template <
typename T>
792 Value visit(T &&node) {
793 mlir::emitError(loc,
"unsupported expression: ")
798 Value visitInvalid(
const slang::ast::Expression &expr) {
799 mlir::emitError(loc,
"invalid expression");
806 struct LvalueExprVisitor {
811 LvalueExprVisitor(
Context &context, Location loc)
812 : context(context), loc(loc), builder(context.builder) {}
815 Value visit(
const slang::ast::NamedValueExpression &expr) {
816 if (
auto value = context.
valueSymbols.lookup(&expr.symbol))
818 auto d = mlir::emitError(loc,
"unknown name `") << expr.symbol.name <<
"`";
825 Value visit(
const slang::ast::ConcatenationExpression &expr) {
826 SmallVector<Value> operands;
827 for (
auto *operand : expr.operands()) {
831 operands.push_back(value);
833 return builder.create<moore::ConcatRefOp>(loc, operands);
837 Value visit(
const slang::ast::ElementSelectExpression &expr) {
842 if (
auto *constValue = expr.selector().constant) {
843 assert(!constValue->hasUnknown());
844 assert(constValue->size() <= 32);
846 auto lowBit = constValue->integer().as<uint32_t>().value();
847 return builder.create<moore::ExtractRefOp>(
854 return builder.create<moore::DynExtractRefOp>(
860 Value visit(
const slang::ast::RangeSelectExpression &expr) {
867 uint32_t constLowBit;
868 auto *leftConst = expr.left().constant;
869 auto *rightConst = expr.right().constant;
871 assert(!leftConst->hasUnknown());
872 assert(leftConst->size() <= 32);
875 assert(!rightConst->hasUnknown());
876 assert(rightConst->size() <= 32);
879 if (expr.getSelectionKind() == slang::ast::RangeSelectionKind::Simple) {
880 if (leftConst && rightConst) {
882 auto lhs = leftConst->integer().as<uint32_t>().value();
883 auto rhs = rightConst->integer().as<uint32_t>().value();
884 constLowBit = lhs < rhs ? lhs : rhs;
886 mlir::emitError(loc,
"unsupported a variable as the index in the")
890 }
else if (expr.getSelectionKind() ==
891 slang::ast::RangeSelectionKind::IndexedDown) {
896 auto subtrahend = leftConst->integer().as<uint32_t>().value();
898 expr.right().constant->integer().as<uint32_t>().value();
899 constLowBit = subtrahend - sliceWidth - 1;
902 auto subtrahendType = cast<moore::UnpackedType>(subtrahend.getType());
904 subtrahendType.getBitSize().value(),
905 subtrahendType.getDomain());
907 expr.right().constant->integer().as<uint32_t>().value() - 1;
909 builder.create<moore::ConstantOp>(loc, intType, sliceWidth);
910 dynLowBit = builder.create<moore::SubOp>(loc, subtrahend, minuend);
915 constLowBit = leftConst->integer().as<uint32_t>().value();
919 if (leftConst && rightConst)
920 return builder.create<moore::ExtractRefOp>(
923 return builder.create<moore::DynExtractRefOp>(
928 Value visit(
const slang::ast::MemberAccessExpression &expr) {
930 auto valueType = expr.value().type;
934 if (valueType->isStruct()) {
935 return builder.create<moore::StructExtractRefOp>(
937 builder.getStringAttr(expr.member.name), value);
939 if (valueType->isPackedUnion() || valueType->isUnpackedUnion()) {
940 return builder.create<moore::UnionExtractRefOp>(
942 builder.getStringAttr(expr.member.name), value);
944 mlir::emitError(loc,
"expression of type ")
945 << value.getType() <<
" cannot be accessed";
950 template <
typename T>
951 Value visit(T &&node) {
955 Value visitInvalid(
const slang::ast::Expression &expr) {
956 mlir::emitError(loc,
"invalid expression");
965 auto value = expr.visit(RvalueExprVisitor(*
this, loc));
966 if (value && requiredType)
974 return expr.visit(LvalueExprVisitor(*
this, loc));
982 if (
auto type = dyn_cast_or_null<moore::IntType>(value.getType()))
983 if (type.getBitSize() == 1)
985 if (
auto type = dyn_cast_or_null<moore::UnpackedType>(value.getType()))
986 return builder.create<moore::BoolCastOp>(value.getLoc(), value);
987 mlir::emitError(value.getLoc(),
"expression of type ")
988 << value.getType() <<
" cannot be cast to a boolean";
994 const slang::ast::Type &astType, Location loc) {
999 bool typeIsFourValued =
false;
1000 if (
auto unpackedType = dyn_cast<moore::UnpackedType>(type))
1005 fvint.hasUnknown() || typeIsFourValued
1008 Value result =
builder.create<moore::ConstantOp>(loc, intType, fvint);
1009 if (result.getType() != type)
1010 result =
builder.create<moore::ConversionOp>(loc, type, result);
1015 const slang::ast::Type &type, Location loc) {
1016 if (constant.isInteger())
1021 slang::ConstantValue
1023 using slang::ast::EvalFlags;
1024 slang::ast::EvalContext evalContext(
1025 compilation, EvalFlags::CacheResults | EvalFlags::SpecparamsAllowed);
1026 return expr.eval(evalContext);
1036 if (value.getType() == type)
1038 return builder.create<moore::ConversionOp>(value.getLoc(), type, value);
1044 if (isa<moore::IntType>(value.getType()))
1051 if (
auto packed = dyn_cast<moore::PackedType>(value.getType())) {
1052 if (
auto bits = packed.getBitSize()) {
1055 return builder.create<moore::ConversionOp>(value.getLoc(), sbvType,
1060 mlir::emitError(value.getLoc()) <<
"expression of type " << value.getType()
1061 <<
" cannot be cast to a simple bit vector";
1067 if (type == value.getType())
1069 auto dstPacked = dyn_cast<moore::PackedType>(type);
1070 auto srcPacked = dyn_cast<moore::PackedType>(value.getType());
1073 if (dstPacked && srcPacked && dstPacked.getBitSize() &&
1074 srcPacked.getBitSize() &&
1075 *dstPacked.getBitSize() != *srcPacked.getBitSize()) {
1076 auto dstWidth = *dstPacked.getBitSize();
1077 auto srcWidth = *srcPacked.getBitSize();
1081 srcPacked.getDomain());
1082 if (value.getType() != srcWidthType)
1083 value =
builder.create<moore::ConversionOp>(value.getLoc(), srcWidthType,
1089 srcPacked.getDomain());
1090 if (dstWidth < srcWidth) {
1091 value =
builder.create<moore::TruncOp>(loc, dstWidthType, value);
1092 }
else if (dstWidth > srcWidth) {
1094 value =
builder.create<moore::SExtOp>(loc, dstWidthType, value);
1096 value =
builder.create<moore::ZExtOp>(loc, dstWidthType, value);
1100 if (value.getType() != type)
1101 value =
builder.create<moore::ConversionOp>(loc, type, value);
assert(baseType &&"element must be base type")
static FVInt convertSVIntToFVInt(const slang::SVInt &svint)
Convert a Slang SVInt to a CIRCT FVInt.
const char * toString(Flow flow)
Four-valued arbitrary precision integers.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Domain
The number of values each bit of a type can assume.
@ FourValued
Four-valued types such as logic or integer.
@ TwoValued
Two-valued types such as bit or int.
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 materializeConversion(Type type, Value value, bool isSigned, Location loc)
Helper function to insert the necessary operations to cast a value from one type to another.
Value convertLvalueExpression(const slang::ast::Expression &expr)
Value materializeConstant(const slang::ConstantValue &constant, const slang::ast::Type &type, Location loc)
Helper function to materialize a ConstantValue as an SSA value.
slang::ConstantValue evaluateConstant(const slang::ast::Expression &expr)
Evaluate the constant value of an expression.
slang::ast::Compilation & compilation
OpBuilder builder
The builder used to create IR operations.
std::function< void(moore::ReadOp)> rvalueReadCallback
A listener called for every variable or net being read.
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
Value materializeSVInt(const slang::SVInt &svint, const slang::ast::Type &type, Location loc)
Helper function to materialize an SVInt as an SSA value.
Value convertToBool(Value value)
Helper function to convert a value to its "truthy" boolean value.
ValueSymbols valueSymbols
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
Value convertToSimpleBitVector(Value value)
Helper function to convert a value to its simple bit vector representation, if it has one.
FunctionLowering * declareFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function and its arguments to a function declaration in the IR.
MLIRContext * getContext()
Return the MLIR context.
SmallVector< Value > lvalueStack
A stack of assignment left-hand side values.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.