-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial Register and BitField macros (#4)
Add initial Register and BitField macros Adds an initial set of macros for declaring symmetric and asymmetric registers composed of bit fields. The new `@Register` macro can be applied to a struct only containing stored properties marked with one of the new bit field macros: `@Reserved`, `@ReadWrite`, `@ReadOnly`, or `@WriteOnly`. The bit field macros take bit range argument which the register macro uses to create three views of the register. The first is a raw view which provides untyped access to the bits of the register. The second is a read view which only provides typed getters for the readable bit fields. The last is a write view which provides setters. Additional bit field macros such as `@Write1Clear` will be introduced in a future PR. Sample usage: ```swift @register(bitWidth: 32) struct Example { @readwrite(bits: 0..<1) var en: EN } var example = Register<Example>(...) example.modify { $0.en = 0x1 } ``` Miscellaneous changes Rewrites diagnostics system leveraging a new `MacroContext` type which handles prefixing diagnostics with the name of the macro which produced them. Adds helper methods prefixed by "require" to swift-syntax types which take a macro context, emit a diagnostic and throw `ExpansionError` if the requirement is not met. Adds MMIOKindMacro protocol wrappers which suppresses thrown `ExpansionErrors` to allow macros to be written as simpler straight line code e.g. `try value.requireSomething(context)`. Replaces `MacroArgumentParser` with `ParsableMacro` leveraging `MacroContext` which emits better diagnostics and fix-its.
- Loading branch information
Showing
41 changed files
with
2,893 additions
and
601 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//===----------------------------------------------------------*- swift -*-===// | ||
// | ||
// This source file is part of the Swift MMIO open source project | ||
// | ||
// Copyright (c) 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
public typealias BitFieldStorage = FixedWidthInteger & UnsignedInteger | ||
|
||
public protocol BitField { | ||
associatedtype RawStorage: BitFieldStorage | ||
static var bitRange: Range<Int> { get } | ||
static var bitWidth: Int { get } | ||
static var bitOffset: Int { get } | ||
static var bitMask: RawStorage { get } | ||
} | ||
|
||
extension BitField { | ||
public static var bitWidth: Int { self.bitRange.count } | ||
public static var bitOffset: Int { self.bitRange.lowerBound } | ||
public static var bitMask: RawStorage { (1 << self.bitWidth) - 1 } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
//===----------------------------------------------------------*- swift -*-===// | ||
// | ||
// This source file is part of the Swift MMIO open source project | ||
// | ||
// Copyright (c) 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
extension FixedWidthInteger { | ||
public subscript<Other: FixedWidthInteger>( | ||
bits range: Range<Int>, as type: Other.Type = Other.self | ||
) -> Other { | ||
@inline(__always) get { | ||
precondition(range.lowerBound >= 0) | ||
precondition(range.upperBound <= Self.bitWidth) | ||
let width = range.upperBound - range.lowerBound | ||
precondition( | ||
width <= Other.bitWidth, | ||
"\(Other.self) cannot accommodate \(width) bits.") | ||
let mask: Self = 1 << width &- 1 | ||
return Other(truncatingIfNeeded: self >> range.lowerBound & mask) | ||
} | ||
|
||
@inline(__always) set { | ||
precondition(range.lowerBound >= 0) | ||
precondition(range.upperBound <= Self.bitWidth) | ||
let width = range.upperBound - range.lowerBound | ||
precondition( | ||
width <= Other.bitWidth, | ||
"\(Other.self) cannot provide \(width) bits.") | ||
let mask: Self = 1 << width &- 1 | ||
self &= ~(mask << range.lowerBound) | ||
self |= (Self(truncatingIfNeeded: newValue) & mask) << range.lowerBound | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,46 @@ | ||
//===----------------------------------------------------------*- swift -*-===// | ||
// | ||
// This source file is part of the Swift MMIO open source project | ||
// | ||
// Copyright (c) 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// RegisterBank macros | ||
@attached(member, names: named(unsafeAddress), named(init)) | ||
public macro RegisterBank() = | ||
#externalMacro( | ||
module: "MMIOMacros", | ||
type: "RegisterBankMacro") | ||
#externalMacro(module: "MMIOMacros", type: "RegisterBankMacro") | ||
|
||
@attached(accessor) | ||
public macro RegisterBank(offset: Int) = | ||
#externalMacro( | ||
module: "MMIOMacros", | ||
type: "RegisterBankOffsetMacro") | ||
#externalMacro(module: "MMIOMacros", type: "RegisterBankOffsetMacro") | ||
|
||
// Register macros | ||
@attached(member, names: arbitrary) | ||
@attached(memberAttribute) | ||
@attached(extension, conformances: RegisterLayout) | ||
public macro Register(bitWidth: Int) = | ||
#externalMacro(module: "MMIOMacros", type: "RegisterMacro") | ||
|
||
// Note: Since the 'Reserved' macro shares an implementation with the other | ||
// bitfield macros, it can also handle the `as:` parameter found on their | ||
// external macro declarations. However, this parameter will never be used by | ||
// expansion for reserved bitfields, so it is omitted to avoid programmer use. | ||
@attached(accessor) | ||
public macro Reserved(bits: Range<Int>) = | ||
#externalMacro(module: "MMIOMacros", type: "ReservedMacro") | ||
|
||
@attached(accessor) | ||
public macro ReadWrite(bits: Range<Int>) = | ||
#externalMacro(module: "MMIOMacros", type: "ReadWriteMacro") | ||
|
||
@attached(accessor) | ||
public macro ReadOnly(bits: Range<Int>) = | ||
#externalMacro(module: "MMIOMacros", type: "ReadOnlyMacro") | ||
|
||
@attached(accessor) | ||
public macro WriteOnly(bits: Range<Int>) = | ||
#externalMacro(module: "MMIOMacros", type: "WriteOnlyMacro") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
//===----------------------------------------------------------*- swift -*-===// | ||
// | ||
// This source file is part of the Swift MMIO open source project | ||
// | ||
// Copyright (c) 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import MMIOVolatile | ||
|
||
/// A type that represents the raw storage of a volatile value type. | ||
/// | ||
/// The set of types which conform to this protocol restricts the the set of | ||
/// volatile operations available on the platform. As such, user code must | ||
/// _never_ conform new types to this protocol. | ||
public protocol MMIOVolatileStorage: BitFieldStorage { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
static func load(from pointer: UnsafePointer<Self>) -> Self | ||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
static func store(_ value: Self, to pointer: UnsafeMutablePointer<Self>) | ||
} | ||
|
||
extension UInt8: MMIOVolatileStorage { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
@_transparent | ||
public static func load(from pointer: UnsafePointer<Self>) -> Self { | ||
mmio_volatile_load_uint8_t(pointer) | ||
} | ||
|
||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
@_transparent | ||
public static func store( | ||
_ value: Self, | ||
to pointer: UnsafeMutablePointer<Self> | ||
) { | ||
mmio_volatile_store_uint8_t(pointer, value) | ||
} | ||
} | ||
|
||
extension UInt16: MMIOVolatileStorage { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
@_transparent | ||
public static func load(from pointer: UnsafePointer<Self>) -> Self { | ||
mmio_volatile_load_uint16_t(pointer) | ||
} | ||
|
||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
@_transparent | ||
public static func store( | ||
_ value: Self, | ||
to pointer: UnsafeMutablePointer<Self> | ||
) { | ||
mmio_volatile_store_uint16_t(pointer, value) | ||
} | ||
} | ||
|
||
extension UInt32: MMIOVolatileStorage { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
@_transparent | ||
public static func load(from pointer: UnsafePointer<Self>) -> Self { | ||
mmio_volatile_load_uint32_t(pointer) | ||
} | ||
|
||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
@_transparent | ||
public static func store( | ||
_ value: Self, | ||
to pointer: UnsafeMutablePointer<Self> | ||
) { | ||
mmio_volatile_store_uint32_t(pointer, value) | ||
} | ||
} | ||
|
||
#if arch(x86_64) || arch(arm64) | ||
extension UInt64: MMIOVolatileStorage { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
@_transparent | ||
public static func load(from pointer: UnsafePointer<Self>) -> Self { | ||
mmio_volatile_load_uint64_t(pointer) | ||
} | ||
|
||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
@_transparent | ||
public static func store( | ||
_ value: Self, | ||
to pointer: UnsafeMutablePointer<Self> | ||
) { | ||
mmio_volatile_store_uint64_t(pointer, value) | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
//===----------------------------------------------------------*- swift -*-===// | ||
// | ||
// This source file is part of the Swift MMIO open source project | ||
// | ||
// Copyright (c) 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// A type that supports volatile operations through a separate volatile storage | ||
/// representation. | ||
public protocol MMIOVolatileValue { | ||
// FIXME: Remove need for MMIOVolatileRepresentation with compiler support | ||
// All types can be MMIOVolatileValues if they are bitwise copyable and have a | ||
// bit width which maps to platform intrinsic load/store width. This could be | ||
// represented with the following potential future swift. | ||
// extension<Type> Type: MMIOVolatileValue where Type: BitwiseCopyable, MemoryLayout<Type>.size == 1 { } | ||
// extension<Type> Type: MMIOVolatileValue where Type: BitwiseCopyable, MemoryLayout<Type>.size == 2 { } | ||
// extension<Type> Type: MMIOVolatileValue where Type: BitwiseCopyable, MemoryLayout<Type>.size == 4 { } | ||
// extension<Type> Type: MMIOVolatileValue where Type: BitwiseCopyable, MemoryLayout<Type>.size == 8 { } | ||
|
||
/// The volatile storage representation for this value. | ||
associatedtype MMIOVolatileRepresentation: MMIOVolatileStorage | ||
/* where Self.bitWidth == MMIOVolatileRepresentation.bitWidth */ | ||
} | ||
|
||
extension MMIOVolatileValue { | ||
/// Loads an instance of `self` from the address pointed to by pointer. | ||
/// | ||
/// First loads Self.MMIOVolatileRepresentation from the pointer, then | ||
/// reinterprets the bits as Self. | ||
@_transparent | ||
static func load(from pointer: UnsafePointer<Self>) -> Self { | ||
pointer.withMemoryRebound( | ||
to: Self.MMIOVolatileRepresentation.self, | ||
capacity: 1 | ||
) { pointer in | ||
let value = Self.MMIOVolatileRepresentation.load(from: pointer) | ||
return unsafeBitCast(value, to: Self.self) | ||
} | ||
} | ||
|
||
/// Stores an instance of `self` to the address pointed to by pointer. | ||
/// | ||
/// First reinterprets the bits of Self as Self.MMIOVolatileRepresentation, | ||
/// then stores the bits to the pointer. | ||
@_transparent | ||
static func store(_ value: Self, to pointer: UnsafeMutablePointer<Self>) { | ||
pointer.withMemoryRebound( | ||
to: MMIOVolatileRepresentation.self, | ||
capacity: 1 | ||
) { pointer in | ||
let value = unsafeBitCast( | ||
value, | ||
to: MMIOVolatileRepresentation.self | ||
) | ||
Self.MMIOVolatileRepresentation.store(value, to: pointer) | ||
} | ||
} | ||
} | ||
|
||
extension UInt8: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt8 | ||
} | ||
|
||
extension UInt16: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt16 | ||
} | ||
|
||
extension UInt32: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt32 | ||
} | ||
|
||
#if arch(x86_64) || arch(arm64) | ||
extension UInt64: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt64 | ||
} | ||
#endif | ||
|
||
extension Int8: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt8 | ||
} | ||
|
||
extension Int16: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt16 | ||
} | ||
|
||
extension Int32: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt32 | ||
} | ||
|
||
#if arch(x86_64) || arch(arm64) | ||
extension Int64: MMIOVolatileValue { | ||
/// The volatile storage representation for this value. | ||
public typealias MMIOVolatileRepresentation = UInt64 | ||
} | ||
#endif |
Oops, something went wrong.