@@ -276,6 +276,77 @@ or the view can be disabled using the ``disable`` method. A disabled
276
276
view can be re-enabled at any time.
277
277
278
278
279
+ .. _3.5 :
280
+
281
+ 3.5 Bus contention handling
282
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
283
+
284
+ Some specific CPUs have be upgraded to be interruptible which allows
285
+ to add bus contention and wait states capabitilites. Being
286
+ interruptible means, in practice, that an instruction can be
287
+ interrupted at any time and the execute_run method of the core exited.
288
+ Other devices can then run, then eventually controls returns to the
289
+ core and the instruction continues from the point it was started.
290
+ Importantly, this can be triggered from a handler and even be used to
291
+ interrupt just before the access that is currently done
292
+ (e.g. continuation will redo the access).
293
+
294
+ The CPUs supporting that declare their capability by overriding the
295
+ method ``cpu_is_interruptible `` to return true.
296
+
297
+ Three intermediate contention handlers can be added to accesses:
298
+
299
+ * ``before_delay ``: wait a number of cycles before doing the access.
300
+ * ``after_delay ``: wait a number of cycles after doing the access.
301
+ * ``before_time ``: wait for a given time before doing the access.
302
+
303
+ For the delay handlers, a method or lambda is called which returns the
304
+ number of cycles to wait (as a u32).
305
+
306
+ The ``before_time `` is special. First, the time is compared to the
307
+ current value of cpu->total_cycles(). That value is the number of
308
+ cycles elapsed since the last reset of the cpu. It is passed as a
309
+ parameter to the method as a u64 and must return the earliest time as
310
+ a u64 when the access can be done, which can be equal to the passed-in
311
+ time. From there two things can happen: either the running cpu has
312
+ enough cycles left to consume to reach that time. In that case, the
313
+ necessary number of cycles is consumed, and the access is done.
314
+ Otherwise, when there isn't enough, the remaining cycles are consumed,
315
+ the access aborted, scheduling happens, and eventually the access is
316
+ redone. In that case the method is called again with the new current
317
+ time, and must return the (probably same) earliest time again. This
318
+ will happen until enough cycles to consume are available to directly
319
+ do the access.
320
+
321
+ This approach allows to for instance handle consecutive DMAs. A first
322
+ DMA grabs the bus for a transfer. This shows up as the method
323
+ answering for the earliest time for access the time of the end of the
324
+ dma. If no timer happens until that time the access will then happen
325
+ just after the dma finishes. But if a timer elapses before that and
326
+ as a consequence another dma is queued while the first is running, the
327
+ cycle will be aborted for lack of remaining time, and the method will
328
+ eventually be called again. It will then give the time of when the
329
+ second dma will finish, and all will be well.
330
+
331
+ It can also allow to reduce said earlier time when circonstances
332
+ require it. For instance a PIO latch that waits up to 64 cycles that
333
+ data arrives can indicate that current time + 64 as a target (which
334
+ will trigger a bus error for instance) but if a timer elapses and
335
+ fills the latch meanwhile the method will be called again and that
336
+ time can just return the current time to let the access pass though.
337
+ Beware that if the timer elapsing did not fill the latch then the
338
+ method must return the time it returned previously, e.g. the initial
339
+ access time + 64, otherwise irrelevant timers happening or simply
340
+ scheduling quantum effects will delay the timeout, possibly to
341
+ infinity if the quantum is small enough.
342
+
343
+ Contention handlers on the same address are taken into account in the
344
+ ``before_time ``, ``before_delay `` then ``after_delay `` order.
345
+ Contention handlers of the same type on the same address at
346
+ last-one-wins. Installing any non-contention handler on a range where
347
+ a contention handler was removes it.
348
+
349
+
279
350
4. Address maps API
280
351
-------------------
281
352
@@ -292,13 +363,14 @@ The general syntax for entries uses method chaining:
292
363
293
364
.. code-block :: C++
294
365
295
- map(start, end).handler(...).handler_qualifier(...).range_qualifier();
366
+ map(start, end).handler(...).handler_qualifier(...).range_qualifier().contention() ;
296
367
297
368
The values start and end define the range, the handler() block
298
369
determines how the access is handled, the handler_qualifier() block
299
- specifies some aspects of the handler (memory sharing for instance) and
300
- the range_qualifier() block refines the range (mirroring, masking, lane
301
- selection, etc.).
370
+ specifies some aspects of the handler (memory sharing for instance)
371
+ and the range_qualifier() block refines the range (mirroring, masking,
372
+ lane selection, etc.). The contention methods handle bus contention
373
+ and wait states for cpus supporting them.
302
374
303
375
The map follows a “last one wins” principle, where the handler specified
304
376
last is selected when multiple handlers match a given address.
@@ -607,7 +679,20 @@ behaviour. An example of use the i960 which marks burstable zones
607
679
that way (they have a specific hardware-level support).
608
680
609
681
610
- 4.5 View setup
682
+ 4.5 Contention
683
+ ~~~~~~~~~~~~~~
684
+
685
+ .. code-block :: C++
686
+
687
+ (...).before_time(method).(...)
688
+ (...).before_delay(method).(...)
689
+ (...).after_delay(method).(...)
690
+
691
+ These three methods allow to add the contention methods to a handler.
692
+ See section `3.5 `_. Multiple methods can be handler to one handler.
693
+
694
+
695
+ 4.6 View setup
611
696
~~~~~~~~~~~~~~
612
697
613
698
.. code-block :: C++
@@ -641,6 +726,7 @@ can be installed only once. A view can also be part of “what was there
641
726
before”.
642
727
643
728
729
+
644
730
5. Address space dynamic mapping API
645
731
------------------------------------
646
732
@@ -803,8 +889,32 @@ with an optional mirror and flags.
803
889
Install a device address with an address map in a space. The
804
890
``unitmask ``, ``cswidth `` and ``flags `` arguments are optional.
805
891
806
- 5.9 View installation
807
- ~~~~~~~~~~~~~~~~~~~~~
892
+ 5.9 Contention
893
+ ~~~~~~~~~~~~~~
894
+
895
+ .. code-block :: C++
896
+
897
+ using ws_time_delegate = device_delegate<u64 (offs_t, u64)>;
898
+ using ws_delay_delegate = device_delegate<u32 (offs_t)>;
899
+
900
+ space.install_read_before_time(addrstart, addrend, addrmirror, ws_time_delegate)
901
+ space.install_write_before_time(addrstart, addrend, addrmirror, ws_time_delegate)
902
+ space.install_readwrite_before_time(addrstart, addrend, addrmirror, ws_time_delegate)
903
+
904
+ space.install_read_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
905
+ space.install_write_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
906
+ space.install_readwrite_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
907
+
908
+ space.install_read_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
909
+ space.install_write_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
910
+ space.install_readwrite_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate)
911
+
912
+ Install a contention handler in the decode path. The addrmirror
913
+ parameter is optional.
914
+
915
+
916
+ 5.10 View installation
917
+ ~~~~~~~~~~~~~~~~~~~~~~
808
918
809
919
.. code-block :: C++
810
920
@@ -820,3 +930,35 @@ by indexing to call a dynamic mapping method on it.
820
930
821
931
A view can be installed into a variant of another view without issues,
822
932
with only the usual constraint of single installation.
933
+
934
+ 5.11 Taps
935
+ ~~~~~~~~~
936
+
937
+ .. code-block :: C++
938
+
939
+ using tap = std::function<void (offs_t offset, uNN &data, uNN mem_mask)
940
+
941
+ memory_passthrough_handler mph = space.install_read_tap(addrstart, addrend, name, read_tap, &mph);
942
+ memory_passthrough_handler mph = space.install_write_tap(addrstart, addrend, name, write_tap, &mph);
943
+ memory_passthrough_handler mph = space.install_readwrite_tap(addrstart, addrend, name, read_tap, write_tap, &mph);
944
+
945
+ mph.remove();
946
+
947
+ A tap is a method that is be called when a specific range of addresses
948
+ is accessed without overriding the actual access. Taps can change the
949
+ data passed around. A write tap happens before the access, and can
950
+ change the value to be written. A read tap happens after the access,
951
+ and can change the value returned.
952
+
953
+ Taps must be of the same width and alignement than the bus. Multiple
954
+ taps can act over the same addresses.
955
+
956
+ The ``memory_passthrough_handler `` object collates a number of taps
957
+ and allow to remove them all in one call. The ``mph `` parameter is
958
+ optional and a new one will be created if absent.
959
+
960
+ Taps are lost when a new handler is installed at the same addresses
961
+ (under the usual principle of last one wins). If they need to be
962
+ preserved, one should install a change notifier on the address space,
963
+ and remove + reinstall the taps when notified.
964
+
0 commit comments