Skip to content

Commit b45a704

Browse files
authored
frontend: Adjust alias register slicing behavior (#519)
1 parent 0bbf258 commit b45a704

File tree

7 files changed

+56
-13
lines changed

7 files changed

+56
-13
lines changed

sys/aarch64/aarch64.vadl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ instruction set architecture AArch64Base = {
6464
[zero : X(31)] // X(31) is the zero register
6565
alias register X = S // general purpose register file with zero register
6666
[zero : W(31)] // X(31) is the zero register
67+
[overwrite source: zero] // S is overwritten on write by zero extending the written value
6768
alias register W = X(*)(31..0) // lower half of general purpose register file with zero register
6869
alias register SP : Address = S(31) // stack pointer
6970
alias register LR : Address = S(30) // link register (return address)

vadl/main/vadl/ast/AnnotationTable.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ public class AnnotationTable {
155155
})
156156
.build();
157157

158+
annotationOn(AliasDefinition.class, "overwrite source",
159+
() -> new EnumAnnotation(List.of("zero", "sign")))
160+
.check((def, annotation, lowering) -> {
161+
annotation.verifyValuesCnt(annotation.definition, 1);
162+
})
163+
.build();
164+
158165
/// PROCESSOR RELATED ///
159166

160167
annotationOn(ProcessorDefinition.class, "htif", EnableAnnotation::new)
@@ -1140,7 +1147,7 @@ void resolveName(AnnotationDefinition definition, SymbolTable.SymbolResolver res
11401147

11411148
if (!possibleValues.contains(value)) {
11421149
throw error("Invalid Annotation Argument", definition)
1143-
.locationDescription(definition, "Expected one of %s but got %s",
1150+
.locationDescription(definition, "Expected one of %s but got `%s`",
11441151
String.join(", ", possibleValues), value)
11451152
.build();
11461153
}

vadl/main/vadl/ast/BehaviorLowering.java

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import static vadl.utils.GraphUtils.neq;
2525
import static vadl.utils.GraphUtils.or;
2626
import static vadl.utils.GraphUtils.select;
27-
import static vadl.utils.GraphUtils.truncate;
27+
import static vadl.utils.GraphUtils.signExtend;
2828
import static vadl.utils.GraphUtils.zeroExtend;
2929

3030
import com.google.common.collect.Lists;
@@ -37,6 +37,7 @@
3737
import java.util.stream.Collectors;
3838
import javax.annotation.Nullable;
3939
import vadl.types.BitsType;
40+
import vadl.types.BoolType;
4041
import vadl.types.BuiltInTable;
4142
import vadl.types.ConcreteRelationType;
4243
import vadl.types.DataType;
@@ -312,8 +313,9 @@ Function getRegisterAliasReadFunc(AliasDefinition definition) {
312313
);
313314
}
314315

315-
if (definition.slice != null) {
316-
regAccess = truncate(regAccess, Type.bits(definition.slice.bitSize()));
316+
var slice = definition.slice;
317+
if (slice != null) {
318+
regAccess = new SliceNode(regAccess, slice, Type.bits(slice.bitSize()));
317319
}
318320

319321
var returnNode = graph.addWithInputs(new ReturnNode(regAccess));
@@ -375,11 +377,28 @@ Procedure getRegisterAliasWriteProc(AliasDefinition definition) {
375377

376378
var regFile = (RegisterTensor) viamLowering.fetch(regFileDef).orElseThrow();
377379

378-
if (definition.slice != null) {
379-
ensure(definition.slice.lsb() == 0,
380+
var slice = definition.slice;
381+
if (slice != null) {
382+
ensure(slice.lsb() == 0,
380383
() -> error("Unsupported alias slice", definition)
381384
.description("Currently, the alias slice MSB must be 0."));
382-
writeValue = zeroExtend(writeValue, regFile.resultType(indices.size()));
385+
386+
var sourceRegType = regFile.resultType(indices.size());
387+
var overwriteAnno = definition.findAnnotation("overwrite source", EnumAnnotation.class);
388+
var overwriteMode = overwriteAnno == null ? null : overwriteAnno.value;
389+
390+
// If we have a slice, we must adjust the write values accordingly.
391+
// By default, we prepare the write values to be sliced by reading the original content.
392+
// If the [overwrite source:] annotation is set, we instead either zero or sign extend the
393+
// write value to overwrite the whole source register.
394+
writeValue = switch (overwriteMode) {
395+
case null -> sliceWriteValue(writeValue,
396+
new ReadRegTensorNode(regFile, indices, sourceRegType, null), List.of(slice));
397+
case "zero" -> zeroExtend(writeValue, sourceRegType);
398+
case "sign" -> signExtend(writeValue, sourceRegType);
399+
default -> throw new IllegalStateException(
400+
"Unexpected value: " + overwriteMode);
401+
};
383402
}
384403

385404
// FIXME: Support pre-indexed registers, for example:
@@ -684,7 +703,8 @@ public ExpressionNode visit(GroupedExpr expr) {
684703
@Override
685704
public ExpressionNode visit(IntegerLiteral expr) {
686705
// IntegerLiteral should never be reached as it should always be substituted by the typechecker.
687-
throw new IllegalStateException("IntegerLiteral should never be reached in the VIAM lowering.");
706+
throw new IllegalStateException(
707+
"IntegerLiteral should never be reached in the VIAM lowering.");
688708
}
689709

690710
@Override
@@ -771,7 +791,8 @@ private ExpressionNode visitSubCall(CallIndexExpr expr, ExpressionNode exprBefor
771791
(DataType) getViamType(Objects.requireNonNull(subCall.formatFieldType)));
772792
resultExpr = visitSliceIndexCall(slice, subCall.argsIndices);
773793
} else if (subCall.computedStatusIndex != null) {
774-
var indexing = new TupleGetFieldNode(subCall.computedStatusIndex, resultExpr, Type.bool());
794+
var indexing =
795+
new TupleGetFieldNode(subCall.computedStatusIndex, resultExpr, Type.bool());
775796
resultExpr = visitSliceIndexCall(indexing, subCall.argsIndices);
776797
} else if (exprBeforeSubcall instanceof ReadResourceNode resRead) {
777798
var computedTarget = expr.target.path().target();
@@ -923,7 +944,7 @@ public ExpressionNode visit(CastExpr expr) {
923944
var sourceDataType = (DataType) sourceType;
924945
var targetDataType = (DataType) targetType;
925946

926-
if (targetType.getClass() == vadl.types.BoolType.class) {
947+
if (targetType.getClass() == BoolType.class) {
927948
// match 2. rule: target type is bool
928949
// -> produce != 0 call
929950
//return new BuiltInCall
@@ -1136,7 +1157,7 @@ yield new WriteMemNode(
11361157
* Method that prepares the value so it can be written to a subset region of a resource.
11371158
* The entire resource before writing the value is given by the entireRead node.
11381159
* The subset region of the resource is given by the slices list, that
1139-
* holds a list of {@link vadl.viam.Constant.BitSlice}.
1160+
* holds a list of {@link Constant.BitSlice}.
11401161
* E.g. {@code A(3, 15..11) := 0b101111} writes the value's msb `1` at position 3 in the
11411162
* resource,
11421163
* and the rest (0b01111) is written to position 15 to 11 (inclusive) in the resource.
@@ -1266,7 +1287,8 @@ public SubgraphContext visit(InstructionCallStatement statement) {
12661287
}
12671288

12681289
var target =
1269-
(Instruction) viamLowering.fetch(Objects.requireNonNull(statement.instrDef)).orElseThrow();
1290+
(Instruction) viamLowering.fetch(Objects.requireNonNull(statement.instrDef))
1291+
.orElseThrow();
12701292
var fieldMap = Arrays.stream(target.encoding().nonEncodedFormatFields())
12711293
.collect(Collectors.toMap(Definition::simpleName, f -> f));
12721294

@@ -1492,7 +1514,8 @@ static SubgraphContext of(Node root, List<vadl.viam.graph.Node> nodes) {
14921514

14931515
SubgraphContext setSideEffects(NodeList<SideEffectNode> sideEffects) {
14941516
if (this.sideEffects != null) {
1495-
throw new IllegalStateException("SideEffects already set to: %s".formatted(this.sideEffects));
1517+
throw new IllegalStateException(
1518+
"SideEffects already set to: %s".formatted(this.sideEffects));
14961519
}
14971520
this.sideEffects = sideEffects;
14981521
return this;

vadl/main/vadl/ast/Definition.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ static void prettyPrintDefinitions(int indent, StringBuilder builder,
8585
}
8686
}
8787

88+
@Nullable
89+
<T extends Annotation> T findAnnotation(String name, Class<T> annotationClass) {
90+
return annotations.stream()
91+
.filter(a -> a.name().equals(name))
92+
.map(a -> a.annotation)
93+
.filter(annotationClass::isInstance)
94+
.map(annotationClass::cast).findFirst().orElse(null);
95+
}
96+
8897
abstract <R> R accept(DefinitionVisitor<R> visitor);
8998
}
9099

vadl/main/vadl/ast/ParserUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class ParserUtils {
136136
ID_TOKENS[Parser._SEQUENCE] = true;
137137
ID_TOKENS[Parser._SIGNED] = true;
138138
ID_TOKENS[Parser._SIZE_T] = true;
139+
ID_TOKENS[Parser._SOURCE] = true;
139140
ID_TOKENS[Parser._STAGE] = true;
140141
ID_TOKENS[Parser._STARTUP] = true;
141142
ID_TOKENS[Parser._RESET] = true;

vadl/main/vadl/ast/vadl.ATG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,7 @@ PRODUCTIONS
18691869
| SEQUENCE
18701870
| SIGNED
18711871
| SIZE_T
1872+
| SOURCE
18721873
| STAGE
18731874
| STARTUP
18741875
| RESET

vadl/test/resources/testSource/sys/aarch64/aarch64.vadl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ instruction set architecture AArch64Base = {
6464
[zero : X(31)] // X(31) is the zero register
6565
alias register X = S // general purpose register file with zero register
6666
[zero : W(31)] // X(31) is the zero register
67+
[overwrite source: zero] // S is overwritten on write by zero extending the written value
6768
alias register W = X(*)(31..0) // lower half of general purpose register file with zero register
6869
alias register SP : Address = S(31) // stack pointer
6970
alias register LR : Address = S(30) // link register (return address)

0 commit comments

Comments
 (0)