Hi All, I am still busy on the PinePhone SoC in Zig. I have a funny
pair of 32b hardware registers representing a u56 value, a chance for me
to play with another nice Zig feature :)
My construct currently supports passing in the u32 address of each
register along with a value to poke() into memory. I basically use a
struct wrapping '*volatile u32' created via @intToPointer on the passed
in comptime 32b address.
My question is, does Zig support anyway to test this design? ie poke()
a value in, then peek() to make sure it is correct.
I tried passing in an address generated via @ptrToInt to a slice. But
taking the address of the slice seems to be 'runtime', and my address
needs to be 'comptime'...
Cheers,Peter
PS I emailed this list a couple times, but not sure how to 'signup' to
receive other discussions taking place here? or is it just me here ;)
On Tue, 15 Aug 2023 11:17 +0200, Peter Bridge wrote:
>Hi All, I am still busy on the PinePhone SoC in Zig. I have a funny >pair of 32b hardware registers representing a u56 value, a chance for >me to play with another nice Zig feature :)>>My construct currently supports passing in the u32 address of each >register along with a value to poke() into memory. I basically use a >struct wrapping '*volatile u32' created via @intToPointer on the >passed in comptime 32b address.>>My question is, does Zig support anyway to test this design? ie >poke() a value in, then peek() to make sure it is correct.>>I tried passing in an address generated via @ptrToInt to a slice. But >taking the address of the slice seems to be 'runtime', and my address >needs to be 'comptime'...
Is there a reason the address needs to be comptime? Note that if you
are creating many instances of this struct, each with different
addresses, the compiler will generate unique type definitions for each
one, which may increase code size.
Can you share your code? Something like this ought to work and does not
require a comptime address:
const PeekPoke = struct {
ptr: [*]volatile u32,
pub fn init(addr: usize) PeekPoke {
return PeekPoke{
.ptr = @as([*]volatile u32, @ptrFromInt(addr)),
};
}
pub fn peek(self: PeekPoke, offset: usize) u32 {
return self.ptr[offset];
}
pub fn poke(self: PeekPoke, offset: usize, value: u32) void {
self.ptr[offset] = value;
}
};
test {
var buf: [8]u32 = undefined;
const addr = @intFromPtr(&buf);
const peek_poke = PeekPoke.init(addr);
peek_poke.poke(0, 42);
peek_poke.poke(1, 17);
const std = @import("std");
try std.testing.expectEqual(peek_poke.peek(0), 42);
try std.testing.expectEqual(peek_poke.peek(1), 17);
}
Though of course I don't know all of the requirements of your system :)
>PS I emailed this list a couple times, but not sure how to 'signup' to >receive other discussions taking place here? or is it just me here ;)
You can subscribe to the list by sending an email to
<~andrewrk/ziglang+subscribe@lists.sr.ht>. Docs are here:
https://man.sr.ht/lists.sr.ht/#email-controls
--
Greg
Thanks. I was previously using the code you mentioned, but now I'm
using the Zig generic pattern to return a struct that implements the
peek and poke, and wraps the volatile. But also because I am using a
packed struct(u32) for the register contents, which gives me some type
safety and very nice readable code for working with Reg contents, which
are just u1, bool, or maybe even a u56 in this case. So I think that
means I am constrained to comptime params on the generic fn signature
(includes 'type' of packed struct). Cheers, Peter
> Is there a reason the address needs to be comptime? Note that if you> are creating many instances of this struct, each with different> addresses, the compiler will generate unique type definitions for each> one, which may increase code size.>> Can you share your code? Something like this ought to work and does not> require a comptime address:>> const PeekPoke = struct {
...