On Wed, Jun 26, 2019 at 11:16 PM Chris Angelico <rosuav@gmail.com> wrote: [...]
Then I completely don't understand getself. Can you give an example of how it would be used? So far, it just seems like an utter total mess.
Sure, below is my code snippet for signal get/set, using "L[:] = thing" syntax and overriding get/setitem(). In this case, signal follow a declaration (e.g. x = signal()) and use (e.g. x[:] = thing, thing = x[...]) paradigm. getitem always return a integer or delegates it to another object (self.current). 207 def __setitem__(self, key, value): 208 if self.typ == IN: 209 raise SignalError("IN type signal cannot be assigned") 210 if self.edge != 0: 211 raise SignalError("edge signal cannot be assigned") 212 elif isinstance(value, self.__class__): 213 self._set_next(key, value.current) 214 delay = Delay(0, value.current, signal=self) 215 self.sim.delta_next.append(delay) 216 elif isinstance(value, Delay): 217 value.next = value.delay + self.sim.current_time # relative delay to absolute time 218 value.signal = self 219 self._set_next(key, value.value) 220 if value.delay == 0: 221 self.sim.delta_next.append(value) 222 else: 223 self.sim._event(value) 224 else: 225 self._set_next(key, value) 226 delay = Delay(0, value, signal=self) 227 delay.next = self.sim.current_time 228 self.sim.delta_next.append(delay) 230 def __getitem__(self, key): 231 ''' 232 Slicing of signals 233 ''' 234 if self.value_type != int: 235 return self.current.__getitem__(key) # support generic payloads, not just int, so delegate it to "current" 236 # int signal always returns an int 237 if key in [slice(None, None, None), ...]: 238 return self.current # behaves like an int if explicitly indexed 239 elif isinstance(key, slice): 240 start = key.start 241 stop = key.stop 242 step = key.step 243 if key.step: 244 step = key.step 245 else: 246 step = 1 247 if start < stop: # the little endian case 248 if stop > self.width: 249 raise SignalError("slice stop is too big: %d (> width %d)" % (stop, self.width)) 250 stop += 1 251 else: # the big endian case 252 if start >= self.width: 253 raise SignalError("slice start is too big: %d (>= width %d)" % (start, self.width)) 254 stop -= 1 255 step = 0 - step 256 vrange = range(start, stop, step) 257 length = len(vrange) 258 current = self.current 259 value_list = [] 260 #print("current:", current) 261 for i in vrange: 262 v = (current >> i) & 0x1 263 #print("v:", v) 264 value_list.append(v) 265 return self._get_value(value_list) 266 elif isinstance(key, int): 267 if key >= self.width: 268 raise SignalError("key is too big: %d (>= width %d)" % (key, self.width)) 269 return (self.current >> key) & 0x1 270 elif isinstance(key, tuple): 271 raise SignalError("signal indices must be integers or slices, not tuple") And this is how it can be used by a user: 8 @block("hdl") 9 def ADD(name, 10 a: signal(32, IN), 11 b: signal(32, IN), 12 out: signal(32, OUT), 13 ): 14 15 x = signal(1, OUT, "x") 16 17 @always(a, b) 18 def add(): 19 out[:] = (a + b) EOF.