mirror of
https://github.com/Minres/RDL-Editor.git
synced 2025-07-01 21:43:26 +02:00
Fixed code generation to use sc_register_indexed for register arrays
This commit is contained in:
@ -2,6 +2,9 @@ package com.minres.rdl.generator
|
||||
|
||||
import com.minres.rdl.generator.RdlBaseGenerator
|
||||
import com.minres.rdl.rdl.ComponentDefinition
|
||||
import com.minres.rdl.IntegerWithRadix
|
||||
import com.minres.rdl.rdl.Instantiation
|
||||
import com.minres.rdl.rdl.ComponentDefinitionType
|
||||
|
||||
class AddrmapGenerator extends RdlBaseGenerator {
|
||||
|
||||
@ -15,10 +18,12 @@ class AddrmapGenerator extends RdlBaseGenerator {
|
||||
#ifndef _E300_PLAT_MAP_H_
|
||||
#define _E300_PLAT_MAP_H_
|
||||
// need double braces, see https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191
|
||||
const std::array<sysc::target_memory_map_entry<32>, 3> e300_plat_map = {{
|
||||
{&i_gpio, 0x10012000, 0x1000},
|
||||
{&i_uart, 0x10013000, 0x1000},
|
||||
{&i_spi, 0x10014000, 0x1000}
|
||||
const std::array<sysc::target_memory_map_entry<32>, «componentDefinition.instanceCount(ComponentDefinitionType.REGFILE)»> e300_plat_map = {{
|
||||
«FOR instantiation : componentDefinition.instantiationsOfType(ComponentDefinitionType.REGFILE)»
|
||||
«FOR instance : instantiation.componentInstances»
|
||||
{&i_«instance.name», 0x«Long.toHexString((instance.address as IntegerWithRadix).value)», 0x«Long.toHexString(instantiation.occupiedSize)»},
|
||||
«ENDFOR»
|
||||
«ENDFOR»
|
||||
}};
|
||||
|
||||
#endif /* _E300_PLAT_MAP_H_ */
|
||||
@ -29,4 +34,16 @@ class AddrmapGenerator extends RdlBaseGenerator {
|
||||
''
|
||||
}
|
||||
|
||||
def int instanceCount(ComponentDefinition definition, ComponentDefinitionType type){
|
||||
definition.instantiationsOfType(type).map[it.componentInstances.size].reduce[p1, p2| p1+p2]
|
||||
}
|
||||
|
||||
def instantiationsOfType(ComponentDefinition definition, ComponentDefinitionType type){
|
||||
definition.instantiations.filter[it.definingComponent.type == type]
|
||||
}
|
||||
|
||||
def long occupiedSize(Instantiation instantiation){
|
||||
return 4096
|
||||
}
|
||||
|
||||
}
|
@ -19,104 +19,107 @@ import org.eclipse.xtext.validation.IResourceValidator
|
||||
import java.text.ParseException
|
||||
import com.minres.rdl.generator.Options.Multiplicity
|
||||
import com.minres.rdl.generator.Options.Separator
|
||||
import org.eclipse.xtext.generator.IFileSystemAccess
|
||||
|
||||
class Main {
|
||||
|
||||
private val USAGE_STR = "RDL2code [-h] [-v] [-I <RDL include dir] [-i <include output dir>] [-s <source output dir>] [-g <generated files output dir>] <input file> <input file>";
|
||||
private val USAGE_STR = "RDL2code [-h] [-v] [-I <RDL include dir] [-o <output dir>] <input file> <input file>";
|
||||
|
||||
def static main(String[] args) {
|
||||
if (args.empty) {
|
||||
System::err.println('Aborting: no path to RDL file provided!')
|
||||
return
|
||||
}
|
||||
val injector = new RDLStandaloneSetup().createInjectorAndDoEMFRegistration
|
||||
val main = injector.getInstance(Main)
|
||||
try {
|
||||
main.run(args)
|
||||
} catch (MalformedParametersException e) {
|
||||
print("Command line error " + e.message)
|
||||
System.exit(1)
|
||||
} catch (IllegalArgumentException e) {
|
||||
print("generation error " + e.message)
|
||||
e.printStackTrace
|
||||
System.exit(2)
|
||||
} catch (ParseException e) {
|
||||
print("parse problem " + e.message + " (" + e.errorOffset + ")")
|
||||
System.exit(3)
|
||||
}
|
||||
}
|
||||
def static main(String[] args) {
|
||||
if (args.empty) {
|
||||
System::err.println('Aborting: no path to RDL file provided!')
|
||||
return
|
||||
}
|
||||
val injector = new RDLStandaloneSetup().createInjectorAndDoEMFRegistration
|
||||
val main = injector.getInstance(Main)
|
||||
try {
|
||||
main.run(args)
|
||||
} catch (MalformedParametersException e) {
|
||||
print("Command line error " + e.message)
|
||||
System.exit(1)
|
||||
} catch (IllegalArgumentException e) {
|
||||
print("generation error " + e.message)
|
||||
e.printStackTrace
|
||||
System.exit(2)
|
||||
} catch (ParseException e) {
|
||||
print("parse problem " + e.message + " (" + e.errorOffset + ")")
|
||||
System.exit(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Inject Provider<ResourceSet> resourceSetProvider
|
||||
@Inject Provider<ResourceSet> resourceSetProvider
|
||||
|
||||
@Inject IResourceValidator validator
|
||||
@Inject IResourceValidator validator
|
||||
|
||||
@Inject GeneratorDelegate generator
|
||||
@Inject GeneratorDelegate generator
|
||||
|
||||
@Inject JavaIoFileSystemAccess fileAccess
|
||||
@Inject JavaIoFileSystemAccess fileAccess
|
||||
|
||||
def run(String[] args) {
|
||||
def run(String[] args) {
|
||||
|
||||
val opt = new Options(args, 0, Integer.MAX_VALUE);
|
||||
opt.getSet().addOption("h", Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("v", Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("i", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("s", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("g", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("I", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
if (!opt.check(false, false)) { // Print usage hints
|
||||
System.err.println("Usage is: " + USAGE_STR);
|
||||
throw new MalformedParametersException(opt.getCheckErrors());
|
||||
}
|
||||
// Normal processing
|
||||
if (opt.getSet().isSet("h")) {
|
||||
println("Usage: " + USAGE_STR);
|
||||
return
|
||||
}
|
||||
val verbose = if(opt.getSet().isSet("v")) true else false;
|
||||
val opt = new Options(args, 0, Integer.MAX_VALUE);
|
||||
opt.getSet().addOption("h", Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("v", Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("o", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
opt.getSet().addOption("I", Separator.BLANK, Multiplicity.ZERO_OR_ONE);
|
||||
if (!opt.check(false, false)) { // Print usage hints
|
||||
System.err.println("Usage is: " + USAGE_STR);
|
||||
throw new MalformedParametersException(opt.getCheckErrors());
|
||||
}
|
||||
// Normal processing
|
||||
if (opt.getSet().isSet("h")) {
|
||||
println("Usage: " + USAGE_STR);
|
||||
return
|
||||
}
|
||||
val verbose = if(opt.getSet().isSet("v")) true else false;
|
||||
|
||||
if (opt.getSet().isSet("I")) {
|
||||
val projectMapping = new ProjectMapping
|
||||
projectMapping.projectName = "RDL Repository"
|
||||
projectMapping.path = opt.getSet().getOption("I").getResultValue(0)
|
||||
new StandaloneSetup().addProjectMapping(projectMapping)
|
||||
}
|
||||
// Configure and start the generator
|
||||
fileAccess.outputPath = 'src-gen/'
|
||||
#{'incl-out' -> false, 'src-out' -> false, 'gen-out' -> true}.forEach[p1, p2|
|
||||
if(opt.getSet().isSet(p1.substring(0, 1)))
|
||||
fileAccess.setOutputPath(p1, opt.getSet().getOption(p1.substring(0, 1)).getResultValue(0)+'/')
|
||||
else
|
||||
fileAccess.setOutputPath(p1, 'src-gen/')
|
||||
fileAccess.outputConfigurations.get(p1)?.setOverrideExistingResources(p2)
|
||||
]
|
||||
opt.getSet().getData().forEach [ String string |
|
||||
if(verbose) println("Reading " + string);
|
||||
// Load the resource
|
||||
val resourceSet = resourceSetProvider.get as XtextResourceSet
|
||||
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
|
||||
val resource = resourceSet.getResource(URI.createFileURI(string), true)
|
||||
// Validate the resource
|
||||
val issues = validator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl)
|
||||
if (!issues.empty) {
|
||||
System.err.println("Error validating " + resource.URI)
|
||||
issues.forEach[System.err.println(it)]
|
||||
throw new ParseException("error validating " + resource.URI, issues.size)
|
||||
}
|
||||
if (opt.getSet().isSet("I")) {
|
||||
val projectMapping = new ProjectMapping
|
||||
projectMapping.projectName = "RDL Repository"
|
||||
projectMapping.path = opt.getSet().getOption("I").getResultValue(0)
|
||||
new StandaloneSetup().addProjectMapping(projectMapping)
|
||||
}
|
||||
// Configure and start the generator
|
||||
fileAccess.outputPath = 'src-gen/'
|
||||
if(opt.getSet().isSet('o')){
|
||||
fileAccess.outputPath = opt.getSet().getOption('o').getResultValue(0)
|
||||
fileAccess.outputConfigurations.get(IFileSystemAccess.DEFAULT_OUTPUT)?.setOverrideExistingResources(true)
|
||||
}
|
||||
// #{'incl-out' -> false, 'src-out' -> false, 'gen-out' -> true}.forEach[p1, p2|
|
||||
// if(opt.getSet().isSet(p1.substring(0, 1)))
|
||||
// fileAccess.setOutputPath(p1, opt.getSet().getOption(p1.substring(0, 1)).getResultValue(0)+'/')
|
||||
// else
|
||||
// fileAccess.setOutputPath(p1, 'src-gen/')
|
||||
// fileAccess.outputConfigurations.get(p1)?.setOverrideExistingResources(p2)
|
||||
// ]
|
||||
opt.getSet().getData().forEach [ String string |
|
||||
if(verbose) println("Processing " + string);
|
||||
// Load the resource
|
||||
val resourceSet = resourceSetProvider.get as XtextResourceSet
|
||||
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
|
||||
val resource = resourceSet.getResource(URI.createFileURI(string), true)
|
||||
// Validate the resource
|
||||
val issues = validator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl)
|
||||
if (!issues.empty) {
|
||||
System.err.println("Error validating " + resource.URI)
|
||||
issues.forEach[System.err.println(it)]
|
||||
throw new ParseException("error validating " + resource.URI, issues.size)
|
||||
}
|
||||
|
||||
val context = new GeneratorContext => [cancelIndicator = CancelIndicator.NullImpl]
|
||||
generator.generate(resource, fileAccess, context)
|
||||
val context = new GeneratorContext => [cancelIndicator = CancelIndicator.NullImpl]
|
||||
generator.generate(resource, fileAccess, context)
|
||||
|
||||
if(verbose) print('Code generation for ' + string + ' finished, ')
|
||||
try {
|
||||
if(verbose) print('includes are in ' + fileAccess.getURI('', 'incl-out') + ', ')
|
||||
} catch (Exception e) {
|
||||
print('includes are in ' + fileAccess.getURI('') + ', ')
|
||||
}
|
||||
try {
|
||||
if(verbose) println('sources are in ' + fileAccess.getURI('', 'src-out') + ', ')
|
||||
} catch (Exception e) {
|
||||
println('sources are in ' + fileAccess.getURI('') + ', ')
|
||||
}
|
||||
]
|
||||
}
|
||||
if(verbose) println('Code generation for ' + string + ' finished')
|
||||
try {
|
||||
if(verbose) println('includes are in ' + fileAccess.getURI('', 'incl-out'))
|
||||
} catch (Exception e) {
|
||||
println('includes are in ' + fileAccess.getURI(''))
|
||||
}
|
||||
try {
|
||||
if(verbose) println('sources are in ' + fileAccess.getURI('', 'src-out'))
|
||||
} catch (Exception e) {
|
||||
println('sources are in ' + fileAccess.getURI(''))
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.minres.rdl.rdl.ComponentDefinitionType
|
||||
import com.minres.rdl.rdl.ComponentInstance
|
||||
import com.minres.rdl.rdl.Instantiation
|
||||
import java.util.Date
|
||||
import com.minres.rdl.rdl.Range
|
||||
|
||||
class RegfileGenerator extends RdlBaseGenerator{
|
||||
|
||||
@ -80,12 +81,18 @@ class RegfileGenerator extends RdlBaseGenerator{
|
||||
«ENDIF»
|
||||
«IF instantiation.component !== null && instantiation.component.type == ComponentDefinitionType.REG»
|
||||
«IF instantiation.isFilledByField»
|
||||
uint«instantiation.size»_t «instantiation.componentInstances.map['r_'+it.name].join(', ')»;
|
||||
uint«instantiation.size»_t «instantiation.componentInstances.filter[it.range===null].map['r_'+it.name].join(', ')»;
|
||||
«FOR componentInstance : instantiation.componentInstances.filter[it.range!==null]»
|
||||
std::array<uint«instantiation.size»_t, «componentInstance.range.absSize»> r_«componentInstance.name»;
|
||||
«ENDFOR»
|
||||
«ENDIF»
|
||||
«IF !instantiation.isFilledByField»
|
||||
BEGIN_BF_DECL(«instantiation.component.effectiveName»_t, uint«instantiation.size»_t);
|
||||
«instantiation.definingComponent.genFieldDeclarations»
|
||||
END_BF_DECL() «instantiation.componentInstances.map['r_'+it.name].join(', ')»;
|
||||
END_BF_DECL() «instantiation.componentInstances.filter[it.range===null].map['r_'+it.name].join(', ')»;
|
||||
«FOR componentInstance : instantiation.componentInstances.filter[it.range!==null]»
|
||||
std::array<«instantiation.component.effectiveName»_t, «componentInstance.range.absSize»> r_«componentInstance.name»;
|
||||
«ENDFOR»
|
||||
«ENDIF»
|
||||
|
||||
«ENDIF»
|
||||
@ -93,11 +100,21 @@ class RegfileGenerator extends RdlBaseGenerator{
|
||||
// register declarations
|
||||
«FOR instantiation : componentDefinition.instantiations»
|
||||
«FOR instance : instantiation.componentInstances»
|
||||
«IF instantiation.isFilledByField»
|
||||
sysc::sc_register<uint«instantiation.size»_t> «instance.name»;
|
||||
«IF instance.range===null»
|
||||
«IF instantiation.isFilledByField»
|
||||
sysc::sc_register<uint«instantiation.size»_t> «instance.name»;
|
||||
«ENDIF»
|
||||
«IF !instantiation.isFilledByField»
|
||||
sysc::sc_register<«instantiation.component.effectiveName»_t> «instance.name»;
|
||||
«ENDIF»
|
||||
«ENDIF»
|
||||
«IF !instantiation.isFilledByField»
|
||||
sysc::sc_register<typename «instantiation.component.effectiveName»_t::StorageType> «instance.name»;
|
||||
«IF instance.range!==null»
|
||||
«IF instantiation.isFilledByField»
|
||||
sysc::sc_register_indexed<«instantiation.size»_t, «instance.range.absSize»> «instance.name»;
|
||||
«ENDIF»
|
||||
«IF !instantiation.isFilledByField»
|
||||
sysc::sc_register_indexed<«instantiation.component.effectiveName»_t, «instance.range.absSize»> «instance.name»;
|
||||
«ENDIF»
|
||||
«ENDIF»
|
||||
«ENDFOR»
|
||||
«ENDFOR»
|
||||
@ -127,7 +144,7 @@ class RegfileGenerator extends RdlBaseGenerator{
|
||||
inline void sysc::«componentDefinition.name»::registerResources(sysc::tlm_target<BUSWIDTH>& target) {
|
||||
«FOR instantiation : componentDefinition.instantiations»
|
||||
«FOR instance : instantiation.componentInstances»
|
||||
target.addResource(«instance.name», 0x«Long.toHexString((instance.address as IntegerWithRadix).value)»UL, 0x«Long.toHexString((instantiation.size+7)/8)»UL);
|
||||
target.addResource(«instance.name», 0x«Long.toHexString((instance.address as IntegerWithRadix).value)»UL);
|
||||
«ENDFOR»
|
||||
«ENDFOR»
|
||||
}
|
||||
@ -135,6 +152,13 @@ class RegfileGenerator extends RdlBaseGenerator{
|
||||
#endif // _«componentDefinition.name.toUpperCase»_H_
|
||||
'''
|
||||
|
||||
def long absSize(Range range){
|
||||
if(range.size!==null)
|
||||
return (range.size as IntegerWithRadix).value
|
||||
else
|
||||
return Math.abs((range.left as IntegerWithRadix).value - (range.right as IntegerWithRadix).value)+1
|
||||
}
|
||||
|
||||
def boolean isFilledByField(Instantiation instantiation){
|
||||
val fieldCount = instantiation.component.instanceCountOfType(ComponentDefinitionType.FIELD)
|
||||
if(fieldCount==1) {
|
||||
|
Reference in New Issue
Block a user