Skip to content

Commit

Permalink
Merge branch 'master' of github.com:specs-feup/specs-java-libs
Browse files Browse the repository at this point in the history
  • Loading branch information
joaobispo committed May 10, 2024
2 parents 71d7ef7 + 46c3de4 commit d81387e
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 48 deletions.
1 change: 1 addition & 0 deletions AsmParser/.classpath
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=AsmParser&amp;ivyXmlPath=ivy.xml&amp;confs=*"/>
<classpathentry kind="output" path="bin"/>
</classpath>
1 change: 1 addition & 0 deletions AsmParser/.project
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.apache.ivyde.eclipse.ivynature</nature>
</natures>
</projectDescription>
13 changes: 11 additions & 2 deletions AsmParser/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ dependencies {
testImplementation "junit:junit:4.11"

implementation ':SpecsUtils'
implementation ':jOptions'

implementation ':jOptions'

implementation group: 'com.google.code.gson', name: 'gson', version: '2.4'
}

java {
Expand All @@ -35,11 +36,19 @@ sourceSets {
java {
srcDir 'src'
}

resources {
srcDir 'test'
}
}

test {
java {
srcDir 'test'
}

resources {
srcDir 'test'
}
}
}
31 changes: 31 additions & 0 deletions AsmParser/ivy.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info
organisation="specs.fe.up.pt"
module="AsmParser"
status="release">
</info>

<dependencies>
<dependency org="com.google.code.gson" name="gson" rev="2.4"/>
</dependencies>
</ivy-module>
104 changes: 104 additions & 0 deletions AsmParser/src/pt/up/fe/specs/asmparser/Isa32bitParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package pt.up.fe.specs.asmparser;

import com.google.gson.Gson;
import pt.up.fe.specs.asmparser.ast.FieldNode;
import pt.up.fe.specs.asmparser.ast.RuleNode;
import pt.up.fe.specs.asmparser.parser32bit.Asm32bitParser;
import pt.up.fe.specs.util.SpecsIo;

import java.util.*;

public class Isa32bitParser {

public static void main(String[] args) {
var isaParser = newInstance(SpecsIo.getResource(() -> "pt/up/fe/specs/binarytranslation/asm/parsing/asm_test.json"));

//"0110_xx_registerd(5)_1000_opcode(1)_0_imm(15)"
// 31, 1, 10925
var decoded = isaParser.parse(Long.parseLong("01100011111100010010101010101101", 2));
System.out.println(Arrays.toString(decoded));
}


private final List<Asm32bitParser> parsers;
private final Map<String, Integer> fieldsMap;

private Isa32bitParser(List<Asm32bitParser> parsers, Map<String, Integer> fieldsMap) {
this.parsers = parsers;
this.fieldsMap = fieldsMap;
}


public static Isa32bitParser newInstance(String jsonContents) {
var isa = new Gson().fromJson(jsonContents, Map.class);

//var fields = new LinkedHashSet<>((List<String>) isa.get("fields"));

// Maps a field to an index
var fieldsMap = new HashMap<String, Integer>();

// Index 0 is id of format
var fieldId = 1;
for (var field : (List<String>) isa.get("fields")) {
fieldsMap.put(field, fieldId);
fieldId++;
}

// System.out.println("FIELDS MAP: " + fieldsMap);

int id = 0;
var parsers = new ArrayList<Asm32bitParser>();
for (var format : (List<String>) isa.get("formats")) {

// Parse format
var rule = new InstructionFormatParser().parse(format);

// Verify rule
verify(rule, format, fieldsMap.keySet());

// Create parser
var parser = Asm32bitParser.build(id, rule, fieldsMap);
parsers.add(parser);
id++;
}


return new Isa32bitParser(parsers, fieldsMap);
}

private static void verify(RuleNode rule, String format, Set<String> fields) {
// Go to all fields, check they are declared
var invalidField = rule.getDescendants(FieldNode.class).stream()
.filter(node -> !fields.contains(node.getField()))
.findFirst()
.orElse(null);


if (invalidField != null) {
throw new RuntimeException("Found undeclared field '" + invalidField.getField() + "' in format rule '" + format + "'");
}

}

public Map<String, Integer> getFieldsMap() {
return fieldsMap;
}

public int[] parse(long instruction) {
// Iterate over all parsers, looking for one that accepts the instruction
for (var parser : parsers) {
var decoded = parser.parse(instruction);

// Could not decode, skip
if (decoded == null) {
continue;
}

// Decoded, return
return decoded;
}

throw new RuntimeException("Could not decode instruction 0x" + Long.toString(instruction, 16));
}

}
3 changes: 3 additions & 0 deletions AsmParser/src/pt/up/fe/specs/asmparser/ast/FieldNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ public FieldNode(DataStore data, Collection<? extends InstructionFormatNode> chi
super(data, children);
}

