Imperative.Cyclesiminclude Imperative.Smodule I_data : Digital_components.Data.S with type t = unitmodule O_data :
Digital_components.Data.S
with type t = unit Hardcaml_step_testbench_kernel.Before_and_after_edge.tmodule Handler : sig ... endval cycle :
Handler.t @ local ->
(?num_cycles:int ->
(unit ->
unit) @ local) @ localcycle i_data ~num_cycles waits for num_cycles cycles of the simulator to run. cycle raises if num_cycles < 1.
val start :
Handler.t @ local ->
((Handler.t @ local -> ('a -> 'b) @ local) ->
('a ->
('b, I_data.t)
Hardcaml_step_testbench_kernel.Step_effect.Component_finished.t) @ local) @ localtype ('a, 'i) finished_event =
('a, 'i) Hardcaml_step_testbench_kernel.Step_effect.Component_finished.t
Hardcaml_step_testbench_kernel.Step_effect.Event.tval spawn :
?period:int ->
Handler.t @ local ->
((Handler.t @ local -> (unit -> 'a) @ local) ->
('a, unit) finished_event) @ localLaunch a new task within the current simulation step.
val wait_for : Handler.t @ local -> (('a, 'i) finished_event -> 'a) @ localWait for the given event to occur, and extract its return value.
val wait_for_with_timeout :
Handler.t @ local ->
(('a, 'i) finished_event ->
(timeout_in_cycles:int ->
'a option) @ local) @ localLike wait_for except it stops waiting after timeout_in_cycles and returns None. Note that the spawned task continues to execute.
val forever :
Handler.t @ local ->
((Handler.t @ local -> (unit -> unit) @ local) ->
Core.never_returns) @ localRuns the given step function forever.
val run_monadic_computation :
Handler.t @ local ->
(('a, O_data.t, I_data.t) Hardcaml_step_testbench_kernel.Step_monad.t ->
'a) @ localmodule As_monad : sig ... endmodule Expert : sig ... endval run_with_timeout :
?update_children_after_finish:bool ->
?show_steps:bool ->
?timeout:int ->
unit ->
simulator:(_, _) Hardcaml.Cyclesim.t ->
testbench:(Handler.t @ local -> 'a) ->
'a optionRun the testbench until the main task finishes.
The optional timeout argument stops the simulation after the given number of steps and returns None. Otherwise it will continue until the testbech completes.
val run_with_timeout' :
?update_children_after_finish:bool ->
?show_steps:bool ->
?timeout:int ->
unit ->
simulator:('i, 'o) Hardcaml.Cyclesim.t ->
testbench:(Handler.t @ local -> (('i, 'o) Hardcaml.Cyclesim.t -> 'a) @ local) ->
'a optionIdentical to run_with_timeout, but the testbench function takes the simulator object. There is no semantical difference at all -- this is just a convenience function.
val run_until_finished :
?update_children_after_finish:bool ->
?show_steps:bool ->
unit ->
simulator:(_, _) Hardcaml.Cyclesim.t ->
testbench:(Handler.t @ local -> 'a) ->
'aRun the testbench until completion.
val wrap :
?show_steps:bool ->
when_to_evaluate_testbenches:[ `Before_cycle | `After_cycle ] ->
testbenches:(Handler.t @ local -> unit) list ->
('i, 'o) Hardcaml.Cyclesim.t ->
('i, 'o) Hardcaml.Cyclesim.twrap constructs a Sim.t instances such that calling Cyclesim.cycle sim will step the testbenches by one a cycle. The testbench will stop executing if it's completed, but the user will not receive any notification if this happens. The provided testbenches are executed sequentially.
Note that there is no safety gurantees on the main simulation loop and the testbenches accessing the ports. It's the programmer's responsibility to think about how the port access. For most use cases, it's expected that the testbenches and the main simulation loop should be modifying different input ports.
val wrap_never_returns :
?show_steps:bool ->
when_to_evaluate_testbenches:[ `Before_cycle | `After_cycle ] ->
testbenches:(Handler.t @ local -> Core.never_returns) list ->
('i, 'o) Hardcaml.Cyclesim.t ->
('i, 'o) Hardcaml.Cyclesim.tExactly the same as wrap, but accepts a never_returns testbench in the signature.