Move element description formatting to a function

Export struct fields for use in the template

Add template helper functions

Multiline comments for interrupts and peripherals

Export more fields

Move comments to the top of each element

Do not remove line breaks from descriptions

The template code should gracefully handle line breaks now

go fmt gen-device-svd.go
Этот коммит содержится в:
Andre Sencioles 2021-01-30 23:53:35 +13:00 коммит произвёл Ron Evans
родитель e161d5a82c
коммит cca0eab3da

Просмотреть файл

@ -83,45 +83,54 @@ type SVDCluster struct {
} }
type Device struct { type Device struct {
metadata map[string]string Metadata *Metadata
interrupts []*interrupt Interrupts []*Interrupt
peripherals []*peripheral Peripherals []*Peripheral
} }
type interrupt struct { type Metadata struct {
File string
DescriptorSource string
Name string
NameLower string
Description string
LicenseBlock string
}
type Interrupt struct {
Name string Name string
HandlerName string HandlerName string
peripheralIndex int PeripheralIndex int
Value int // interrupt number Value int // interrupt number
Description string Description string
} }
type peripheral struct { type Peripheral struct {
Name string Name string
GroupName string GroupName string
BaseAddress uint64 BaseAddress uint64
Description string Description string
ClusterName string ClusterName string
registers []*PeripheralField Registers []*PeripheralField
subtypes []*peripheral Subtypes []*Peripheral
} }
// A PeripheralField is a single field in a peripheral type. It may be a full // A PeripheralField is a single field in a peripheral type. It may be a full
// peripheral or a cluster within a peripheral. // peripheral or a cluster within a peripheral.
type PeripheralField struct { type PeripheralField struct {
name string Name string
address uint64 Address uint64
description string Description string
registers []*PeripheralField // contains fields if this is a cluster Registers []*PeripheralField // contains fields if this is a cluster
array int Array int
elementSize int ElementSize int
bitfields []Bitfield Bitfields []Bitfield
} }
type Bitfield struct { type Bitfield struct {
name string Name string
description string Description string
value uint32 Value uint32
} }
func formatText(text string) string { func formatText(text string) string {
@ -131,6 +140,14 @@ func formatText(text string) string {
return text return text
} }
func isMultiline(s string) bool {
return strings.Index(s, "\n") >= 0
}
func splitLine(s string) []string {
return strings.Split(s, "\n")
}
// Replace characters that are not allowed in a symbol name with a '_'. This is // Replace characters that are not allowed in a symbol name with a '_'. This is
// useful to be able to process SVD files with errors. // useful to be able to process SVD files with errors.
func cleanName(text string) string { func cleanName(text string) string {
@ -168,11 +185,11 @@ func readSVD(path, sourceURL string) (*Device, error) {
return nil, err return nil, err
} }
peripheralDict := map[string]*peripheral{} peripheralDict := map[string]*Peripheral{}
groups := map[string]*peripheral{} groups := map[string]*Peripheral{}
interrupts := make(map[string]*interrupt) interrupts := make(map[string]*Interrupt)
var peripheralsList []*peripheral var peripheralsList []*Peripheral
// Some SVD files have peripheral elements derived from a peripheral that // Some SVD files have peripheral elements derived from a peripheral that
// comes later in the file. To make sure this works, sort the peripherals if // comes later in the file. To make sure this works, sort the peripherals if
@ -203,13 +220,13 @@ func readSVD(path, sourceURL string) (*Device, error) {
} }
if _, ok := groups[groupName]; ok || periphEl.DerivedFrom != "" { if _, ok := groups[groupName]; ok || periphEl.DerivedFrom != "" {
var derivedFrom *peripheral var derivedFrom *Peripheral
if periphEl.DerivedFrom != "" { if periphEl.DerivedFrom != "" {
derivedFrom = peripheralDict[periphEl.DerivedFrom] derivedFrom = peripheralDict[periphEl.DerivedFrom]
} else { } else {
derivedFrom = groups[groupName] derivedFrom = groups[groupName]
} }
p := &peripheral{ p := &Peripheral{
Name: periphEl.Name, Name: periphEl.Name,
GroupName: derivedFrom.GroupName, GroupName: derivedFrom.GroupName,
Description: description, Description: description,
@ -220,8 +237,8 @@ func readSVD(path, sourceURL string) (*Device, error) {
} }
peripheralsList = append(peripheralsList, p) peripheralsList = append(peripheralsList, p)
peripheralDict[p.Name] = p peripheralDict[p.Name] = p
for _, subtype := range derivedFrom.subtypes { for _, subtype := range derivedFrom.Subtypes {
peripheralsList = append(peripheralsList, &peripheral{ peripheralsList = append(peripheralsList, &Peripheral{
Name: periphEl.Name + "_" + subtype.ClusterName, Name: periphEl.Name + "_" + subtype.ClusterName,
GroupName: subtype.GroupName, GroupName: subtype.GroupName,
Description: subtype.Description, Description: subtype.Description,
@ -231,12 +248,12 @@ func readSVD(path, sourceURL string) (*Device, error) {
continue continue
} }
p := &peripheral{ p := &Peripheral{
Name: periphEl.Name, Name: periphEl.Name,
GroupName: groupName, GroupName: groupName,
Description: description, Description: description,
BaseAddress: baseAddress, BaseAddress: baseAddress,
registers: []*PeripheralField{}, Registers: []*PeripheralField{},
} }
if p.GroupName == "" { if p.GroupName == "" {
p.GroupName = periphEl.Name p.GroupName = periphEl.Name
@ -253,7 +270,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
if regName == "" { if regName == "" {
regName = periphEl.Name // fall back to peripheral name regName = periphEl.Name // fall back to peripheral name
} }
p.registers = append(p.registers, parseRegister(regName, register, baseAddress, "")...) p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
} }
for _, cluster := range periphEl.Clusters { for _, cluster := range periphEl.Clusters {
clusterName := strings.Replace(cluster.Name, "[%s]", "", -1) clusterName := strings.Replace(cluster.Name, "[%s]", "", -1)
@ -299,12 +316,12 @@ func readSVD(path, sourceURL string) (*Device, error) {
subcpRegisters = append(subcpRegisters, parseRegister(groupName, regEl, baseAddress+subclusterOffset, subclusterPrefix)...) subcpRegisters = append(subcpRegisters, parseRegister(groupName, regEl, baseAddress+subclusterOffset, subclusterPrefix)...)
} }
cpRegisters = append(cpRegisters, &PeripheralField{ cpRegisters = append(cpRegisters, &PeripheralField{
name: subclusterName, Name: subclusterName,
address: baseAddress + subclusterOffset, Address: baseAddress + subclusterOffset,
description: subClusterEl.Description, Description: subClusterEl.Description,
registers: subcpRegisters, Registers: subcpRegisters,
array: subdim, Array: subdim,
elementSize: int(subdimIncrement), ElementSize: int(subdimIncrement),
}) })
} else { } else {
for _, regEl := range subClusterEl.Registers { for _, regEl := range subClusterEl.Registers {
@ -314,19 +331,19 @@ func readSVD(path, sourceURL string) (*Device, error) {
} }
sort.SliceStable(cpRegisters, func(i, j int) bool { sort.SliceStable(cpRegisters, func(i, j int) bool {
return cpRegisters[i].address < cpRegisters[j].address return cpRegisters[i].Address < cpRegisters[j].Address
}) })
clusterPeripheral := &peripheral{ clusterPeripheral := &Peripheral{
Name: periphEl.Name + "_" + clusterName, Name: periphEl.Name + "_" + clusterName,
GroupName: groupName + "_" + clusterName, GroupName: groupName + "_" + clusterName,
Description: description + " - " + clusterName, Description: description + " - " + clusterName,
ClusterName: clusterName, ClusterName: clusterName,
BaseAddress: baseAddress, BaseAddress: baseAddress,
registers: cpRegisters, Registers: cpRegisters,
} }
peripheralsList = append(peripheralsList, clusterPeripheral) peripheralsList = append(peripheralsList, clusterPeripheral)
peripheralDict[clusterPeripheral.Name] = clusterPeripheral peripheralDict[clusterPeripheral.Name] = clusterPeripheral
p.subtypes = append(p.subtypes, clusterPeripheral) p.Subtypes = append(p.Subtypes, clusterPeripheral)
continue continue
} }
dim = -1 dim = -1
@ -352,15 +369,15 @@ func readSVD(path, sourceURL string) (*Device, error) {
clusterRegisters = append(clusterRegisters, parseRegister(regName, regEl, baseAddress+clusterOffset, clusterPrefix)...) clusterRegisters = append(clusterRegisters, parseRegister(regName, regEl, baseAddress+clusterOffset, clusterPrefix)...)
} }
sort.SliceStable(clusterRegisters, func(i, j int) bool { sort.SliceStable(clusterRegisters, func(i, j int) bool {
return clusterRegisters[i].address < clusterRegisters[j].address return clusterRegisters[i].Address < clusterRegisters[j].Address
}) })
if dimIncrement == -1 && len(clusterRegisters) > 0 { if dimIncrement == -1 && len(clusterRegisters) > 0 {
lastReg := clusterRegisters[len(clusterRegisters)-1] lastReg := clusterRegisters[len(clusterRegisters)-1]
lastAddress := lastReg.address lastAddress := lastReg.Address
if lastReg.array != -1 { if lastReg.Array != -1 {
lastAddress = lastReg.address + uint64(lastReg.array*lastReg.elementSize) lastAddress = lastReg.Address + uint64(lastReg.Array*lastReg.ElementSize)
} }
firstAddress := clusterRegisters[0].address firstAddress := clusterRegisters[0].Address
dimIncrement = int(lastAddress - firstAddress) dimIncrement = int(lastAddress - firstAddress)
} }
@ -368,22 +385,22 @@ func readSVD(path, sourceURL string) (*Device, error) {
clusterName = strings.ToUpper(clusterName) clusterName = strings.ToUpper(clusterName)
} }
p.registers = append(p.registers, &PeripheralField{ p.Registers = append(p.Registers, &PeripheralField{
name: clusterName, Name: clusterName,
address: baseAddress + clusterOffset, Address: baseAddress + clusterOffset,
description: cluster.Description, Description: cluster.Description,
registers: clusterRegisters, Registers: clusterRegisters,
array: dim, Array: dim,
elementSize: dimIncrement, ElementSize: dimIncrement,
}) })
} }
sort.SliceStable(p.registers, func(i, j int) bool { sort.SliceStable(p.Registers, func(i, j int) bool {
return p.registers[i].address < p.registers[j].address return p.Registers[i].Address < p.Registers[j].Address
}) })
} }
// Make a sorted list of interrupts. // Make a sorted list of interrupts.
interruptList := make([]*interrupt, 0, len(interrupts)) interruptList := make([]*Interrupt, 0, len(interrupts))
for _, intr := range interrupts { for _, intr := range interrupts {
interruptList = append(interruptList, intr) interruptList = append(interruptList, intr)
} }
@ -391,7 +408,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
if interruptList[i].Value != interruptList[j].Value { if interruptList[i].Value != interruptList[j].Value {
return interruptList[i].Value < interruptList[j].Value return interruptList[i].Value < interruptList[j].Value
} }
return interruptList[i].peripheralIndex < interruptList[j].peripheralIndex return interruptList[i].PeripheralIndex < interruptList[j].PeripheralIndex
}) })
// Properly format the license block, with comments. // Properly format the license block, with comments.
@ -402,16 +419,16 @@ func readSVD(path, sourceURL string) (*Device, error) {
} }
return &Device{ return &Device{
metadata: map[string]string{ Metadata: &Metadata{
"file": filepath.Base(path), File: filepath.Base(path),
"descriptorSource": sourceURL, DescriptorSource: sourceURL,
"name": device.Name, Name: device.Name,
"nameLower": strings.ToLower(device.Name), NameLower: strings.ToLower(device.Name),
"description": strings.TrimSpace(device.Description), Description: strings.TrimSpace(device.Description),
"licenseBlock": licenseBlock, LicenseBlock: licenseBlock,
}, },
interrupts: interruptList, Interrupts: interruptList,
peripherals: peripheralsList, Peripherals: peripheralsList,
}, nil }, nil
} }
@ -443,7 +460,7 @@ func orderPeripherals(input []SVDPeripheral) []*SVDPeripheral {
return sortedPeripherals return sortedPeripherals
} }
func addInterrupt(interrupts map[string]*interrupt, name, interruptName string, index int, description string) { func addInterrupt(interrupts map[string]*Interrupt, name, interruptName string, index int, description string) {
if _, ok := interrupts[name]; ok { if _, ok := interrupts[name]; ok {
if interrupts[name].Value != index { if interrupts[name].Value != index {
// Note: some SVD files like the one for STM32H7x7 contain mistakes. // Note: some SVD files like the one for STM32H7x7 contain mistakes.
@ -462,10 +479,10 @@ func addInterrupt(interrupts map[string]*interrupt, name, interruptName string,
interrupts[name].Description += " // " + description interrupts[name].Description += " // " + description
} }
} else { } else {
interrupts[name] = &interrupt{ interrupts[name] = &Interrupt{
Name: name, Name: name,
HandlerName: interruptName + "_IRQHandler", HandlerName: interruptName + "_IRQHandler",
peripheralIndex: len(interrupts), PeripheralIndex: len(interrupts),
Value: index, Value: index,
Description: description, Description: description,
} }
@ -542,20 +559,20 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
} }
fields = append(fields, Bitfield{ fields = append(fields, Bitfield{
name: fmt.Sprintf("%s_%s%s_%s_Pos", groupName, bitfieldPrefix, regName, fieldName), Name: fmt.Sprintf("%s_%s%s_%s_Pos", groupName, bitfieldPrefix, regName, fieldName),
description: fmt.Sprintf("Position of %s field.", fieldName), Description: fmt.Sprintf("Position of %s field.", fieldName),
value: lsb, Value: lsb,
}) })
fields = append(fields, Bitfield{ fields = append(fields, Bitfield{
name: fmt.Sprintf("%s_%s%s_%s_Msk", groupName, bitfieldPrefix, regName, fieldName), Name: fmt.Sprintf("%s_%s%s_%s_Msk", groupName, bitfieldPrefix, regName, fieldName),
description: fmt.Sprintf("Bit mask of %s field.", fieldName), Description: fmt.Sprintf("Bit mask of %s field.", fieldName),
value: (0xffffffff >> (31 - (msb - lsb))) << lsb, Value: (0xffffffff >> (31 - (msb - lsb))) << lsb,
}) })
if lsb == msb { // single bit if lsb == msb { // single bit
fields = append(fields, Bitfield{ fields = append(fields, Bitfield{
name: fmt.Sprintf("%s_%s%s_%s", groupName, bitfieldPrefix, regName, fieldName), Name: fmt.Sprintf("%s_%s%s_%s", groupName, bitfieldPrefix, regName, fieldName),
description: fmt.Sprintf("Bit %s.", fieldName), Description: fmt.Sprintf("Bit %s.", fieldName),
value: 1 << lsb, Value: 1 << lsb,
}) })
} }
for _, enumEl := range enumeratedValues.EnumeratedValue { for _, enumEl := range enumeratedValues.EnumeratedValue {
@ -566,7 +583,7 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
if !unicode.IsUpper(rune(enumName[0])) && !unicode.IsDigit(rune(enumName[0])) { if !unicode.IsUpper(rune(enumName[0])) && !unicode.IsDigit(rune(enumName[0])) {
enumName = strings.ToUpper(enumName) enumName = strings.ToUpper(enumName)
} }
enumDescription := strings.Replace(enumEl.Description, "\n", " ", -1) enumDescription := formatText(enumEl.Description)
var enumValue uint64 var enumValue uint64
var err error var err error
if strings.HasPrefix(enumEl.Value, "0b") { if strings.HasPrefix(enumEl.Value, "0b") {
@ -606,7 +623,7 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
// existing enum bitfield value. // existing enum bitfield value.
enumSeen[enumName] = -1 enumSeen[enumName] = -1
for i, field := range fields { for i, field := range fields {
if field.name == enumName { if field.Name == enumName {
fields = append(fields[:i], fields[i+1:]...) fields = append(fields[:i], fields[i+1:]...)
break break
} }
@ -617,9 +634,9 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
enumSeen[enumName] = int64(enumValue) enumSeen[enumName] = int64(enumValue)
fields = append(fields, Bitfield{ fields = append(fields, Bitfield{
name: enumName, Name: enumName,
description: enumDescription, Description: enumDescription,
value: uint32(enumValue), Value: uint32(enumValue),
}) })
} }
} }
@ -643,7 +660,7 @@ func (r *Register) name() string {
} }
func (r *Register) description() string { func (r *Register) description() string {
return strings.Replace(r.element.Description, "\n", " ", -1) return formatText(r.element.Description)
} }
func (r *Register) address() uint64 { func (r *Register) address() uint64 {
@ -748,16 +765,16 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
for i, j := range reg.dimIndex() { for i, j := range reg.dimIndex() {
regAddress := reg.address() + (uint64(i) * dimIncrement) regAddress := reg.address() + (uint64(i) * dimIncrement)
results = append(results, &PeripheralField{ results = append(results, &PeripheralField{
name: strings.ToUpper(strings.Replace(reg.name(), "%s", j, -1)), Name: strings.ToUpper(strings.Replace(reg.name(), "%s", j, -1)),
address: regAddress, Address: regAddress,
description: reg.description(), Description: reg.description(),
array: -1, Array: -1,
elementSize: reg.size(), ElementSize: reg.size(),
}) })
} }
// set first result bitfield // set first result bitfield
shortName := strings.ToUpper(strings.Replace(strings.Replace(reg.name(), "_%s", "", -1), "%s", "", -1)) shortName := strings.ToUpper(strings.Replace(strings.Replace(reg.name(), "_%s", "", -1), "%s", "", -1))
results[0].bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix) results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)
return results return results
} }
} }
@ -769,18 +786,18 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
bitfields := parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix) bitfields := parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix)
return []*PeripheralField{&PeripheralField{ return []*PeripheralField{&PeripheralField{
name: regName, Name: regName,
address: reg.address(), Address: reg.address(),
description: reg.description(), Description: reg.description(),
bitfields: bitfields, Bitfields: bitfields,
array: reg.dim(), Array: reg.dim(),
elementSize: reg.size(), ElementSize: reg.size(),
}} }}
} }
// The Go module for this device. // The Go module for this device.
func writeGo(outdir string, device *Device, interruptSystem string) error { func writeGo(outdir string, device *Device, interruptSystem string) error {
outf, err := os.Create(filepath.Join(outdir, device.metadata["nameLower"]+".go")) outf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+".go"))
if err != nil { if err != nil {
return err return err
} }
@ -788,20 +805,24 @@ func writeGo(outdir string, device *Device, interruptSystem string) error {
w := bufio.NewWriter(outf) w := bufio.NewWriter(outf)
maxInterruptValue := 0 maxInterruptValue := 0
for _, intr := range device.interrupts { for _, intr := range device.Interrupts {
if intr.Value > maxInterruptValue { if intr.Value > maxInterruptValue {
maxInterruptValue = intr.Value maxInterruptValue = intr.Value
} }
} }
t := template.Must(template.New("go").Parse(`// Automatically generated file. DO NOT EDIT. t := template.Must(template.New("go").Funcs(template.FuncMap{
// Generated by gen-device-svd.go from {{.metadata.file}}, see {{.metadata.descriptorSource}} "bytesNeeded": func(i, j uint64) uint64 { return j - i },
"isMultiline": isMultiline,
"splitLine": splitLine,
}).Parse(`// Automatically generated file. DO NOT EDIT.
// Generated by gen-device-svd.go from {{.device.Metadata.File}}, see {{.device.Metadata.DescriptorSource}}
// +build {{.pkgName}},{{.metadata.nameLower}} // +build {{.pkgName}},{{.device.Metadata.NameLower}}
// {{.metadata.description}} // {{.device.Metadata.Description}}
// //
{{.metadata.licenseBlock}} {{.device.Metadata.LicenseBlock}}
package {{.pkgName}} package {{.pkgName}}
import ( import (
@ -812,32 +833,50 @@ import (
// Some information about this device. // Some information about this device.
const ( const (
DEVICE = "{{.metadata.name}}" DEVICE = "{{.device.Metadata.Name}}"
) )
// Interrupt numbers. // Interrupt numbers.
const ({{range .interrupts}} const (
IRQ_{{.Name}} = {{.Value}} // {{.Description}}{{end}} {{- range .device.Interrupts}}
IRQ_max = {{.interruptMax}} // Highest interrupt number on this device. {{- if .Description}}
{{- range .Description|splitLine}}
// {{.}}
{{- end}}
{{- end}}
IRQ_{{.Name}} = {{.Value}}
{{- "\n"}}
{{- end}}
// Highest interrupt number on this device.
IRQ_max = {{.interruptMax}}
) )
{{if eq .interruptSystem "hardware"}} {{- if eq .interruptSystem "hardware"}}
// Map interrupt numbers to function names. // Map interrupt numbers to function names.
// These aren't real calls, they're removed by the compiler. // These aren't real calls, they're removed by the compiler.
var ({{range .interrupts}} var (
_ = interrupt.Register(IRQ_{{.Name}}, "{{.HandlerName}}"){{end}} {{- range .device.Interrupts}}
_ = interrupt.Register(IRQ_{{.Name}}, "{{.HandlerName}}")
{{- end}}
) )
{{end}} {{- end}}
// Peripherals. // Peripherals.
var ( var (
{{range .peripherals}} {{.Name}} = (*{{.GroupName}}_Type)(unsafe.Pointer(uintptr(0x{{printf "%x" .BaseAddress}}))) // {{.Description}} {{- range .device.Peripherals}}
{{end}}) {{- if .Description}}
{{- range .Description|splitLine}}
// {{.}}
{{- end}}
{{- end}}
{{.Name}} = (*{{.GroupName}}_Type)(unsafe.Pointer(uintptr(0x{{printf "%x" .BaseAddress}})))
{{- "\n"}}
{{- end}}
)
`)) `))
err = t.Execute(w, map[string]interface{}{ err = t.Execute(w, map[string]interface{}{
"metadata": device.metadata, "device": device,
"interrupts": device.interrupts,
"peripherals": device.peripherals,
"pkgName": filepath.Base(strings.TrimRight(outdir, "/")), "pkgName": filepath.Base(strings.TrimRight(outdir, "/")),
"interruptMax": maxInterruptValue, "interruptMax": maxInterruptValue,
"interruptSystem": interruptSystem, "interruptSystem": interruptSystem,
@ -847,16 +886,23 @@ var (
} }
// Define peripheral struct types. // Define peripheral struct types.
for _, peripheral := range device.peripherals { for _, peripheral := range device.Peripherals {
if peripheral.registers == nil { if peripheral.Registers == nil {
// This peripheral was derived from another peripheral. No new type // This peripheral was derived from another peripheral. No new type
// needs to be defined for it. // needs to be defined for it.
continue continue
} }
fmt.Fprintf(w, "\n// %s\ntype %s_Type struct {\n", peripheral.Description, peripheral.GroupName) fmt.Fprintln(w)
if peripheral.Description != "" {
for _, l := range splitLine(peripheral.Description) {
fmt.Fprintf(w, "// %s\n", l)
}
}
fmt.Fprintf(w, "type %s_Type struct {\n", peripheral.GroupName)
address := peripheral.BaseAddress address := peripheral.BaseAddress
for _, register := range peripheral.registers { for _, register := range peripheral.Registers {
if register.registers == nil && address > register.address { if register.Registers == nil && address > register.Address {
// In Nordic SVD files, these registers are deprecated or // In Nordic SVD files, these registers are deprecated or
// duplicates, so can be ignored. // duplicates, so can be ignored.
//fmt.Fprintf(os.Stderr, "skip: %s.%s 0x%x - 0x%x %d\n", peripheral.Name, register.name, address, register.address, register.elementSize) //fmt.Fprintf(os.Stderr, "skip: %s.%s 0x%x - 0x%x %d\n", peripheral.Name, register.name, address, register.address, register.elementSize)
@ -864,7 +910,7 @@ var (
} }
var regType string var regType string
switch register.elementSize { switch register.ElementSize {
case 8: case 8:
regType = "volatile.Register64" regType = "volatile.Register64"
case 4: case 4:
@ -878,24 +924,24 @@ var (
} }
// insert padding, if needed // insert padding, if needed
if address < register.address { if address < register.Address {
bytesNeeded := register.address - address bytesNeeded := register.Address - address
if bytesNeeded == 1 { if bytesNeeded == 1 {
w.WriteString("\t_ byte\n") w.WriteString("\t_ byte\n")
} else { } else {
fmt.Fprintf(w, "\t_ [%d]byte\n", bytesNeeded) fmt.Fprintf(w, "\t_ [%d]byte\n", bytesNeeded)
} }
address = register.address address = register.Address
} }
lastCluster := false lastCluster := false
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 = "struct {\n" regType = "struct {\n"
subaddress := register.address subaddress := register.Address
for _, subregister := range register.registers { for _, subregister := range register.Registers {
var subregType string var subregType string
switch subregister.elementSize { switch subregister.ElementSize {
case 8: case 8:
subregType = "volatile.Register64" subregType = "volatile.Register64"
case 4: case 4:
@ -909,11 +955,11 @@ var (
panic("unknown element size") panic("unknown element size")
} }
if subregister.array != -1 { if subregister.Array != -1 {
subregType = fmt.Sprintf("[%d]%s", subregister.array, subregType) subregType = fmt.Sprintf("[%d]%s", subregister.Array, subregType)
} }
if subaddress != subregister.address { if subaddress != subregister.Address {
bytesNeeded := subregister.address - subaddress bytesNeeded := subregister.Address - subaddress
if bytesNeeded == 1 { if bytesNeeded == 1 {
regType += "\t\t_ byte\n" regType += "\t\t_ byte\n"
} else { } else {
@ -922,17 +968,17 @@ var (
subaddress += bytesNeeded subaddress += bytesNeeded
} }
var subregSize uint64 var subregSize uint64
if subregister.array != -1 { if subregister.Array != -1 {
subregSize = uint64(subregister.array * subregister.elementSize) subregSize = uint64(subregister.Array * subregister.ElementSize)
} else { } else {
subregSize = uint64(subregister.elementSize) subregSize = uint64(subregister.ElementSize)
} }
subaddress += subregSize subaddress += subregSize
regType += fmt.Sprintf("\t\t%s %s\n", subregister.name, subregType) regType += fmt.Sprintf("\t\t%s %s\n", subregister.Name, subregType)
} }
if register.array != -1 { if register.Array != -1 {
if subaddress != register.address+uint64(register.elementSize) { if subaddress != register.Address+uint64(register.ElementSize) {
bytesNeeded := (register.address + uint64(register.elementSize)) - subaddress bytesNeeded := (register.Address + uint64(register.ElementSize)) - subaddress
if bytesNeeded == 1 { if bytesNeeded == 1 {
regType += "\t_ byte\n" regType += "\t_ byte\n"
} else { } else {
@ -946,40 +992,49 @@ var (
address = subaddress address = subaddress
} }
if register.array != -1 { if register.Array != -1 {
regType = fmt.Sprintf("[%d]%s", register.array, regType) regType = fmt.Sprintf("[%d]%s", register.Array, regType)
} }
fmt.Fprintf(w, "\t%s %s // 0x%X\n", register.name, regType, register.address-peripheral.BaseAddress) fmt.Fprintf(w, "\t%s %s // 0x%X\n", register.Name, regType, register.Address-peripheral.BaseAddress)
// next address // next address
if lastCluster { if lastCluster {
lastCluster = false lastCluster = false
} else if register.array != -1 { } else if register.Array != -1 {
address = register.address + uint64(register.elementSize*register.array) address = register.Address + uint64(register.ElementSize*register.Array)
} else { } else {
address = register.address + uint64(register.elementSize) address = register.Address + uint64(register.ElementSize)
} }
} }
w.WriteString("}\n") w.WriteString("}\n")
} }
// Define bitfields. // Define bitfields.
for _, peripheral := range device.peripherals { for _, peripheral := range device.Peripherals {
if peripheral.registers == nil { if peripheral.Registers == nil {
// This peripheral was derived from another peripheral. Bitfields are // This peripheral was derived from another peripheral. Bitfields are
// already defined. // already defined.
continue continue
} }
fmt.Fprintf(w, "\n// Bitfields for %s: %s\nconst(", peripheral.Name, peripheral.Description) fmt.Fprintf(w, "\n// Bitfields for %s", peripheral.Name)
for _, register := range peripheral.registers { if isMultiline(peripheral.Description) {
if len(register.bitfields) != 0 { for _, l := range splitLine(peripheral.Description) {
writeGoRegisterBitfields(w, register, register.name) fmt.Fprintf(w, "\n// %s", l)
} }
if register.registers == nil { } else if peripheral.Description != "" {
fmt.Fprintf(w, ": %s", peripheral.Description)
}
fmt.Fprint(w, "\nconst(")
for _, register := range peripheral.Registers {
if len(register.Bitfields) != 0 {
writeGoRegisterBitfields(w, register, register.Name)
}
if register.Registers == nil {
continue continue
} }
for _, subregister := range register.registers { for _, subregister := range register.Registers {
writeGoRegisterBitfields(w, subregister, register.name+"."+subregister.name) writeGoRegisterBitfields(w, subregister, register.Name+"."+subregister.Name)
} }
} }
w.WriteString(")\n") w.WriteString(")\n")
@ -990,22 +1045,29 @@ var (
func writeGoRegisterBitfields(w *bufio.Writer, register *PeripheralField, name string) { func writeGoRegisterBitfields(w *bufio.Writer, register *PeripheralField, name string) {
w.WriteString("\n\t// " + name) w.WriteString("\n\t// " + name)
if register.description != "" { if register.Description != "" {
w.WriteString(": " + register.description) if isMultiline(register.Description) {
for _, l := range splitLine(register.Description) {
w.WriteString("\n\t// " + l)
}
} else {
w.WriteString(": " + register.Description)
}
} }
w.WriteByte('\n') w.WriteByte('\n')
for _, bitfield := range register.bitfields { for _, bitfield := range register.Bitfields {
fmt.Fprintf(w, "\t%s = 0x%x", bitfield.name, bitfield.value) if bitfield.Description != "" {
if bitfield.description != "" { for _, l := range splitLine(bitfield.Description) {
w.WriteString(" // " + bitfield.description) w.WriteString("\t// " + l + "\n")
} }
w.WriteByte('\n') }
fmt.Fprintf(w, "\t%s = 0x%x\n", bitfield.Name, bitfield.Value)
} }
} }
// The interrupt vector, which is hard to write directly in Go. // The interrupt vector, which is hard to write directly in Go.
func writeAsm(outdir string, device *Device) error { func writeAsm(outdir string, device *Device) error {
outf, err := os.Create(filepath.Join(outdir, device.metadata["nameLower"]+".s")) outf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+".s"))
if err != nil { if err != nil {
return err return err
} }
@ -1013,11 +1075,11 @@ func writeAsm(outdir string, device *Device) error {
w := bufio.NewWriter(outf) w := bufio.NewWriter(outf)
t := template.Must(template.New("go").Parse(`// Automatically generated file. DO NOT EDIT. t := template.Must(template.New("go").Parse(`// Automatically generated file. DO NOT EDIT.
// Generated by gen-device-svd.go from {{.file}}, see {{.descriptorSource}} // Generated by gen-device-svd.go from {{.File}}, see {{.DescriptorSource}}
// {{.description}} // {{.Description}}
// //
{{.licenseBlock}} {{.LicenseBlock}}
.syntax unified .syntax unified
@ -1063,12 +1125,12 @@ Default_Handler:
// Extra interrupts for peripherals defined by the hardware vendor. // Extra interrupts for peripherals defined by the hardware vendor.
`)) `))
err = t.Execute(w, device.metadata) err = t.Execute(w, device.Metadata)
if err != nil { if err != nil {
return err return err
} }
num := 0 num := 0
for _, intr := range device.interrupts { for _, intr := range device.Interrupts {
if intr.Value == num-1 { if intr.Value == num-1 {
continue continue
} }
@ -1096,7 +1158,7 @@ Default_Handler:
IRQ PendSV_Handler IRQ PendSV_Handler
IRQ SysTick_Handler IRQ SysTick_Handler
`) `)
for _, intr := range device.interrupts { for _, intr := range device.Interrupts {
fmt.Fprintf(w, " IRQ %s_IRQHandler\n", intr.Name) fmt.Fprintf(w, " IRQ %s_IRQHandler\n", intr.Name)
} }
return w.Flush() return w.Flush()