Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.minres.coredsl.coreDsl.Statement
import com.minres.coredsl.tests.CoreDslInjectorProvider
import com.minres.coredsl.tests.CoreDslTestHelper
import com.minres.coredsl.type.IntegerType
import com.minres.coredsl.validation.IssueCodes
import java.math.BigInteger
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.ecore.EObject
Expand Down Expand Up @@ -339,6 +340,89 @@ class CoreDslExpressionTest {
.expectSyntaxErrors()
.run();
}

@Test
def intrinsicSizeOfValid() {
'''
int a = bitsizeof(1'b0);
int b = bitsizeof(8'b101010);
int c = bitsizeof(24'd0);

signed<14> d = bitsizeof(c);
int e = bitsizeof(d);

int f = bitsizeof(int);
int g = bitsizeof(unsigned<1337>);
'''
.testStatements()
.expectTypeAndValue(null, initializerOf('a'), IntegerType.unsigned(1), 1)
.expectTypeAndValue(null, initializerOf('b'), IntegerType.unsigned(4), 8)
.expectTypeAndValue(null, initializerOf('c'), IntegerType.unsigned(5), 24)
.expectTypeAndValue(null, initializerOf('d'), IntegerType.unsigned(6), 32)
.expectTypeAndValue(null, initializerOf('e'), IntegerType.unsigned(4), 14)
.expectTypeAndValue(null, initializerOf('f'), IntegerType.unsigned(6), 32)
.expectTypeAndValue(null, initializerOf('g'), IntegerType.unsigned(11), 1337)
.run();

'''
int a = sizeof(1'b0);
int b = sizeof(8'b101010);
int c = sizeof(24'b101010);

signed<14> d = sizeof(c);
int e = sizeof(d);

int f = sizeof(int);
int g = sizeof(unsigned<1337>);
'''
.testStatements()
.expectWarning(IssueCodes.SizeOfNotExact, 1)
.expectWarning(IssueCodes.SizeOfNotExact, 6)
.expectWarning(IssueCodes.SizeOfNotExact, 9)
.expectTypeAndValue(null, initializerOf('a'), IntegerType.unsigned(1), 1)
.expectTypeAndValue(null, initializerOf('b'), IntegerType.unsigned(1), 1)
.expectTypeAndValue(null, initializerOf('c'), IntegerType.unsigned(2), 3)
.expectTypeAndValue(null, initializerOf('d'), IntegerType.unsigned(3), 4)
.expectTypeAndValue(null, initializerOf('e'), IntegerType.unsigned(2), 2)
.expectTypeAndValue(null, initializerOf('f'), IntegerType.unsigned(3), 4)
.expectTypeAndValue(null, initializerOf('g'), IntegerType.unsigned(8), 168)
.run();
}

