aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorAnton D. Kachalov <[email protected]>2023-02-18 09:10:23 +0100
committerGitHub <[email protected]>2023-02-18 09:10:23 +0100
commit361ecf9ea452b8787f9b68689216bb26227bd64a (patch)
tree09be3a27d75f450e170e465688f814c19046614f /tools
parente21ab04fad5e273b8f4c933f3e96133b90797314 (diff)
downloadtinygo-361ecf9ea452b8787f9b68689216bb26227bd64a.tar.gz
tinygo-361ecf9ea452b8787f9b68689216bb26227bd64a.zip
Better handling of sub-clusters in SVD (#3335)
gen: Better handling of sub-clusters in SVD
Diffstat (limited to 'tools')
-rwxr-xr-xtools/gen-device-svd/gen-device-svd.go300
1 files changed, 161 insertions, 139 deletions
diff --git a/tools/gen-device-svd/gen-device-svd.go b/tools/gen-device-svd/gen-device-svd.go
index ce1f7ed13..087a66226 100755
--- a/tools/gen-device-svd/gen-device-svd.go
+++ b/tools/gen-device-svd/gen-device-svd.go
@@ -90,9 +90,10 @@ type SVDCluster struct {
}
type Device struct {
- Metadata *Metadata
- Interrupts []*Interrupt
- Peripherals []*Peripheral
+ Metadata *Metadata
+ Interrupts []*Interrupt
+ Peripherals []*Peripheral
+ PeripheralDict map[string]*Peripheral
}
type Metadata struct {
@@ -191,6 +192,142 @@ func cleanName(text string) string {
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.
func readSVD(path, sourceURL string) (*Device, error) {
// Open the XML file.
@@ -293,133 +430,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
}
p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
}
- for _, cluster := range periphEl.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 {
- 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
- })
+ peripheralsList = append(peripheralsList, processCluster(p, periphEl.Clusters, peripheralDict)...)
}
// Make a sorted list of interrupts.
@@ -459,9 +470,10 @@ func readSVD(path, sourceURL string) (*Device, error) {
metadata.NVICPrioBits = device.CPU.NVICPrioBits
}
return &Device{
- Metadata: metadata,
- Interrupts: interruptList,
- Peripherals: peripheralsList,
+ Metadata: metadata,
+ Interrupts: interruptList,
+ Peripherals: peripheralsList,
+ PeripheralDict: peripheralDict,
}, nil
}
@@ -979,10 +991,11 @@ var (
address := peripheral.BaseAddress
type clusterInfo struct {
- name string
- address uint64
- size uint64
- registers []*PeripheralField
+ name string
+ description string
+ address uint64
+ size uint64
+ registers []*PeripheralField
}
clusters := []clusterInfo{}
for _, register := range peripheral.Registers {
@@ -1024,7 +1037,7 @@ var (
if register.Registers != nil {
// This is a cluster, not a register. Create the cluster type.
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"
subaddress := register.Address
for _, subregister := range register.Registers {
@@ -1075,7 +1088,16 @@ var (
continue
}
+ if _, ok := device.PeripheralDict[cluster.name]; ok {
+ continue
+ }
+
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)
address := cluster.address
@@ -1116,7 +1138,7 @@ var (
if register.Registers != nil {
// This is a cluster, not a register. Create the cluster type.
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"
subaddress := register.Address