public String getField() {
return get(FIELD);
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,68 @@
/**
* Copyright 2024 SPeCS.
*
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p>
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. under the License.
*/

package pt.up.fe.specs.asmparser.parser32bit;

import java.util.List;

import pt.up.fe.specs.asmparser.ast.ConstantNode;
import pt.up.fe.specs.asmparser.ast.FieldNode;
import pt.up.fe.specs.asmparser.ast.IgnoreNode;
import pt.up.fe.specs.asmparser.ast.InstructionFormatNode;
import pt.up.fe.specs.asmparser.ast.RuleNode;
import pt.up.fe.specs.asmparser.ast.*;
import pt.up.fe.specs.asmparser.parser32bit.rules.Asm32bitConstantRule;
import pt.up.fe.specs.asmparser.parser32bit.rules.Asm32bitFieldRule;
import pt.up.fe.specs.asmparser.parser32bit.rules.Asm32bitIgnoreRule;
import pt.up.fe.specs.asmparser.parser32bit.rules.Asm32bitRule;
import pt.up.fe.specs.util.exceptions.NotImplementedException;

import java.util.List;
import java.util.Map;

public class Asm32bitParser {

private final int id;
private final List<Asm32bitRule> rules;
private final Map<String, Integer> fieldsMap;

private final int numFields;
private final int[] fieldIndexes;

private Asm32bitParser(int id, List<Asm32bitRule> rules) {
private Asm32bitParser(int id, List<Asm32bitRule> rules, Map<String, Integer> fieldsMap) {
this.id = id;
this.rules = rules;
this.numFields = (int) rules.stream()
.filter(rule -> rule.hasValue())
.count();
this.fieldsMap = fieldsMap;
this.fieldIndexes = buildFieldsIndexes(rules, fieldsMap);
this.numFields = fieldIndexes.length;
}

private int[] buildFieldsIndexes(List<Asm32bitRule> rules, Map<String, Integer> fieldsMap) {
var fieldRules = rules.stream()
.filter(rule -> rule instanceof Asm32bitFieldRule)
.map(Asm32bitFieldRule.class::cast)
.toList();

var numFields = fieldsMap != null ? fieldsMap.size() : fieldRules.size();

var fieldIndexes = new int[numFields];

// If no map, just fill with indexes from 1 to N
if (fieldsMap == null) {
for (int i = 0; i < numFields; i++) {
fieldIndexes[i] = i + 1;
}
} else {
// Iterate over all rules with fields, store the corresponding index
for (int i = 0; i < fieldRules.size(); i++) {
fieldIndexes[i] = fieldsMap.get(fieldRules.get(i).getField());
}
}

return fieldIndexes;
}

public int[] parse(long instruction) {
Expand All @@ -46,7 +71,8 @@ public int[] parse(long instruction) {
int[] decoded = new int[1 + numFields];
decoded[0] = id;

int fieldIndex = 1;
//int fieldIndex = 1;
int fieldIndex = 0;
int startIndex = 0;

// Iterate over all rules
Expand All @@ -59,8 +85,8 @@ public int[] parse(long instruction) {
}

// If rule extracts a value, store it
if (rule.hasValue()) {
decoded[fieldIndex] = res.value();
if (rule instanceof Asm32bitFieldRule) {
decoded[fieldIndexes[fieldIndex]] = res.value();
fieldIndex++;
}

Expand All @@ -72,6 +98,10 @@ public int[] parse(long instruction) {
}

public static Asm32bitParser build(int id, RuleNode rule) {
return build(id, rule, null);
}

public static Asm32bitParser build(int id, RuleNode rule, Map<String, Integer> fieldsMap) {
// Check if total bits is 32
var totalBits = rule.getTotalBits();
if (totalBits != 32) {
Expand All @@ -82,7 +112,7 @@ public static Asm32bitParser build(int id, RuleNode rule) {
.map(Asm32bitParser::convert)
.toList();

return new Asm32bitParser(id, rules);
return new Asm32bitParser(id, rules, fieldsMap);
}

private static Asm32bitRule convert(InstructionFormatNode node) {
Expand All @@ -94,8 +124,8 @@ private static Asm32bitRule convert(InstructionFormatNode node) {
return new Asm32bitIgnoreRule(node.getNumBits());
}

if (node instanceof FieldNode) {
return new Asm32bitFieldRule(node.getNumBits());
if (node instanceof FieldNode fieldNode) {
return new Asm32bitFieldRule(fieldNode.getField(), fieldNode.getNumBits());
}

throw new NotImplementedException(node.getClass());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/**
* Copyright 2024 SPeCS.
*
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p>
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. under the License.
Expand All @@ -18,14 +18,20 @@

public class Asm32bitFieldRule implements Asm32bitRule {

private final String field;
private final int numBits;
private final long mask;

public Asm32bitFieldRule(int numBits) {
public Asm32bitFieldRule(String field, int numBits) {
this.field = field;
this.numBits = numBits;
this.mask = SpecsBits.mask(-1, numBits);
}

public String getField() {
return field;
}

@Override
public Asm32bitResult parse(long asm, int startIndex) {

Expand All @@ -40,9 +46,5 @@ public Asm32bitResult parse(long asm, int startIndex) {
return new Asm32bitResult(startIndex + numBits, (int) asmFiltered);
}

@Override
public boolean hasValue() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface Asm32bitRule {

Asm32bitResult parse(long asm, int startIndex);

default boolean hasValue() {
return false;
}
// default boolean hasValue() {
// return false;
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ public void test1() {
*/
}

@Test
public void testFromJson() {

}

}
Loading

0 comments on commit d81387e

Please sign in to comment.