123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152open!ImportmoduletypeCyclesim=sigmodulePort_list:sigtypet=(string*Bits.tref)list[@@derivingsexp_of]end(** base type of the cycle based simulators *)type('i,'o)ttypet_port_list=(Port_list.t,Port_list.t)t(** Specialised signal dependencies that define a graph that breaks cycles through
sequential elements. This is done by removing the input edges of registers and
memories (excluding the read address, since hardcaml memories are read
asynchronously).
Instantiations do not allow cycles from output to input ports, which is a valid
assumption for the simulator, but not in general.
Note that all signals in the graph cannot be reached from just the outputs of a
circuit using these dependencies. The (discarded) inputs to all registers and
memories must also be included. *)valscheduling_deps:Signal.t->Signal.tlist(** advance by 1 clock cycle (check->comb->seq->comb) *)valcycle:_t->unit(** check inputs are valid before a simulation cycle *)valcycle_check:_t->unit(** update combinatorial logic before clock edge and relative to new inputs. *)valcycle_before_clock_edge:_t->unit(** update sequential logic - registers and memories. *)valcycle_at_clock_edge:_t->unit(** update combinatorial logic after clock edge *)valcycle_after_clock_edge:_t->unit(** reset simulator *)valreset:_t->unit(** get input port given a name *)valin_port:_t->string->Bits.tref(** Get output port given a name. If [clock_edge] is [Before] the outputs are computed
prior to the clock edge - [After] means the outputs are computed after the clock
edge. *)valout_port:?clock_edge:Side.t(** default is [After]. *)->_t->string->Bits.trefvalinputs:('i,_)t->'ivaloutputs:?clock_edge:Side.t->(_,'o)t->'ovalin_ports:_t->Port_list.tvalout_ports:?clock_edge:Side.t->_t->Port_list.t(** get list of internal nodes *)valinternal_ports:_t->Port_list.tvallookup_signal:_t->Signal.Uid.t->Bits.trefvallookup_reg:_t->Signal.Uid.t->Bits.treftype'awith_create_options=?is_internal_port:(Signal.t->bool)->?combinational_ops_database:Combinational_ops_database.t->'a(** construct a simulator from a circuit *)valcreate:(Circuit.t->t_port_list)with_create_optionsmoduleCombine_error:sigtypet={cycle_no:int;clock_edge:Side.t;port_name:string;value0:Bits.t;value1:Bits.t}[@@derivingsexp_of]end(** Combine 2 simulators. The inputs are set on the 1st simulator and copied to the
2nd. Outputs are checked and [on_error] is called if a difference is found. By
default, [on_error] raises.
The simulators should have the same input and output port sets, unless
[port_sets_may_differ] is [true], in which case only ports which exist on both
simulators are checked. *)valcombine:?port_sets_may_differ:bool(** Default is [false]. *)->?on_error:(Combine_error.t->unit)->('i,'o)t->('i,'o)t->('i,'o)tmoduleWith_interface(I:Interface.S)(O:Interface.S):sigtypenonrect=(Bits.trefI.t,Bits.trefO.t)t[@@derivingsexp_of](** Create a simulator using the provided [Create_fn]. The returned simulator ports
are coerced to the input and output interface types. *)valcreate:(?port_checks:Circuit.Port_checks.t->?add_phantom_inputs:bool->Circuit.With_interface(I)(O).create->t)with_create_optionsCircuit.with_create_options(** Coerce simulator port types to use the provided input and output interfaces. *)valcoerce:t_port_list->tendmodulePrivate:sigtypetask=unit->unitvalcreate:in_ports:Port_list.t->out_ports_before_clock_edge:Port_list.t->out_ports_after_clock_edge:Port_list.t->internal_ports:Port_list.t->reset:task->cycle_check:task->cycle_before_clock_edge:task->cycle_at_clock_edge:task->cycle_after_clock_edge:task->lookup_signal:(Signal.Uid.t->Bits.tref)->lookup_reg:(Signal.Uid.t->Bits.tref)->t_port_listmoduleStep:sigtypet=|Reset|Check|Before_clock_edge|At_clock_edge|After_clock_edge[@@derivingsexp_of]endvalmodify:('i,'o)t->(Side.t*Step.t*task)list->('i,'o)tvalcoerce:(Port_list.t,Port_list.t)t->to_input:(Port_list.t->'i)->to_output:(Port_list.t->'o)->('i,'o)tendend