@Test
def intrinsicSizeOfInvalid() {
'''
int a = bitsizeof();
int b = bitsizeof(1, 2);
'''
.testStatements()
.expectError(IssueCodes.InvalidArgumentCount, 1)
.expectError(IssueCodes.InvalidArgumentCount, 2)
.run();

'''
int a = sizeof();
int b = sizeof(1, 2);
'''
.testStatements()
.expectError(IssueCodes.InvalidArgumentCount, 1)
.expectError(IssueCodes.InvalidArgumentCount, 2)
.run();

'''
Core X {
architectural_state {
int x = bitsizeof(255 + 1);
int y = sizeof(255 + 1);
}
}
'''
.testProgram()
.expectError(IssueCodes.InvalidIsaStateElementValue, 1)
.expectError(IssueCodes.UnsupportedSizeOfDuringElaboration, 3)
.expectError(IssueCodes.UnsupportedSizeOfDuringElaboration, 4)
.run();
Copy link
Contributor Author

@AtomCrafty AtomCrafty Dec 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note this test. The way type analysis works, sizeof(255+1) (=9) is not able to be used in elaboration-time constants. This is because the types of expressions are only determined during analysis, which happens after elaboration. If we wanted to support this case we'd have to do full type analysis during elaboration, which would require a major restructuring of the analysis framework.

The constant expression evaluator has special handling of sizeof(<type>) and sizeof(<identifier>), so those can still be used, but expressions using any operator are unsupported.

}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class AnalysisContext extends ProxyMessageAcceptor {
public val ISA root;
public val boolean isPartialAnalysis;
public val Set<ISA> analyzedIsas = new HashSet();
public var isElaborationDone = false;

new(ISA root, ValidationMessageAcceptor acceptor) {
super(acceptor, root, root, CoreDslPackage.Literals.ISA__NAME, -1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ class CoreDslConstantExpressionEvaluator {
if(type.isIncomplete) return ConstantValue.indeterminate;
if(inBytes) {
if(type.bitSize % 8 !== 0) {
ctx.acceptWarning('The size is not an exact multiple of 8', target.object, target.feature, target.index,
IssueCodes.SizeOfNotExact);
ctx.acceptWarning('The size (' + type.bitSize + ' bits) is not an exact multiple of 8', target.object,
target.feature, target.index, IssueCodes.SizeOfNotExact);
}
return new ConstantValue((type.bitSize + 7) / 8);
} else {
Expand Down Expand Up @@ -172,7 +172,13 @@ class CoreDslConstantExpressionEvaluator {
}
}
Expression: {
val type = ctx.getExpressionType(expression);
if(!ctx.isElaborationDone) {
ctx.acceptError('Size of expression can not be determined during elaboration', expression,
CoreDslPackage.Literals.INTRINSIC_EXPRESSION__FUNCTION, -1,
IssueCodes.UnsupportedSizeOfDuringElaboration);
return ConstantValue.invalid;
}
val type = ctx.getExpressionType(arg);
return getTypeSize(ctx, type, inBytes, target);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class CoreDslElaborator {
validateResults(ctx);
checkDuplicateDeclarations(ctx);

ctx.analysisContext.isElaborationDone = true;

return ctx;
}

Expand Down Expand Up @@ -187,7 +189,7 @@ class CoreDslElaborator {
CoreDslPackage.Literals.ASSIGNMENT_EXPRESSION__OPERATOR, -1,
IssueCodes.InvalidIsaParameterAssignmentOperator);
}

if(reference?.target.eIsProxy) {
// linking error
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class IntegerValueConverter extends AbstractLexerBasedConverter<TypedBigInteger>
value = new TypedBigInteger(value - BigInteger.ONE.shiftLeft(value.bitLength), radix, size, signed);
}

// TODO test this with negative numbers
if(size == 0 || size > 0 && value.bitLength > size) {
throw new ValueConverterException('''Value «value» does not fit into «size» bits''', node, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@ import com.minres.coredsl.coreDsl.Declarator
import com.minres.coredsl.coreDsl.EnumTypeDeclaration
import com.minres.coredsl.coreDsl.ISA
import com.minres.coredsl.coreDsl.InstructionSet
import com.minres.coredsl.coreDsl.NamedEntity
import com.minres.coredsl.coreDsl.StructTypeDeclaration
import com.minres.coredsl.coreDsl.TypeQualifier
import com.minres.coredsl.coreDsl.UnionTypeDeclaration
import com.minres.coredsl.coreDsl.UserTypeDeclaration
import java.util.ArrayList
import java.util.HashSet
import java.util.Iterator
import java.util.List
import org.eclipse.emf.ecore.EObject
import org.eclipse.xtext.nodemodel.util.NodeModelUtils

import static extension com.minres.coredsl.util.DataExtensions.*
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
import com.minres.coredsl.coreDsl.NamedEntity

abstract class ModelExtensions {
private new() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,5 @@ class IssueCodes {
public static val IndexOutOfRange = _prefix + 'IndexOutOfRange';
public static val IncompleteType = _prefix + 'IncompleteType';
public static val LikelyAccidentalAssignment = _prefix + 'LikelyAccidentalAssignment';
public static val UnsupportedSizeOfDuringElaboration = _prefix + 'UnsupportedSizeOfDuringElaboration';
}