Initial checkin

This commit is contained in:
2021-09-25 16:22:15 +02:00
commit 07831ef4fc
41 changed files with 19782 additions and 0 deletions
@@ -0,0 +1,171 @@
package com.minres.coredsl.json.tests
import com.google.inject.Inject
import com.minres.coredsl.coreDsl.CoreDef
import com.minres.coredsl.coreDsl.DescriptionContent
import org.eclipse.emf.ecore.util.EcoreUtil
import org.eclipse.xtext.generator.GeneratorContext
import org.eclipse.xtext.generator.IGenerator2
import org.eclipse.xtext.generator.InMemoryFileSystemAccess
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.testing.util.ParseHelper
import org.eclipse.xtext.util.CancelIndicator
import org.junit.Test
import org.junit.runner.RunWith
import static org.junit.Assert.*
import static extension com.google.common.io.CharStreams.*
import com.minres.coredsl.coreDsl.InstructionSet
import java.io.FileReader
import org.eclipse.xtext.testing.validation.ValidationTestHelper
@RunWith(XtextRunner)
@InjectWith(CoreDslInjectorProvider)
class CoreDslGenerationTest{
@Inject IGenerator2 generator
@Inject extension ParseHelper<DescriptionContent> parseHelper
@Inject ValidationTestHelper validator
val isa_rv32i = '''
Core RV32I {
constants {
unsigned int XLEN, FLEN;
unsigned CSR_SIZE = 4096;
unsigned REG_FILE_SIZE=32;
}
registers {
[[is_pc]] int PC ;
int X[REG_FILE_SIZE];
}
address_spaces {
char MEM[1<<XLEN];
unsigned CSR[CSR_SIZE];
}
instructions {
ADDI {
encoding: imm[11:0]s :: rs1[4:0] :: b000 :: rd[4:0] :: b0010011;
behavior: {
X[rd] = X[rs1] + imm;
}
}
SLTI {
encoding: imm[11:0]s :: rs1[4:0] :: b010 :: rd[4:0] :: b0010011;
behavior: {
X[rd] = X[rs1] < imm? 1 : 0;
}
}
SLTIU {
encoding: imm[11:0]s :: rs1[4:0] :: b011 :: rd[4:0] :: b0010011;
behavior: {
X[rd] = X[rs1] < imm? 1 : 0;
}
}
SW {
encoding: imm[11:5]s :: rs2[4:0] :: rs1[4:0] :: b010 :: imm[4:0]s :: b0100011;
behavior: {
int offset = X[rs1] + imm;
MEM[offset] = X[rs2];
}
}
JAL[[no_cont]] {
encoding:imm[20:20]s :: imm[10:1]s :: imm[11:11]s :: imm[19:12]s :: rd[4:0] :: b1101111;
behavior: {
if(rd!=0) X[rd] = (unsigned)PC;
PC = PC+imm;
}
}
}
}
'''
@Test
def void loadSimpleModel() {
val content = new FileReader('inputs/isa_1.core_desc').readLines.join('\n').parse
validator.assertNoErrors(content)
val InstructionSet result = content.definitions.get(0) as InstructionSet
assertNotNull(result)
assertEquals("RV32I", result.name)
assertNull(result.superType)
assertEquals(4, result.declarations.size())
assertNotNull(result.instructions)
assertEquals(5, result.instructions.size)
val i0 = result.instructions.get(0);
assertEquals("ADDI", i0.name)
assertEquals(5, i0.encoding.fields.size)
val i1 = result.instructions.get(1);
assertEquals("SLTI", i1.name)
assertEquals(5, i1.encoding.fields.size)
val i2 = result.instructions.get(2);
assertEquals("SLTIU", i2.name)
assertEquals(5, i2.encoding.fields.size)
val i3 = result.instructions.get(3);
assertEquals("SW", i3.name)
assertEquals(6, i3.encoding.fields.size)
}
@Test
def void generateCpp() {
val content = parseHelper.parse(isa_rv32i)
assertNotNull(content)
assertEquals(1, content.definitions.size)
val resource = content.eResource
EcoreUtil.resolveAll(resource);
assertEquals(0, resource.errors.size)
assertEquals(0, resource.warnings.size)
val fsa = new InMemoryFileSystemAccess()
generator.doGenerate(content.eResource, fsa, new GeneratorContext => [
cancelIndicator = CancelIndicator.NullImpl
])
println(fsa.textFiles)
assertEquals(1,fsa.textFiles.size)
assertTrue(fsa.textFiles.containsKey("DEFAULT_OUTPUTRV32I.txt"))
// assertEquals(
// '''
// public class Alice {
//
// }
// '''.toString, fsa.textFiles.get(IFileSystemAccess::DEFAULT_OUTPUT+"Alice.java").toString
// )
}
@Test
def void expandCppFile() {
val content = parseHelper.parse(isa_rv32i)
assertNotNull(content)
val resource = content.eResource
EcoreUtil.resolveAll(resource);
assertEquals(0, resource.errors.size)
assertEquals(0, resource.warnings.size)
val CoreDef model = content.definitions.get(0) as CoreDef
assertNotNull(model)
val fsa = new InMemoryFileSystemAccess()
val quote1 = ''
val quote2 = ''
fsa.generateFile("vm_" + model.name.toLowerCase + ".in.cpp", "vm-out", '''
/* quote1start generated codequote2 */
InstructionDesriptor instr_descr[0] = {};
/* quote1end generated codequote2 */
''')
generator.doGenerate(model.eResource, fsa, new GeneratorContext => [
cancelIndicator = CancelIndicator.NullImpl
])
println(fsa.textFiles)
assertEquals(2,fsa.textFiles.size)
assertTrue(fsa.textFiles.containsKey("DEFAULT_OUTPUTRV32I.txt"))
// assertEquals(
// '''
// public class Bob {
//
// }
// '''.toString, fsa.textFiles.get(IFileSystemAccess::DEFAULT_OUTPUT+"Bob.java").toString)
}
}
@@ -0,0 +1,117 @@
package com.minres.coredsl.json.tests
import com.google.inject.Inject
import com.minres.coredsl.coreDsl.DescriptionContent
import org.eclipse.xtext.generator.GeneratorContext
import org.eclipse.xtext.generator.IGenerator2
import org.eclipse.xtext.generator.InMemoryFileSystemAccess
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.testing.util.ParseHelper
import org.eclipse.xtext.testing.validation.ValidationTestHelper
import org.eclipse.xtext.util.CancelIndicator
import org.junit.Test
import org.junit.runner.RunWith
import static org.junit.Assert.*
import org.json.JSONObject
import org.json.JSONTokener
import org.json.JSONArray
@RunWith(XtextRunner)
@InjectWith(CoreDslInjectorProvider)
class CoreDslGenerationUnitTest{
@Inject IGenerator2 generator
@Inject extension ParseHelper<DescriptionContent> parseHelper
@Inject ValidationTestHelper validator
def CharSequence addInstructionContext(CharSequence str)'''
InstructionSet TestISA {
architectural_state {
unsigned XLEN;
const unsigned FLEN=32;
register unsigned<32> PC [[is_pc]];
register unsigned<32> X[32];
}
instructions {
«str»
}
}
Core TestCore provides TestISA {
architectural_state {
XLEN=32;
}
}
'''
@Test
def void genDisabledInstr() {
val content = '''
CLI {
encoding: 0b010 :: imm[5:5] :: rd[4:0] :: imm[4:0] :: 0b01;
behavior: {
if(rd == 0) //rd==0 is a hint, so no trap
X[rd] = (unsigned<32>)(signed)imm;
}
}
'''.addInstructionContext.parse
validator.assertNoErrors(content)
val ref = '''
void CLI(){
{
if(rd == 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm);
}
}
'''
val fsa = new InMemoryFileSystemAccess()
generator.doGenerate(content.eResource, fsa, new GeneratorContext => [
cancelIndicator = CancelIndicator.NullImpl
])
val res = fsa.textFiles
res.forEach[name, text|
val jsonTokener = new JSONTokener(text.toString)
val json = new JSONObject(jsonTokener);
assertNotNull(json.get("instructions"))
assertTrue(json.get("instructions") instanceof JSONArray)
val instructions = json.get("instructions") as JSONArray
assertEquals(0, instructions.length)
]
}
@Test
def void genEnabledInstr() {
val content = '''
CLI [[hls]]{
encoding: 0b010 :: imm[5:5] :: rd[4:0] :: imm[4:0] :: 0b01;
behavior: {
if(rd == 0) //rd==0 is a hint, so no trap
X[rd] = (unsigned<32>)(signed)imm;
}
}
'''.addInstructionContext.parse
validator.assertNoErrors(content)
val ref = '''
void CLI(){
{
if(rd == 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm);
}
}
'''
val fsa = new InMemoryFileSystemAccess()
generator.doGenerate(content.eResource, fsa, new GeneratorContext => [
cancelIndicator = CancelIndicator.NullImpl
])
val res = fsa.textFiles
res.forEach[name, text|
val jsonTokener = new JSONTokener(text.toString)
val json = new JSONObject(jsonTokener);
assertNotNull(json.get("instructions"))
assertTrue(json.get("instructions") instanceof JSONArray)
val instructions = json.get("instructions") as JSONArray
assertEquals(1, instructions.length)
]
}
}
@@ -0,0 +1,71 @@
/*
* generated by Xtext 2.22.0
*/
package com.minres.coredsl.json.tests;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.minres.coredsl.CoreDslRuntimeModule;
import com.minres.coredsl.CoreDslStandaloneSetup;
import com.minres.coredsl.json.CoreDslGeneratorModule;
import org.eclipse.xtext.testing.GlobalRegistries;
import org.eclipse.xtext.testing.GlobalRegistries.GlobalStateMemento;
import org.eclipse.xtext.testing.IInjectorProvider;
import org.eclipse.xtext.testing.IRegistryConfigurator;
public class CoreDslInjectorProvider implements IInjectorProvider, IRegistryConfigurator {
protected GlobalStateMemento stateBeforeInjectorCreation;
protected GlobalStateMemento stateAfterInjectorCreation;
protected Injector injector;
static {
GlobalRegistries.initializeDefaults();
}
@Override
public Injector getInjector() {
if (injector == null) {
this.injector = internalCreateInjector();
stateAfterInjectorCreation = GlobalRegistries.makeCopyOfGlobalState();
}
return injector;
}
protected Injector internalCreateInjector() {
return new CoreDslStandaloneSetup() {
@Override
public Injector createInjector() {
return Guice.createInjector(createRuntimeModule());
}
}.createInjectorAndDoEMFRegistration();
}
protected CoreDslRuntimeModule createRuntimeModule() {
// make it work also with Maven/Tycho and OSGI
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=493672
return new CoreDslGeneratorModule() {
@Override
public ClassLoader bindClassLoaderToInstance() {
return CoreDslInjectorProvider.class
.getClassLoader();
}
};
}
@Override
public void restoreRegistry() {
stateBeforeInjectorCreation.restoreGlobalState();
stateBeforeInjectorCreation = null;
}
@Override
public void setupRegistry() {
stateBeforeInjectorCreation = GlobalRegistries.makeCopyOfGlobalState();
if (injector == null) {
getInjector();
}
stateAfterInjectorCreation.restoreGlobalState();
}
}