123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408open!Core0moduletypeNames=sigtypet(** Returns the list of names and locations assigned to the signal. *)valnames_and_locs:t->Name_and_loc.tlist(** Returns the list of names assigned to the signal. *)valnames:t->stringlist(** Set the given names on the signal. Wipes any names currently set. *)valset_names:t->Name_and_loc.tlist->unit(** Reset any names for global signals. *)valreset_names:unit->unitendmoduletypeAttributes=sigtypet(** Add an attribute to node. *)valadd_attribute:t->Rtl_attribute.t->t(** Returns attributes associated to the signal. *)valattributes:t->Rtl_attribute.tlist(** Set the format used to display the signal *)valset_wave_format:t->Wave_format.t->unitval(--$):t->Wave_format.t->tendmoduletypeComments=sigtypet(** Set the comment associated with the signal. This is currently only supported in
Verilog. *)valset_comment:t->string->t(** Remove the comment associated with the signal. This is currently only supported in
Verilog. *)valunset_comment:t->t(** Returns comment associated with the signal. *)valcomment:t->stringoptionendmoduletypeCoverage=sigopenCoverage_primtypet(** Attach a waiver for mux coverage. Raises if the signal is not a mux. *)valadd_mux_waiver_exn:t->intWaiver.t->t(** Attach a waiver for cases coverage. Raises if the signal is not a cases signal. *)valadd_cases_waiver_exn:t->Case.tWaiver.t->t(** Attach a waiver for register coverage. Raises if the signal is not a register or it
is an always state register. *)valadd_register_waiver_exn:t->Toggle.tWaiver.t->t(** Attach a state waiver to an always state register. Raises if the signal is not an
always state register. *)valadd_always_state_waiver_exn:t->stringWaiver.t->t(** Attach as transition wavier to an always state register. Raises if the signal is not
an always state register. *)valadd_always_state_transition_waiver_exn:t->stringTransition.tWaiver.t->tendmoduletypePorts=sigtypet(** Creates an input. *)valinput:string->int->t(** Creates an output. *)valoutput:string->t->tendmoduletypeWires=sigtypet(** Creates an unassigned wire. *)valwire:int->t(** Creates an assigned wire. *)valwireof:t->t(** Assigns to wire. *)val(<--):t->t->unitvalassign:t->t->unitendmoduletypeLogic=sigtypettypeinfo(** Combinational logic API with constant propogation optimizations. *)includeComb.Swithtypet:=t(** Combinational logic API without constant propogation optimizations. *)moduleUnoptimized:Comb.Swithtypet:=t(** Create the signal from bits. *)valof_bits:Bits.t->t(** Convert the signal to bits. Raises if the signal is not a constant. *)valto_bits:t->Bits.tendmoduletypeRegs=sigtypetmoduleReg_spec:Reg_spec.Swithtypesignal:=ttype'awith_register_spec=?enable:t->?initialize_to:Bits.t->?reset_to:Bits.t->?clear:t->?clear_to:t->Reg_spec.t->'avalreg:(t->t)with_register_specvalreg_fb:(width:int->f:(t->t)->t)with_register_spec(** Like {!reg_fb} but returns both the registered value and the next cycle's value
(i.e. the output of [f prev_value]). The next value ignores [clear] or [reset] if
applied, i.e. if [clear] is applied, next will still be [f prev_value] rather than
[clear_to]. *)valreg_fb_and_next:(width:int->f:(t->t)->t*t)with_register_spec(** Pipeline a signal [n] times with the given register specification. If set, a list of
RTL attributes will also be applied to each register created. *)valpipeline:?attributes:Rtl_attribute.tlist->(n:int->t->t)with_register_spec(** A register which forwards its input value to the output during cycles in which it is
enabled.
Implemented as a register with a mux on the output. Note that the cut through
bevahiour will also occur if enable is high during a clear (or even reset)
operation. *)valcut_through_reg:?initialize_to:Bits.t->?reset_to:Bits.t->?clear:t->?clear_to:t->Reg_spec.t->enable:t->t->t(** [Staged.unstage (prev spec ?enable d)] returns a function [prev n] which provides
[d] registered [n] times (ie the value of [d] [n] cycles in the past). [n=0] means
the current (combinational value).
The internal registers are shared between calls. When called multiple times with a
maximum value of [n] exactly [n] registers are created. *)valprev:(t->(int->t)Staged.t)with_register_spec(** Basic counter. Adds [by] on each [enabled] cycle. Wraps on over/underflow. *)valcounter:?enable:t->?initialize_to:Bits.t->?reset_to:Bits.t->?clear:t->?clear_to:t->?by:int(** Default is [1] *)->Reg_spec.t->width:int->tendmoduletypeMemory_prim=sigtypet(** Underlying function for constructing various memory primitives. Should not be used
by client code. Instead, use the functions defined in [Memories]. *)valmultiport_memory_prim:?name:string->?attributes:Rtl_attribute.tlist->?initialize_to:Bits.tarray->int->remove_unused_write_ports:bool->data_width:int->write_ports:tWrite_port.tarray->read_addresses:tarray->tarrayendmoduletypeMemories=sigtypet(** Synchronous write / asynchronous read memory. Supports an arbitrary number of
[read_addresses] and [write_ports]. Placement of registers on the address or data
output will allow synthesizers to infer RAMs from generated RTL (see also
[Ram.create] which builds on this primitive to implement inferred memories).
Any provided attributes are applied to the memory array itself.
The memory may be initialized by providing [initialize_to].
[enable_modelling_features] allows multibit enable and port scaling features. In
both cases they will generate valid synthesizable RTL but backend tool inference is
unlikely to work leading to sub-optimal designs.
In both cases extra read/write ports are generated and the internal RAM may be
narrowed to support the feature.
For multibit enables the number of write enables must evenly divide the write data
width or an exception will be raised.
For port scaling the read/write port ratio must be a power of two. It is specified
by making the read and write address widths different and scaling the write data
width appropriately. The [size] and [initialize_to] parameters are specified
relative to the write port with the widest data bus. *)valmultiport_memory:?enable_modelling_features:bool->?verbose:bool->?name:string->?attributes:Rtl_attribute.tlist->?initialize_to:Bits.tarray->int->write_ports:tWrite_port.tarray->read_addresses:tarray->tarray(** A multi-read port asynchronous ROM built from a memory primitive. This can be used
to map ROMs into RAM resources by registering the output. *)valrom:read_addresses:tarray->Bits.tarray->tarrayvalmemory:?attributes:Rtl_attribute.tlist->int->write_port:tWrite_port.t->read_address:t->tvalram_wbr:?name:string->?attributes:Rtl_attribute.tlist->write_port:tWrite_port.t->read_port:tRead_port.t->int->tvalram_rbw:?name:string->?attributes:Rtl_attribute.tlist->write_port:tWrite_port.t->read_port:tRead_port.t->int->tendmoduletypeUnderlying_representation=sigtypettypeinfo(** Return the underlying representation for the signal. *)valto_rep:t->Signal__type.t*info(** Construct a signal from the underlying representation and the information tracked by
this signal. *)valfrom_rep:Signal__type.t->info->t(** Update the information attached to this signal. *)valupdate_rep:t->info:info->tendmoduletypeS=sig(** Signal type for constructing logic designs. *)typetincludeSignal__type.With_infowithtypet:=t(** {1 Naming}
One or more string names applied to a signal. These will be used during RTL code
generation and simulation to aid design inspection. *)includeNameswithtypet:=t(** {1 Attributes}
Attributes are attached to signals and written during RTL generation. They can be
used to control downstream synthesis and place and route tools. They do not
otherwise affect the Hardcaml circuit. *)includeAttributeswithtypet:=t(** {1 Comments}
A comment can be associated with a signal, and this is sometimes useful to pass
information to downstream tooling (specifically Verilator). *)includeCommentswithtypet:=tincludeCoveragewithtypet:=t(** {1 Circuit Input and Output Ports}
Specification of the module level input and output ports. Ports are represented in
Hardcaml as wires with a single name. Note that Hardcaml will generally rewrite and
legalize names depending on context but will not do so for ports. *)includePortswithtypet:=t(** {1 Wires}
Wires are used in Hardcaml to conenct two signals together. They are first created
then assigned to (internally they have a mutable reference to their driver). Wires
are how we can create cycles which we require in order to build logic like, for
example, a counter.
It is entirely possible to create combinational loops using wires. Often this is not
the intent and Hardcaml has functions to detect this - for example, Cyclesim will
fail if there is such a loop. *)includeWireswithtypet:=t(** {1 Combinational Logic}
The main combinational logic API for creating things like adders, multiplexers etc.
This API is the same as provided by [Bits.t].
By default Hardcaml performs constant propogation over signals - operations with
purely constant values (and some other simple cases such as [a &: vdd]) will be
simplified. You can avoid this by using the operations from the [Unoptimized]
module. *)includeLogicwithtypet:=tandtypeinfo:=info(** {1 Registers}
Registers are configured using a [Reg_spec.t]. This encodes the clock, synchronous
clear, and asychronous reset used. *)includeRegswithtypet:=t(** {1 Memories}
[multiport_memory] provides the low-level primitive from which Hardcaml memories are
created. It provides a memory with an arbitrary number of read and write ports that
is asychronously read.
By default synthesizers will infer either LUT ram or register banks from this
primitive.
Limiting the number of read/write ports and placing a register on the read address
or read output port will allow synthesizers to infer single or simple dual port RAM
from RTL. [ram_rbw] and [ram_wbr] are examples of this. *)includeMemorieswithtypet:=t(** {1 Signal representations}
Operate on the underlying representation of the signal type. This is useful if you
need to operate on the underlying [Signal.Type] that represents the [Signal.S] that
you are working with or to reflect on the extra information attached to the specific
[Signal.S] (like clock domains for [Clocked.t]). *)includeUnderlying_representationwithtypet:=tandtypeinfo:=info(** Pretty printer. *)valpp:Formatter.t->t->unit(**/**)(*_ Apply a name to a signal using the hardcaml ppx [%hw] extension *)val__ppx_auto_name:loc:[%call_pos]->t->string->tmoduleExpert:sig(*_ Exported for internal use. *)includeMemory_primwithtypet:=t(*_ Same as [reg] but with a signal argument for [reset_to]. This is used in some old
downstream libraries, and we recommend using the normal [reg] function so that
resets are generally driven by a constant value. *)valreg__with_signal_reset:?enable:t->?initialize_to:Bits.t->?reset_to:t->?clear:t->?clear_to:t->Reg_spec.t->t->tendendmoduletypeSignal=sigtypet=Signal__type.tmoduletypeS=SmoduleType=Signal__typeincludeSwithtypet:=Signal__type.t(** Returns the unique id of the signal. *)val%templateuid:t@m->Type.Uid.t@m[@@modem=(local,global)]end