@@ -276,6 +276,77 @@ or the view can be disabled using the ``disable`` method. A disabled
276276view can be re-enabled at any time.
277277
278278
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+
2793504. Address maps API
280351-------------------
281352
@@ -292,13 +363,14 @@ The general syntax for entries uses method chaining:
292363
293364.. code-block :: C++
294365
295- map(start, end).handler(...).handler_qualifier(...).range_qualifier();
366+ map(start, end).handler(...).handler_qualifier(...).range_qualifier().contention() ;
296367
297368The values start and end define the range, the handler() block
298369determines 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.
302374
303375The map follows a “last one wins” principle, where the handler specified
304376last is selected when multiple handlers match a given address.
@@ -607,7 +679,20 @@ behaviour. An example of use the i960 which marks burstable zones
607679that way (they have a specific hardware-level support).
608680
609681
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
611696~~~~~~~~~~~~~~
612697
613698.. code-block :: C++
@@ -641,6 +726,7 @@ can be installed only once. A view can also be part of “what was there
641726before”.
642727
643728
729+
6447305. Address space dynamic mapping API
645731------------------------------------
646732
@@ -803,8 +889,32 @@ with an optional mirror and flags.
803889Install a device address with an address map in a space. The
804890``unitmask ``, ``cswidth `` and ``flags `` arguments are optional.
805891
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+ ~~~~~~~~~~~~~~~~~~~~~~
808918
809919.. code-block :: C++
810920
@@ -820,3 +930,35 @@ by indexing to call a dynamic mapping method on it.
820930
821931A view can be installed into a variant of another view without issues,
822932with 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