Provide Set/Get for each register field described in SVD files
- rename Bitfield to Constant - add methods to the exiting types to set/get bitfields - integrate clustered registers - add cluster size to properly add filler at the end of the structure - fix structures with leading filler (i.e. for FICR_Type.INFO in nfr9160) - shorten the function name when prefix and suffix are identical. i.e. GetSTATE_STATE vs GetSTATE
Этот коммит содержится в:
родитель
2f57e4ff6d
коммит
0a0981a475
1 изменённых файлов: 253 добавлений и 66 удалений
|
@ -128,21 +128,30 @@ type Peripheral struct {
|
||||||
// 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
|
Constants []Constant
|
||||||
|
ShortName string // name stripped of "spaced array" suffix
|
||||||
|
Bitfields []Bitfield // set of bit-fields provided by this
|
||||||
|
HasBitfields bool // set true when Bitfields was set for a first PeripheralField of "spaced array".
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bitfield struct {
|
type Constant struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Value uint64
|
Value uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Bitfield struct {
|
||||||
|
Name string
|
||||||
|
Offset uint32
|
||||||
|
Mask uint32
|
||||||
|
}
|
||||||
|
|
||||||
func formatText(text string) string {
|
func formatText(text string) string {
|
||||||
text = regexp.MustCompile(`[ \t\n]+`).ReplaceAllString(text, " ") // Collapse whitespace (like in HTML)
|
text = regexp.MustCompile(`[ \t\n]+`).ReplaceAllString(text, " ") // Collapse whitespace (like in HTML)
|
||||||
text = strings.ReplaceAll(text, "\\n ", "\n")
|
text = strings.ReplaceAll(text, "\\n ", "\n")
|
||||||
|
@ -332,6 +341,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
||||||
Registers: subcpRegisters,
|
Registers: subcpRegisters,
|
||||||
Array: subdim,
|
Array: subdim,
|
||||||
ElementSize: int(subdimIncrement),
|
ElementSize: int(subdimIncrement),
|
||||||
|
ShortName: clusterPrefix + subclusterName,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
for _, regEl := range subClusterEl.Registers {
|
for _, regEl := range subClusterEl.Registers {
|
||||||
|
@ -402,6 +412,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
||||||
Registers: clusterRegisters,
|
Registers: clusterRegisters,
|
||||||
Array: dim,
|
Array: dim,
|
||||||
ElementSize: dimIncrement,
|
ElementSize: dimIncrement,
|
||||||
|
ShortName: clusterName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.SliceStable(p.Registers, func(i, j int) bool {
|
sort.SliceStable(p.Registers, func(i, j int) bool {
|
||||||
|
@ -509,8 +520,9 @@ func addInterrupt(interrupts map[string]*Interrupt, name, interruptName string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPrefix string) []Bitfield {
|
func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPrefix string) ([]Constant, []Bitfield) {
|
||||||
var fields []Bitfield
|
var fields []Constant
|
||||||
|
var bitfields []Bitfield
|
||||||
enumSeen := map[string]int64{}
|
enumSeen := map[string]int64{}
|
||||||
for _, fieldEl := range fieldEls {
|
for _, fieldEl := range fieldEls {
|
||||||
// Some bitfields (like the STM32H7x7) contain invalid bitfield
|
// Some bitfields (like the STM32H7x7) contain invalid bitfield
|
||||||
|
@ -578,18 +590,23 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields = append(fields, Bitfield{
|
bitfields = append(bitfields, Bitfield{
|
||||||
|
Name: fieldName,
|
||||||
|
Offset: lsb,
|
||||||
|
Mask: (0xffffffff >> (31 - (msb - lsb))) << lsb,
|
||||||
|
})
|
||||||
|
fields = append(fields, Constant{
|
||||||
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: uint64(lsb),
|
Value: uint64(lsb),
|
||||||
})
|
})
|
||||||
fields = append(fields, Bitfield{
|
fields = append(fields, Constant{
|
||||||
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: (0xffffffffffffffff >> (63 - (msb - lsb))) << lsb,
|
Value: (0xffffffffffffffff >> (63 - (msb - lsb))) << lsb,
|
||||||
})
|
})
|
||||||
if lsb == msb { // single bit
|
if lsb == msb { // single bit
|
||||||
fields = append(fields, Bitfield{
|
fields = append(fields, Constant{
|
||||||
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,
|
||||||
|
@ -653,14 +670,14 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
|
||||||
}
|
}
|
||||||
enumSeen[enumName] = int64(enumValue)
|
enumSeen[enumName] = int64(enumValue)
|
||||||
|
|
||||||
fields = append(fields, Bitfield{
|
fields = append(fields, Constant{
|
||||||
Name: enumName,
|
Name: enumName,
|
||||||
Description: enumDescription,
|
Description: enumDescription,
|
||||||
Value: enumValue,
|
Value: enumValue,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fields
|
return fields, bitfields
|
||||||
}
|
}
|
||||||
|
|
||||||
type Register struct {
|
type Register struct {
|
||||||
|
@ -782,6 +799,7 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
||||||
// a "spaced array" of registers, special processing required
|
// a "spaced array" of registers, special processing required
|
||||||
// we need to generate a separate register for each "element"
|
// we need to generate a separate register for each "element"
|
||||||
var results []*PeripheralField
|
var results []*PeripheralField
|
||||||
|
shortName := strings.ToUpper(strings.ReplaceAll(strings.ReplaceAll(reg.name(), "_%s", ""), "%s", ""))
|
||||||
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{
|
||||||
|
@ -790,11 +808,16 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
||||||
Description: reg.description(),
|
Description: reg.description(),
|
||||||
Array: -1,
|
Array: -1,
|
||||||
ElementSize: reg.size(),
|
ElementSize: reg.size(),
|
||||||
|
ShortName: shortName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// set first result bitfield
|
// set first result bitfield
|
||||||
shortName := strings.ToUpper(strings.ReplaceAll(strings.ReplaceAll(reg.name(), "_%s", ""), "%s", ""))
|
results[0].Constants, results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)
|
||||||
results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)
|
results[0].HasBitfields = len(results[0].Bitfields) > 0
|
||||||
|
for i := 1; i < len(results); i++ {
|
||||||
|
results[i].Bitfields = results[0].Bitfields
|
||||||
|
results[i].HasBitfields = results[0].HasBitfields
|
||||||
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,14 +827,17 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
||||||
}
|
}
|
||||||
regName = cleanName(regName)
|
regName = cleanName(regName)
|
||||||
|
|
||||||
bitfields := parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix)
|
constants, 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,
|
Constants: constants,
|
||||||
Array: reg.dim(),
|
Array: reg.dim(),
|
||||||
ElementSize: reg.size(),
|
ElementSize: reg.size(),
|
||||||
|
ShortName: regName,
|
||||||
|
Bitfields: bitfields,
|
||||||
|
HasBitfields: len(bitfields) > 0,
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,11 +976,20 @@ var (
|
||||||
fmt.Fprintf(w, "type %s_Type struct {\n", peripheral.GroupName)
|
fmt.Fprintf(w, "type %s_Type struct {\n", peripheral.GroupName)
|
||||||
|
|
||||||
address := peripheral.BaseAddress
|
address := peripheral.BaseAddress
|
||||||
|
type clusterInfo struct {
|
||||||
|
name string
|
||||||
|
address uint64
|
||||||
|
size uint64
|
||||||
|
registers []*PeripheralField
|
||||||
|
}
|
||||||
|
clusters := []clusterInfo{}
|
||||||
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)
|
||||||
|
// remove bit fields from such register
|
||||||
|
register.Bitfields = nil
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -986,34 +1021,14 @@ var (
|
||||||
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 = peripheral.GroupName + "_" + register.Name
|
||||||
|
clusters = append(clusters, clusterInfo{regType, register.Address, uint64(register.ElementSize), register.Registers})
|
||||||
|
regType = regType + "_Type"
|
||||||
subaddress := register.Address
|
subaddress := register.Address
|
||||||
for _, subregister := range register.Registers {
|
for _, subregister := range register.Registers {
|
||||||
var subregType string
|
|
||||||
switch subregister.ElementSize {
|
|
||||||
case 8:
|
|
||||||
subregType = "volatile.Register64"
|
|
||||||
case 4:
|
|
||||||
subregType = "volatile.Register32"
|
|
||||||
case 2:
|
|
||||||
subregType = "volatile.Register16"
|
|
||||||
case 1:
|
|
||||||
subregType = "volatile.Register8"
|
|
||||||
}
|
|
||||||
if subregType == "" {
|
|
||||||
panic("unknown element size")
|
|
||||||
}
|
|
||||||
|
|
||||||
if subregister.Array != -1 {
|
|
||||||
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 {
|
|
||||||
regType += "\t\t_ byte\n"
|
|
||||||
} else {
|
|
||||||
regType += fmt.Sprintf("\t\t_ [%d]byte\n", bytesNeeded)
|
|
||||||
}
|
|
||||||
subaddress += bytesNeeded
|
subaddress += bytesNeeded
|
||||||
}
|
}
|
||||||
var subregSize uint64
|
var subregSize uint64
|
||||||
|
@ -1023,21 +1038,10 @@ var (
|
||||||
subregSize = uint64(subregister.ElementSize)
|
subregSize = uint64(subregister.ElementSize)
|
||||||
}
|
}
|
||||||
subaddress += subregSize
|
subaddress += subregSize
|
||||||
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) {
|
|
||||||
bytesNeeded := (register.Address + uint64(register.ElementSize)) - subaddress
|
|
||||||
if bytesNeeded == 1 {
|
|
||||||
regType += "\t_ byte\n"
|
|
||||||
} else {
|
|
||||||
regType += fmt.Sprintf("\t_ [%d]byte\n", bytesNeeded)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lastCluster = true
|
lastCluster = true
|
||||||
}
|
}
|
||||||
regType += "\t}"
|
|
||||||
address = subaddress
|
address = subaddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,16 +1060,127 @@ var (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.WriteString("}\n")
|
w.WriteString("}\n")
|
||||||
|
|
||||||
|
for _, register := range peripheral.Registers {
|
||||||
|
regName := register.Name
|
||||||
|
writeGoRegisterBitfieldType(w, register, peripheral.GroupName, regName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define clusters
|
||||||
|
for i := 0; i < len(clusters); i++ {
|
||||||
|
cluster := clusters[i]
|
||||||
|
if len(cluster.registers) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintf(w, "type %s_Type struct {\n", cluster.name)
|
||||||
|
|
||||||
|
address := cluster.address
|
||||||
|
|
||||||
|
for _, register := range cluster.registers {
|
||||||
|
if register.Registers == nil && address > register.Address {
|
||||||
|
// In Nordic SVD files, these registers are deprecated or
|
||||||
|
// 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)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var regType string
|
||||||
|
switch register.ElementSize {
|
||||||
|
case 8:
|
||||||
|
regType = "volatile.Register64"
|
||||||
|
case 4:
|
||||||
|
regType = "volatile.Register32"
|
||||||
|
case 2:
|
||||||
|
regType = "volatile.Register16"
|
||||||
|
case 1:
|
||||||
|
regType = "volatile.Register8"
|
||||||
|
default:
|
||||||
|
regType = "volatile.Register32"
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert padding, if needed
|
||||||
|
if address < register.Address {
|
||||||
|
bytesNeeded := register.Address - address
|
||||||
|
if bytesNeeded == 1 {
|
||||||
|
w.WriteString("\t_ byte\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "\t_ [%d]byte\n", bytesNeeded)
|
||||||
|
}
|
||||||
|
address = register.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCluster := false
|
||||||
|
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})
|
||||||
|
regType = regType + "_Type"
|
||||||
|
|
||||||
|
subaddress := register.Address
|
||||||
|
for _, subregister := range register.Registers {
|
||||||
|
if subaddress != subregister.Address {
|
||||||
|
bytesNeeded := subregister.Address - subaddress
|
||||||
|
subaddress += bytesNeeded
|
||||||
|
}
|
||||||
|
var subregSize uint64
|
||||||
|
if subregister.Array != -1 {
|
||||||
|
subregSize = uint64(subregister.Array * subregister.ElementSize)
|
||||||
|
} else {
|
||||||
|
subregSize = uint64(subregister.ElementSize)
|
||||||
|
}
|
||||||
|
subaddress += subregSize
|
||||||
|
}
|
||||||
|
if register.Array == -1 {
|
||||||
|
lastCluster = true
|
||||||
|
}
|
||||||
|
address = subaddress
|
||||||
|
}
|
||||||
|
|
||||||
|
if register.Array != -1 {
|
||||||
|
regType = fmt.Sprintf("[%d]%s", register.Array, regType)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\t%s %s // 0x%X\n", register.Name, regType, register.Address-peripheral.BaseAddress)
|
||||||
|
|
||||||
|
// next address
|
||||||
|
if lastCluster {
|
||||||
|
lastCluster = false
|
||||||
|
} else if register.Array != -1 {
|
||||||
|
address = register.Address + uint64(register.ElementSize*register.Array)
|
||||||
|
} else {
|
||||||
|
address = register.Address + uint64(register.ElementSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// make sure the structure is full
|
||||||
|
if cluster.size > (address - cluster.registers[0].Address) {
|
||||||
|
bytesNeeded := cluster.size - (address - cluster.registers[0].Address)
|
||||||
|
if bytesNeeded == 1 {
|
||||||
|
w.WriteString("\t_ byte\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "\t_ [%d]byte\n", bytesNeeded)
|
||||||
|
}
|
||||||
|
} else if cluster.size != (address - cluster.registers[0].Address) {
|
||||||
|
println("peripheral:", peripheral.Name, "cluster:", cluster.name, "size:", cluster.size, "struct size:", (address - cluster.registers[0].Address))
|
||||||
|
}
|
||||||
|
w.WriteString("}\n")
|
||||||
|
|
||||||
|
for _, register := range cluster.registers {
|
||||||
|
regName := register.Name
|
||||||
|
if register.Array == -1 {
|
||||||
|
writeGoRegisterBitfieldType(w, register, cluster.name, regName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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. Constants are
|
||||||
// already defined.
|
// already defined.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "\n// Bitfields for %s", peripheral.Name)
|
fmt.Fprintf(w, "\n// Constants for %s", peripheral.Name)
|
||||||
if isMultiline(peripheral.Description) {
|
if isMultiline(peripheral.Description) {
|
||||||
for _, l := range splitLine(peripheral.Description) {
|
for _, l := range splitLine(peripheral.Description) {
|
||||||
fmt.Fprintf(w, "\n// %s", l)
|
fmt.Fprintf(w, "\n// %s", l)
|
||||||
|
@ -1076,14 +1191,14 @@ var (
|
||||||
|
|
||||||
fmt.Fprint(w, "\nconst(")
|
fmt.Fprint(w, "\nconst(")
|
||||||
for _, register := range peripheral.Registers {
|
for _, register := range peripheral.Registers {
|
||||||
if len(register.Bitfields) != 0 {
|
if len(register.Constants) != 0 {
|
||||||
writeGoRegisterBitfields(w, register, register.Name)
|
writeGoRegisterConstants(w, register, register.Name)
|
||||||
}
|
}
|
||||||
if register.Registers == nil {
|
if register.Registers == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, subregister := range register.Registers {
|
for _, subregister := range register.Registers {
|
||||||
writeGoRegisterBitfields(w, subregister, register.Name+"."+subregister.Name)
|
writeGoRegisterConstants(w, subregister, register.Name+"."+subregister.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.WriteString(")\n")
|
w.WriteString(")\n")
|
||||||
|
@ -1092,7 +1207,7 @@ var (
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeGoRegisterBitfields(w *bufio.Writer, register *PeripheralField, name string) {
|
func writeGoRegisterConstants(w *bufio.Writer, register *PeripheralField, name string) {
|
||||||
w.WriteString("\n\t// " + name)
|
w.WriteString("\n\t// " + name)
|
||||||
if register.Description != "" {
|
if register.Description != "" {
|
||||||
if isMultiline(register.Description) {
|
if isMultiline(register.Description) {
|
||||||
|
@ -1104,7 +1219,7 @@ func writeGoRegisterBitfields(w *bufio.Writer, register *PeripheralField, name s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.WriteByte('\n')
|
w.WriteByte('\n')
|
||||||
for _, bitfield := range register.Bitfields {
|
for _, bitfield := range register.Constants {
|
||||||
if bitfield.Description != "" {
|
if bitfield.Description != "" {
|
||||||
for _, l := range splitLine(bitfield.Description) {
|
for _, l := range splitLine(bitfield.Description) {
|
||||||
w.WriteString("\t// " + l + "\n")
|
w.WriteString("\t// " + l + "\n")
|
||||||
|
@ -1114,6 +1229,78 @@ func writeGoRegisterBitfields(w *bufio.Writer, register *PeripheralField, name s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeGoRegisterBitfieldType(w *bufio.Writer, register *PeripheralField, peripheralName, registerName string) {
|
||||||
|
if len(register.Bitfields) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteString("\n// " + peripheralName + "." + registerName)
|
||||||
|
if 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')
|
||||||
|
var bitSize int
|
||||||
|
var maxMask uint32
|
||||||
|
switch register.ElementSize {
|
||||||
|
case 8:
|
||||||
|
bitSize = 64
|
||||||
|
maxMask = 0xffffffff
|
||||||
|
// maxMask = 0xffffffffffffffff // TODO how to handle 64-bit fields
|
||||||
|
case 4:
|
||||||
|
bitSize = 32
|
||||||
|
maxMask = 0xffffffff
|
||||||
|
case 2:
|
||||||
|
bitSize = 16
|
||||||
|
maxMask = 0xffff
|
||||||
|
case 1:
|
||||||
|
bitSize = 8
|
||||||
|
maxMask = 0xff
|
||||||
|
default:
|
||||||
|
bitSize = 32
|
||||||
|
maxMask = 0xffffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
typeName := fmt.Sprintf("%s_Type", peripheralName)
|
||||||
|
|
||||||
|
for _, bitfield := range register.Bitfields {
|
||||||
|
idxArg := ""
|
||||||
|
regAccess := "&o." + registerName + ".Reg"
|
||||||
|
if register.Array != -1 {
|
||||||
|
idxArg = "idx int, "
|
||||||
|
regAccess = "&o." + registerName + "[idx].Reg"
|
||||||
|
}
|
||||||
|
var funcSuffix string
|
||||||
|
if maxMask == bitfield.Mask || registerName == bitfield.Name {
|
||||||
|
funcSuffix = registerName
|
||||||
|
} else {
|
||||||
|
funcSuffix = registerName + "_" + bitfield.Name
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "func (o *%s) Set%s(%s value uint%d) {\n", typeName, funcSuffix, idxArg, bitSize)
|
||||||
|
if maxMask == bitfield.Mask {
|
||||||
|
fmt.Fprintf(w, "\tvolatile.StoreUint%d(%s, value)\n", bitSize, regAccess)
|
||||||
|
} else if bitfield.Offset > 0 {
|
||||||
|
fmt.Fprintf(w, "\tvolatile.StoreUint%d(%s, volatile.LoadUint%d(%s)&^(0x%x)|value<<%d)\n", bitSize, regAccess, bitSize, regAccess, bitfield.Mask, bitfield.Offset)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "\tvolatile.StoreUint%d(%s, volatile.LoadUint%d(%s)&^(0x%x)|value)\n", bitSize, regAccess, bitSize, regAccess, bitfield.Mask)
|
||||||
|
}
|
||||||
|
w.WriteString("}\n")
|
||||||
|
fmt.Fprintf(w, "func (o *%s) Get%s(%s) uint%d {\n", typeName, funcSuffix, idxArg, bitSize)
|
||||||
|
if maxMask == bitfield.Mask {
|
||||||
|
fmt.Fprintf(w, "\treturn volatile.LoadUint%d(%s)\n", bitSize, regAccess)
|
||||||
|
} else if bitfield.Offset > 0 {
|
||||||
|
fmt.Fprintf(w, "\treturn (volatile.LoadUint%d(%s)&0x%x) >> %d\n", bitSize, regAccess, bitfield.Mask, bitfield.Offset)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "\treturn volatile.LoadUint%d(%s)&0x%x\n", bitSize, regAccess, bitfield.Mask)
|
||||||
|
}
|
||||||
|
w.WriteString("}\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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"))
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче