@@ -97,75 +97,41 @@ pub const Flash = struct {
9797pub const RAM = struct {
9898 pub const Address = u24 ;
9999
100- ctx : ? * anyopaque ,
101- vtable : * const VTable ,
102-
103- /// Size of the RAM memory space in bytes.
104- size : usize ,
105-
106- pub fn read (mem : RAM , index : Address ) u8 {
107- // Index is a 0-based array index, not a data-space address.
108- return mem .vtable .readFn (mem .ctx , index );
109- }
110-
111- pub fn write (mem : RAM , index : Address , value : u8 ) void {
112- // Index is a 0-based array index, not a data-space address.
113- return mem .vtable .writeFn (mem .ctx , index , value );
114- }
115-
116- pub const VTable = struct {
117- readFn : * const fn (ctx : ? * anyopaque , index : Address ) u8 ,
118- writeFn : * const fn (ctx : ? * anyopaque , index : Address , value : u8 ) void ,
119- };
120-
121- pub const empty = RAM {
122- .ctx = null ,
123- .size = 0 ,
124- .vtable = & VTable { .readFn = empty_read , .writeFn = empty_write },
125- };
126-
127- fn empty_read (ctx : ? * anyopaque , index : Address ) u8 {
128- _ = index ;
129- _ = ctx ;
130- return 0 ;
131- }
132-
133- fn empty_write (ctx : ? * anyopaque , index : Address , value : u8 ) void {
134- _ = value ;
135- _ = index ;
136- _ = ctx ;
137- }
138-
139100 pub fn Static (comptime size : comptime_int ) type {
140101 return struct {
141102 const Self = @This ();
142103
143104 data : [size ]u8 align (2 ) = .{0 } ** size ,
144105
145- pub fn memory (self : * Self ) RAM {
146- return RAM {
147- .ctx = self ,
148- .vtable = & vtable ,
149- .size = size ,
150- };
106+ pub fn device (self : * Self ) Device {
107+ return Device { .ctx = self , .vtable = & dev_vtable };
151108 }
152109
153- pub const vtable = VTable {
154- .readFn = mem_read ,
155- .writeFn = mem_write ,
110+ pub const dev_vtable = Device.VTable {
111+ .read8 = dev_read8 ,
112+ .write8 = dev_write8 ,
113+ .write_masked = dev_write_masked ,
114+ .check_exit = null ,
156115 };
157116
158- fn mem_read (ctx : ? * anyopaque , index : Address ) u8 {
159- const mem : * Self = @ptrCast (@alignCast (ctx .? ));
117+ fn dev_read8 (ctx : * anyopaque , index : usize ) u8 {
118+ const mem : * Self = @ptrCast (@alignCast (ctx ));
160119 std .debug .assert (index < size );
161120 return mem .data [index ];
162121 }
163122
164- fn mem_write (ctx : ? * anyopaque , index : Address , value : u8 ) void {
165- const mem : * Self = @ptrCast (@alignCast (ctx .? ));
123+ fn dev_write8 (ctx : * anyopaque , index : usize , value : u8 ) void {
124+ const mem : * Self = @ptrCast (@alignCast (ctx ));
166125 std .debug .assert (index < size );
167126 mem .data [index ] = value ;
168127 }
128+
129+ fn dev_write_masked (ctx : * anyopaque , index : usize , mask : u8 , value : u8 ) void {
130+ const mem : * Self = @ptrCast (@alignCast (ctx ));
131+ std .debug .assert (index < size );
132+ const old = mem .data [index ];
133+ mem .data [index ] = (old & ~ mask ) | (value & mask );
134+ }
169135 };
170136 }
171137
@@ -187,29 +153,34 @@ pub const RAM = struct {
187153 self .allocator .free (self .data );
188154 }
189155
190- pub fn memory (self : * Self ) RAM {
191- return RAM {
192- .ctx = self ,
193- .vtable = & vtable ,
194- .size = self .data .len ,
195- };
156+ pub fn device (self : * Self ) Device {
157+ return Device { .ctx = self , .vtable = & dev_vtable };
196158 }
197159
198- pub const vtable = VTable {
199- .readFn = mem_read ,
200- .writeFn = mem_write ,
160+ pub const dev_vtable = Device.VTable {
161+ .read8 = dev_read8 ,
162+ .write8 = dev_write8 ,
163+ .write_masked = dev_write_masked ,
164+ .check_exit = null ,
201165 };
202166
203- fn mem_read (ctx : ? * anyopaque , index : Address ) u8 {
204- const mem : * Self = @ptrCast (@alignCast (ctx .? ));
205- std .debug .assert (index < mem .data .len );
206- return mem .data [index ];
167+ fn dev_read8 (ctx : * anyopaque , idx : usize ) u8 {
168+ const mem : * Self = @ptrCast (@alignCast (ctx ));
169+ std .debug .assert (idx < mem .data .len );
170+ return mem .data [idx ];
207171 }
208172
209- fn mem_write (ctx : ? * anyopaque , index : Address , value : u8 ) void {
210- const mem : * Self = @ptrCast (@alignCast (ctx .? ));
211- std .debug .assert (index < mem .data .len );
212- mem .data [index ] = value ;
173+ fn dev_write8 (ctx : * anyopaque , idx : usize , v : u8 ) void {
174+ const mem : * Self = @ptrCast (@alignCast (ctx ));
175+ std .debug .assert (idx < mem .data .len );
176+ mem .data [idx ] = v ;
177+ }
178+
179+ fn dev_write_masked (ctx : * anyopaque , idx : usize , mask : u8 , v : u8 ) void {
180+ const mem : * Self = @ptrCast (@alignCast (ctx ));
181+ std .debug .assert (idx < mem .data .len );
182+ const old = mem .data [idx ];
183+ mem .data [idx ] = (old & ~ mask ) | (v & mask );
213184 }
214185 };
215186 }
@@ -275,6 +246,33 @@ pub const IO = struct {
275246 _ = ctx ;
276247 return null ;
277248 }
249+ };
250+
251+ // Unified byte-addressable device interface used by MemorySpace for RAM and IO
252+ pub const Device = struct {
253+ ctx : * anyopaque ,
254+ vtable : * const VTable ,
278255
279- // no translate in new design
256+ pub const VTable = struct {
257+ read8 : * const fn (ctx : * anyopaque , idx : usize ) u8 ,
258+ write8 : * const fn (ctx : * anyopaque , idx : usize , v : u8 ) void ,
259+ write_masked : * const fn (ctx : * anyopaque , idx : usize , mask : u8 , v : u8 ) void ,
260+ check_exit : ? * const fn (ctx : * anyopaque ) ? u8 = null ,
261+ };
262+
263+ pub fn read8 (self : * const Device , idx : usize ) u8 {
264+ return self .vtable .read8 (self .ctx , idx );
265+ }
266+
267+ pub fn write8 (self : * const Device , idx : usize , v : u8 ) void {
268+ self .vtable .write8 (self .ctx , idx , v );
269+ }
270+
271+ pub fn write_masked (self : * const Device , idx : usize , mask : u8 , v : u8 ) void {
272+ self .vtable .write_masked (self .ctx , idx , mask , v );
273+ }
274+
275+ pub fn check_exit (self : * const Device ) ? u8 {
276+ if (self .vtable .check_exit ) | f | return f (self .ctx ) else return null ;
277+ }
280278};
0 commit comments