Better handling of sub-clusters in SVD (#3335)
gen: Better handling of sub-clusters in SVD
Этот коммит содержится в:
родитель
e21ab04fad
коммит
361ecf9ea4
1 изменённых файлов: 161 добавлений и 139 удалений
|
@ -90,9 +90,10 @@ type SVDCluster struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
Metadata *Metadata
|
Metadata *Metadata
|
||||||
Interrupts []*Interrupt
|
Interrupts []*Interrupt
|
||||||
Peripherals []*Peripheral
|
Peripherals []*Peripheral
|
||||||
|
PeripheralDict map[string]*Peripheral
|
||||||
}
|
}
|
||||||
|
|
||||||
type Metadata struct {
|
type Metadata struct {
|
||||||
|
@ -191,6 +192,142 @@ func cleanName(text string) string {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processSubCluster(p *Peripheral, cluster *SVDCluster, clusterOffset uint64, clusterName string, peripheralDict map[string]*Peripheral) []*Peripheral {
|
||||||
|
var peripheralsList []*Peripheral
|
||||||
|
clusterPrefix := clusterName + "_"
|
||||||
|
cpRegisters := []*PeripheralField{}
|
||||||
|
|
||||||
|
for _, regEl := range cluster.Registers {
|
||||||
|
cpRegisters = append(cpRegisters, parseRegister(p.GroupName, regEl, p.BaseAddress+clusterOffset, clusterPrefix)...)
|
||||||
|
}
|
||||||
|
// handle sub-clusters of registers
|
||||||
|
for _, subClusterEl := range cluster.Clusters {
|
||||||
|
subclusterName := strings.ReplaceAll(subClusterEl.Name, "[%s]", "")
|
||||||
|
subclusterPrefix := subclusterName + "_"
|
||||||
|
subclusterOffset, err := strconv.ParseUint(subClusterEl.AddressOffset, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
subdim := *subClusterEl.Dim
|
||||||
|
subdimIncrement, err := strconv.ParseInt(subClusterEl.DimIncrement, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if subdim > 1 {
|
||||||
|
subcpRegisters := []*PeripheralField{}
|
||||||
|
for _, regEl := range subClusterEl.Registers {
|
||||||
|
subcpRegisters = append(subcpRegisters, parseRegister(p.GroupName, regEl, p.BaseAddress+clusterOffset+subclusterOffset, subclusterPrefix)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
cpRegisters = append(cpRegisters, &PeripheralField{
|
||||||
|
Name: subclusterName,
|
||||||
|
Address: p.BaseAddress + clusterOffset + subclusterOffset,
|
||||||
|
Description: subClusterEl.Description,
|
||||||
|
Registers: subcpRegisters,
|
||||||
|
Array: subdim,
|
||||||
|
ElementSize: int(subdimIncrement),
|
||||||
|
ShortName: clusterPrefix + subclusterName,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for _, regEl := range subClusterEl.Registers {
|
||||||
|
cpRegisters = append(cpRegisters, parseRegister(regEl.Name, regEl, p.BaseAddress+clusterOffset+subclusterOffset, subclusterPrefix)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(cpRegisters, func(i, j int) bool {
|
||||||
|
return cpRegisters[i].Address < cpRegisters[j].Address
|
||||||
|
})
|
||||||
|
clusterPeripheral := &Peripheral{
|
||||||
|
Name: p.Name + "_" + clusterName,
|
||||||
|
GroupName: p.GroupName + "_" + clusterName,
|
||||||
|
Description: p.Description + " - " + clusterName,
|
||||||
|
ClusterName: clusterName,
|
||||||
|
BaseAddress: p.BaseAddress + clusterOffset,
|
||||||
|
Registers: cpRegisters,
|
||||||
|
}
|
||||||
|
peripheralsList = append(peripheralsList, clusterPeripheral)
|
||||||
|
peripheralDict[clusterPeripheral.Name] = clusterPeripheral
|
||||||
|
p.Subtypes = append(p.Subtypes, clusterPeripheral)
|
||||||
|
|
||||||
|
return peripheralsList
|
||||||
|
}
|
||||||
|
|
||||||
|
func processCluster(p *Peripheral, clusters []*SVDCluster, peripheralDict map[string]*Peripheral) []*Peripheral {
|
||||||
|
var peripheralsList []*Peripheral
|
||||||
|
for _, cluster := range clusters {
|
||||||
|
clusterName := strings.ReplaceAll(cluster.Name, "[%s]", "")
|
||||||
|
if cluster.DimIndex != nil {
|
||||||
|
clusterName = strings.ReplaceAll(clusterName, "%s", "")
|
||||||
|
}
|
||||||
|
clusterPrefix := clusterName + "_"
|
||||||
|
clusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
var dim, dimIncrement int
|
||||||
|
if cluster.Dim == nil {
|
||||||
|
// Nordic SVD have sub-clusters with another sub-clusters.
|
||||||
|
if clusterOffset == 0 || len(cluster.Clusters) > 0 {
|
||||||
|
peripheralsList = append(peripheralsList, processSubCluster(p, cluster, clusterOffset, clusterName, peripheralDict)...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dim = -1
|
||||||
|
dimIncrement = -1
|
||||||
|
} else {
|
||||||
|
dim = *cluster.Dim
|
||||||
|
if dim == 1 {
|
||||||
|
dimIncrement = -1
|
||||||
|
} else {
|
||||||
|
inc, err := strconv.ParseUint(cluster.DimIncrement, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dimIncrement = int(inc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clusterRegisters := []*PeripheralField{}
|
||||||
|
for _, regEl := range cluster.Registers {
|
||||||
|
regName := p.GroupName
|
||||||
|
if regName == "" {
|
||||||
|
regName = p.Name
|
||||||
|
}
|
||||||
|
clusterRegisters = append(clusterRegisters, parseRegister(regName, regEl, p.BaseAddress+clusterOffset, clusterPrefix)...)
|
||||||
|
}
|
||||||
|
sort.SliceStable(clusterRegisters, func(i, j int) bool {
|
||||||
|
return clusterRegisters[i].Address < clusterRegisters[j].Address
|
||||||
|
})
|
||||||
|
if dimIncrement == -1 && len(clusterRegisters) > 0 {
|
||||||
|
lastReg := clusterRegisters[len(clusterRegisters)-1]
|
||||||
|
lastAddress := lastReg.Address
|
||||||
|
if lastReg.Array != -1 {
|
||||||
|
lastAddress = lastReg.Address + uint64(lastReg.Array*lastReg.ElementSize)
|
||||||
|
}
|
||||||
|
firstAddress := clusterRegisters[0].Address
|
||||||
|
dimIncrement = int(lastAddress - firstAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !unicode.IsUpper(rune(clusterName[0])) && !unicode.IsDigit(rune(clusterName[0])) {
|
||||||
|
clusterName = strings.ToUpper(clusterName)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Registers = append(p.Registers, &PeripheralField{
|
||||||
|
Name: clusterName,
|
||||||
|
Address: p.BaseAddress + clusterOffset,
|
||||||
|
Description: cluster.Description,
|
||||||
|
Registers: clusterRegisters,
|
||||||
|
Array: dim,
|
||||||
|
ElementSize: dimIncrement,
|
||||||
|
ShortName: clusterName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.SliceStable(p.Registers, func(i, j int) bool {
|
||||||
|
return p.Registers[i].Address < p.Registers[j].Address
|
||||||
|
})
|
||||||
|
return peripheralsList
|
||||||
|
}
|
||||||
|
|
||||||
// Read ARM SVD files.
|
// Read ARM SVD files.
|
||||||
func readSVD(path, sourceURL string) (*Device, error) {
|
func readSVD(path, sourceURL string) (*Device, error) {
|
||||||
// Open the XML file.
|
// Open the XML file.
|
||||||
|
@ -293,133 +430,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
||||||
}
|
}
|
||||||
p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
|
p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
|
||||||
}
|
}
|
||||||
for _, cluster := range periphEl.Clusters {
|
peripheralsList = append(peripheralsList, processCluster(p, periphEl.Clusters, peripheralDict)...)
|
||||||
clusterName := strings.ReplaceAll(cluster.Name, "[%s]", "")
|
|
||||||
if cluster.DimIndex != nil {
|
|
||||||
clusterName = strings.ReplaceAll(clusterName, "%s", "")
|
|
||||||
}
|
|
||||||
clusterPrefix := clusterName + "_"
|
|
||||||
clusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
var dim, dimIncrement int
|
|
||||||
if cluster.Dim == nil {
|
|
||||||
if clusterOffset == 0 {
|
|
||||||
// make this a separate peripheral
|
|
||||||
cpRegisters := []*PeripheralField{}
|
|
||||||
for _, regEl := range cluster.Registers {
|
|
||||||
cpRegisters = append(cpRegisters, parseRegister(groupName, regEl, baseAddress, clusterName+"_")...)
|
|
||||||
}
|
|
||||||
// handle sub-clusters of registers
|
|
||||||
for _, subClusterEl := range cluster.Clusters {
|
|
||||||
subclusterName := strings.ReplaceAll(subClusterEl.Name, "[%s]", "")
|
|
||||||
subclusterPrefix := subclusterName + "_"
|
|
||||||
subclusterOffset, err := strconv.ParseUint(subClusterEl.AddressOffset, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
subdim := *subClusterEl.Dim
|
|
||||||
subdimIncrement, err := strconv.ParseInt(subClusterEl.DimIncrement, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subdim > 1 {
|
|
||||||
subcpRegisters := []*PeripheralField{}
|
|
||||||
subregSize := 0
|
|
||||||
for _, regEl := range subClusterEl.Registers {
|
|
||||||
size, err := strconv.ParseInt(*regEl.Size, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
subregSize += int(size)
|
|
||||||
subcpRegisters = append(subcpRegisters, parseRegister(groupName, regEl, baseAddress+subclusterOffset, subclusterPrefix)...)
|
|
||||||
}
|
|
||||||
cpRegisters = append(cpRegisters, &PeripheralField{
|
|
||||||
Name: subclusterName,
|
|
||||||
Address: baseAddress + subclusterOffset,
|
|
||||||
Description: subClusterEl.Description,
|
|
||||||
Registers: subcpRegisters,
|
|
||||||
Array: subdim,
|
|
||||||
ElementSize: int(subdimIncrement),
|
|
||||||
ShortName: clusterPrefix + subclusterName,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
for _, regEl := range subClusterEl.Registers {
|
|
||||||
cpRegisters = append(cpRegisters, parseRegister(regEl.Name, regEl, baseAddress+subclusterOffset, subclusterPrefix)...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.SliceStable(cpRegisters, func(i, j int) bool {
|
|
||||||
return cpRegisters[i].Address < cpRegisters[j].Address
|
|
||||||
})
|
|
||||||
clusterPeripheral := &Peripheral{
|
|
||||||
Name: periphEl.Name + "_" + clusterName,
|
|
||||||
GroupName: groupName + "_" + clusterName,
|
|
||||||
Description: description + " - " + clusterName,
|
|
||||||
ClusterName: clusterName,
|
|
||||||
BaseAddress: baseAddress,
|
|
||||||
Registers: cpRegisters,
|
|
||||||
}
|
|
||||||
peripheralsList = append(peripheralsList, clusterPeripheral)
|
|
||||||
peripheralDict[clusterPeripheral.Name] = clusterPeripheral
|
|
||||||
p.Subtypes = append(p.Subtypes, clusterPeripheral)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dim = -1
|
|
||||||
dimIncrement = -1
|
|
||||||
} else {
|
|
||||||
dim = *cluster.Dim
|
|
||||||
if dim == 1 {
|
|
||||||
dimIncrement = -1
|
|
||||||
} else {
|
|
||||||
inc, err := strconv.ParseUint(cluster.DimIncrement, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
dimIncrement = int(inc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clusterRegisters := []*PeripheralField{}
|
|
||||||
for _, regEl := range cluster.Registers {
|
|
||||||
regName := groupName
|
|
||||||
if regName == "" {
|
|
||||||
regName = periphEl.Name
|
|
||||||
}
|
|
||||||
clusterRegisters = append(clusterRegisters, parseRegister(regName, regEl, baseAddress+clusterOffset, clusterPrefix)...)
|
|
||||||
}
|
|
||||||
sort.SliceStable(clusterRegisters, func(i, j int) bool {
|
|
||||||
return clusterRegisters[i].Address < clusterRegisters[j].Address
|
|
||||||
})
|
|
||||||
if dimIncrement == -1 && len(clusterRegisters) > 0 {
|
|
||||||
lastReg := clusterRegisters[len(clusterRegisters)-1]
|
|
||||||
lastAddress := lastReg.Address
|
|
||||||
if lastReg.Array != -1 {
|
|
||||||
lastAddress = lastReg.Address + uint64(lastReg.Array*lastReg.ElementSize)
|
|
||||||
}
|
|
||||||
firstAddress := clusterRegisters[0].Address
|
|
||||||
dimIncrement = int(lastAddress - firstAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !unicode.IsUpper(rune(clusterName[0])) && !unicode.IsDigit(rune(clusterName[0])) {
|
|
||||||
clusterName = strings.ToUpper(clusterName)
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Registers = append(p.Registers, &PeripheralField{
|
|
||||||
Name: clusterName,
|
|
||||||
Address: baseAddress + clusterOffset,
|
|
||||||
Description: cluster.Description,
|
|
||||||
Registers: clusterRegisters,
|
|
||||||
Array: dim,
|
|
||||||
ElementSize: dimIncrement,
|
|
||||||
ShortName: clusterName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.SliceStable(p.Registers, func(i, j int) bool {
|
|
||||||
return p.Registers[i].Address < p.Registers[j].Address
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a sorted list of interrupts.
|
// Make a sorted list of interrupts.
|
||||||
|
@ -459,9 +470,10 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
||||||
metadata.NVICPrioBits = device.CPU.NVICPrioBits
|
metadata.NVICPrioBits = device.CPU.NVICPrioBits
|
||||||
}
|
}
|
||||||
return &Device{
|
return &Device{
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
Interrupts: interruptList,
|
Interrupts: interruptList,
|
||||||
Peripherals: peripheralsList,
|
Peripherals: peripheralsList,
|
||||||
|
PeripheralDict: peripheralDict,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,10 +991,11 @@ var (
|
||||||
|
|
||||||
address := peripheral.BaseAddress
|
address := peripheral.BaseAddress
|
||||||
type clusterInfo struct {
|
type clusterInfo struct {
|
||||||
name string
|
name string
|
||||||
address uint64
|
description string
|
||||||
size uint64
|
address uint64
|
||||||
registers []*PeripheralField
|
size uint64
|
||||||
|
registers []*PeripheralField
|
||||||
}
|
}
|
||||||
clusters := []clusterInfo{}
|
clusters := []clusterInfo{}
|
||||||
for _, register := range peripheral.Registers {
|
for _, register := range peripheral.Registers {
|
||||||
|
@ -1024,7 +1037,7 @@ var (
|
||||||
if register.Registers != nil {
|
if register.Registers != nil {
|
||||||
// This is a cluster, not a register. Create the cluster type.
|
// This is a cluster, not a register. Create the cluster type.
|
||||||
regType = peripheral.GroupName + "_" + register.Name
|
regType = peripheral.GroupName + "_" + register.Name
|
||||||
clusters = append(clusters, clusterInfo{regType, register.Address, uint64(register.ElementSize), register.Registers})
|
clusters = append(clusters, clusterInfo{regType, register.Description, register.Address, uint64(register.ElementSize), register.Registers})
|
||||||
regType = regType + "_Type"
|
regType = regType + "_Type"
|
||||||
subaddress := register.Address
|
subaddress := register.Address
|
||||||
for _, subregister := range register.Registers {
|
for _, subregister := range register.Registers {
|
||||||
|
@ -1075,7 +1088,16 @@ var (
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := device.PeripheralDict[cluster.name]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintln(w)
|
fmt.Fprintln(w)
|
||||||
|
if cluster.description != "" {
|
||||||
|
for _, l := range splitLine(cluster.description) {
|
||||||
|
fmt.Fprintf(w, "// %s\n", l)
|
||||||
|
}
|
||||||
|
}
|
||||||
fmt.Fprintf(w, "type %s_Type struct {\n", cluster.name)
|
fmt.Fprintf(w, "type %s_Type struct {\n", cluster.name)
|
||||||
|
|
||||||
address := cluster.address
|
address := cluster.address
|
||||||
|
@ -1116,7 +1138,7 @@ var (
|
||||||
if register.Registers != nil {
|
if register.Registers != nil {
|
||||||
// This is a cluster, not a register. Create the cluster type.
|
// This is a cluster, not a register. Create the cluster type.
|
||||||
regType = peripheral.GroupName + "_" + register.Name
|
regType = peripheral.GroupName + "_" + register.Name
|
||||||
clusters = append(clusters, clusterInfo{regType, register.Address, uint64(register.ElementSize), register.Registers})
|
clusters = append(clusters, clusterInfo{regType, register.Description, register.Address, uint64(register.ElementSize), register.Registers})
|
||||||
regType = regType + "_Type"
|
regType = regType + "_Type"
|
||||||
|
|
||||||
subaddress := register.Address
|
subaddress := register.Address
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче