123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849open!Core0(** Various functions that build a tree-structured circuit take an optional
[branching_factor] argument that controls the number of branches at each level of the
circuit. With [N] inputs and [branching_factor = 1] the depth is [N]. With
[branching_factor = 2] the the depth is [ceil_log2 N]. Similarly for
[branching_factor = X], the depth is given by [ceil_log_{X} N]. *)type'aoptional_branching_factor=?branching_factor:int(** default is 2 *)->'atype'awith_valid=('a,'a)with_valid2and('a,'b)with_valid2={valid:'a;value:'b}(** Types wrappers for vectors which differentiate their signedness.
Operator argument widths are more flexible as we know how to resize them. Results are
sized to avoid truncation. *)moduletypeTyped_math=sig(** Base signal or bits type *)typet(** Addition. Arguments are extended appropriately and result is 1 bit wider to avoid
truncation. *)val(+:):t->t->t(** Subtraction. Arguments are extended appropriately and result is 1 bit wider to avoid
truncation. *)val(-:):t->t->t(** Multiplication. *)val(*:):t->t->t(** {2 Comparison operations}
Arguments need not be the same width. *)val(<:):t->t->tval(>:):t->t->tval(<=:):t->t->tval(>=:):t->t->tval(==:):t->t->tval(<>:):t->t->t(** Resize argument to given width. Appropriate extension is performed. *)valresize:t->int->t(** Reduce the width of [t] to [width] bits. The result is [valid] if the [value] fits
within [width] bits. *)valtruncate:t->width:int->twith_validendmoduletypeFor_collection=sigtypettype'acollection(** [concat_msb ts] concatenates a list of signals - the msb of the head of the list
will become the msb of the result.
[let c = concat_msb [ a; b; c ] in ...]
[concat_msb] raises if [ts] is empty or if any [t] in [ts] is empty. *)valconcat_msb:tcollection->t(** Similar to [concat_msb] except the lsb of the head of the list will become the lsb
of the result. *)valconcat_lsb:tcollection->t(** convert signal to a list of bits with msb at head of list *)valbits_msb:t->tcollection(** convert signal to a list of bits with lsb at head of list *)valbits_lsb:t->tcollection(** Split signal into a list of signals with width equal to [part_width]. The least
significant bits are at the head of the returned list. If [exact] is [true] the
input signal width must be exactly divisable by [part_width]. When [exact] is
[false] and the input signal width is not exactly divisible by [part_width], the
last element will contains residual bits.
eg:
{v
split_lsb ~part_width:4 16b0001_0010_0011_0100 =
[ 4b0100; 4b0011; 4b0010; 4b0001 ]
split_lsb ~exact:false ~part_width:4 17b11_0001_0010_0011_0100 =
[ 4b0100; 4b0011; 4b0010; 4b0001; 2b11 ]
v} *)valsplit_lsb:?exact:bool->part_width:int->t->tcollection(** Like [split_lsb] except the most significant bits are at the head of the returned
list. Residual bits when [exact] is [false] goes to the last element of the list, so
in the general case [split_lsb] is not necessarily equivalent to
[split_msb |> List.rev]. *)valsplit_msb:?exact:bool->part_width:int->t->tcollection(** multiplexer.
[let m = mux sel inputs in ...]
Given [l] = [List.length inputs] and [w] = [width sel] the following conditions must
hold:
[l] <= [Int.pow 2 w], [l] >= 1
If [l] < [Int.pow 2 w], the last input is repeated.
All inputs provided must have the same width, which will in turn be equal to the
width of [m]. *)valmux:t->tcollection->t(** Same as [mux] except requires:
[l] = [Int.pow 2 w] *)valmux_strict:t->tcollection->tendmoduletypeGates=sigtypet[@@derivingsexp_of]include%templateEqual.S[@modelocal]withtypet:=t(** the empty signal *)valempty:tvalis_empty:t->bool(** returns the width of a signal *)valwidth:t->int(** creates a constant *)valof_constant:Constant.t->tvalto_constant:t->Constant.t(** concatenates a list of signals *)valconcat_msb:tlist->tvalgnd:tvalvdd:t(** select a range of bits *)valselect:t->high:int->low:int->t(** names a signal *)val(--):loc:[%call_pos]->t->string->t(** bitwise and *)val(&:):t->t->t(** bitwise or *)val(|:):t->t->t(** bitwise xor *)val(^:):t->t->t(** bitwise not *)val(~:):t->t(** create string from signal *)valto_string:t->stringend(** Type required to generate the full combinational API *)moduletypePrimitives=sigincludeGates(** multiplexer *)valmux:t->tlist->t(** addition *)val(+:):t->t->t(** subtraction *)val(-:):t->t->t(** unsigned multiplication *)val(*:):t->t->t(** signed multiplication *)val(*+):t->t->t(** equality *)val(==:):t->t->t(** less than *)val(<:):t->t->t(** match against explicit case values. *)valcases:default:t->t->(t*t)list->tend(** Constructors for combinational types. *)moduletypeConstructors=sig(** Type for implementing the combinational interface. *)typet(** logic 1 *)valvdd:t(** logic 0 *)valgnd:t(** create signal from a constant *)valof_constant:Constant.t->t(** convert binary string to constant *)valof_bit_string:string->t(** Convert integer to constant. Negative values are sign extended up to [width]. Input
values which are larger or smaller than those representable in [width] bits are
truncated. *)valof_int_trunc:width:int->int->tvalof_int32_trunc:width:int->int32->tvalof_int64_trunc:width:int->int64->t(** Same as [of_int_trunc] *)valof_int:width:int->int->t[@@deprecated"[since 2024-11] use [of_int_trunc]"]valof_int32:width:int->int32->t[@@deprecated"[since 2024-11] use [of_int32_trunc]"]valof_int64:width:int->int64->t[@@deprecated"[since 2024-11] use [of_int64_trunc]"](** Convert non-negative values to constant. Input values which are not representable in
[width] bits will raise. *)valof_unsigned_int:width:int->int->tvalof_unsigned_int32:width:int->int32->tvalof_unsigned_int64:width:int->int64->tvalof_unsigned_bigint:width:int->Bigint.t->t(** Convert signed values to constant. Input values which are not representable in
[width] bits will raise. *)valof_signed_int:width:int->int->tvalof_signed_int32:width:int->int32->tvalof_signed_int64:width:int->int64->tvalof_signed_bigint:width:int->Bigint.t->t(** convert hex string to a constant. If the target width is greater than the hex length
and [signedness] is [Signed] then the result is sign extended. Otherwise the result
is zero padded. *)valof_hex:?signedness:Signedness.t(** default is [Unsigned] *)->width:int->string->t(** convert octal string to a constant. If the target width is greater than the octal
length and [signedness] is [Signed] then the result is sign extended. Otherwise the
result is zero padded. *)valof_octal:?signedness:Signedness.t(** default is [Unsigned] *)->width:int->string->t(** Convert an arbitrarily wide integer value to a constant. *)valof_bigint_trunc:width:int->Bigint.t->t(** convert verilog style or binary string to constant *)valof_string:string->t(** convert IntbitsList to constant *)valof_bit_list:intlist->tvalof_decimal_string:width:int->string->t(** convert a [char] to an 8 bit constant *)valof_char:char->t(** convert a [bool] to [vdd] or [gnd] *)valof_bool:bool->t(** convert a string to a series of 8-bit characters and concatenate them into a signal,
with the first character of the string being in the least-significant bits *)valof_ascii_string_lsb:string->t(** convert a string to a series of 8-bit characters and concatenate them into a signal,
with the first character of the string being in the most-significant bits *)valof_ascii_string_msb:string->t(** create random constant vector of given width *)valrandom:width:int->t(** [zero w] makes a the zero valued constant of width [w] *)valzero:int->t(** [ones w] makes a constant of all ones of width [w] *)valones:int->t(** [one w] makes a one valued constant of width [w] *)valone:int->tend(** Full combinational API *)moduletypeS=sigtypet[@@derivingsexp_of]include%templateEqual.S[@modelocal]withtypet:=tincludeConstructorswithtypet:=t(** the empty signal *)valempty:t(** returns true if the signal is empty *)valis_empty:t->bool(** names a signal
[let a = a -- "a" in ...]
signals may have multiple names. *)val(--):loc:[%call_pos]->t->string->t(** returns the width (number of bits) of a signal.
[let w = width s in ...] *)valwidth:t->int(** [addess_bits_for num_elements] returns the address width required to index
[num_elements].
It is the same as [Int.ceil_log2], except it wll return a minimum value of 1 (since
you cannot have 0 width vectors). Raises if [num_elements] is [< 0]. *)valaddress_bits_for:int->int(** [num_bits_to_represent x] returns the number of bits required to represent the
number [x], which should be [>= 0]. *)valnum_bits_to_represent:int->int(** convert the signal to a constant *)valto_constant:t->Constant.tmoduletypeFor_collection=For_collectionwithtypet:=tincludeFor_collectionwithtype'acollection:=tlist(** @inline *)moduleFor_array:For_collectionwithtype'acollection:='aarraymoduleFor_iarray:For_collectionwithtype'acollection:='aiarray(** concatenate two signals.
[let c = a @: b in ...]
equivalent to [concat [ a; b ]] *)val(@:):t->t->tvalis_vdd:t->bool[@@deprecated"[since 2025-03] use [to_bool]"]valis_gnd:t->bool[@@deprecated"[since 2025-03] use [not to_bool]"](** [select t ~high ~low] selects from [t] bits in the range [high]...[low], inclusive.
[select] raises unless [high] and [low] fall within [0 .. width t - 1] and
[high >= lo]. *)valselect:t->high:int->low:int->t(** select a single bit *)valbit:t->pos:int->t(** get most significant bit *)valmsb:t->t(** get least significant bits *)vallsbs:t->t(** get least significant bit *)vallsb:t->t(** get most significant bits *)valmsbs:t->t(** [drop_bottom s ~width] drop bottom [width] bits of [s] *)valdrop_bottom:t->width:int->t(** [drop_top s ~width] drop top [width] bits of [s] *)valdrop_top:t->width:int->t(** [sel_bottom s ~width] select bottom [width] bits of [s] *)valsel_bottom:t->width:int->t(** [sel_top s ~width] select top [width] bits of [s] *)valsel_top:t->width:int->t(* Verilog-like addressing operators. These operators are less verbose than the function
counterparts. See IEEE 1800 Syntax 11-5. *)(** [x.:[hi, lo]] == [select x hi lo] *)val(.:[]):t->int*int->t(** [x.:+[lo, width]] == [select x (lo + width - 1) lo]. If [width] is [None] it selects
all remaining msbs of the vector ie [x.:+[lo,None]] == [drop_bottom x lo] *)val(.:+[]):t->int*intoption->t(** [x.:-[hi, width]] == [select x hi (hi - width + 1)]. If [hi] is [None] it defaults
to the msb of the vector ie [x.:-[None, width]] == [sel_top x width] *)val(.:-[]):t->intoption*int->t(** [x.(i)] == [bit x i] *)val(.:()):t->int->t(** [insert ~into:t x ~at_offset] insert [x] into [t] at given offet *)valinsert:into:t->t->at_offset:int->t(** [mux2 c t f] 2 input multiplexer. Selects [t] if [c] is high otherwise [f].
[t] and [f] must have same width and [c] must be 1 bit.
Equivalent to [mux c [f; t]] *)valmux2:t->t->t->tvalmux_init:t->int->f:(int->t)->t(** [cases ~default select [(match0, value0); (match0, value0)...]] compares [select]
with [matchN] and outputs [valueN]. If nothing matches [default] is output. This
construct maps to a case statement.
The [matchN] values must be constants. *)valcases:default:t->t->(t*t)list->t(** logical and *)val(&:):t->t->tval(&:.):t->int->tval(&+.):t->int->t(** a <>:. 0 &: b <>:. 0 *)val(&&:):t->t->t(** logical or *)val(|:):t->t->tval(|:.):t->int->tval(|+.):t->int->t(** {v a <>:. 0 |: b <>:. 0 v} *)val(||:):t->t->t(** logic xor *)val(^:):t->t->tval(^:.):t->int->tval(^+.):t->int->t(** logical not *)val(~:):t->t(** addition *)val(+:):t->t->tval(+:.):t->int->tval(++.):t->int->t(** subtraction *)val(-:):t->t->tval(-:.):t->int->tval(-+.):t->int->t(** negation *)valnegate:t->t(** unsigned multiplication *)val(*:):t->t->t(** signed multiplication *)val(*+):t->t->t(** equality *)val(==:):t->t->tval(==:.):t->int->tval(==+.):t->int->t(** inequality *)val(<>:):t->t->tval(<>:.):t->int->tval(<>+.):t->int->t(** less than *)val(<:):t->t->tval(<:.):t->int->t(* added due to clash with camlp5 *)vallt:t->t->t(** greater than *)val(>:):t->t->tval(>:.):t->int->t(** less than or equal to *)val(<=:):t->t->tval(<=:.):t->int->t(** greater than or equal to *)val(>=:):t->t->tval(>=:.):t->int->t(** signed less than *)val(<+):t->t->tval(<+.):t->int->t(** signed greater than *)val(>+):t->t->tval(>+.):t->int->t(** signed less than or equal to *)val(<=+):t->t->tval(<=+.):t->int->t(** signed greated than or equal to *)val(>=+):t->t->tval(>=+.):t->int->t(** Propositional logic implication operator *)val(-->:):t->t->t(** create string from signal *)valto_string:t->string(** [to_int t] treats [t] as unsigned and resizes it to fit exactly within an OCaml
[Int.t].
- If [width t > Int.num_bits] then the upper bits are truncated.
- If [width t >= Int.num_bits] and [bit t (Int.num_bits-1) = vdd] (i.e. the msb of
the resulting [Int.t] is set), then the result is negative.
- If [t] is [Signal.t] and not a constant value, an exception is raised. *)valto_int_trunc:t->intvalto_int32_trunc:t->int32valto_int64_trunc:t->int64(** Same as [to_int_trunc]. *)valto_int:t->int[@@deprecated"[since 2024-11] use [to_int_trunc]"]valto_int32:t->int32[@@deprecated"[since 2024-11] use [to_int32_trunc]"]valto_int64:t->int64[@@deprecated"[since 2024-11] use [to_int64_trunc]"](** [to_signed_int t] treats [t] as signed and resizes it to fit exactly within an OCaml
[Int.t].
- An exception is raised if the value cannot fit in the resulting int.
- If [t] is [Signal.t] and not a constant value, an exception is raised. *)valto_signed_int:t->intvalto_signed_int32:t->int32valto_signed_int64:t->int64(** [to_unsigned_int t] treats [t] as unsigned and resizes it to fit exactly within an
OCaml [Int.t].
- An exception is raised if the value cannot fit in the resulting int.
- The value [int] value must be unsigned (so the max width is [Int.num_bits - 1]).
- If [t] is [Signal.t] and not a constant value, an exception is raised. *)valto_unsigned_int:t->intvalto_unsigned_int32:t->int32valto_unsigned_int64:t->int64(** Convert signal to a [bool]. The signal must be 1 bit wide. *)valto_bool:t->bool(** Convert signal to a [char]. The signal must be 8 bits wide. *)valto_char:t->char(** Convert into a string, with the first character being from the least-significant
bits of the signal. The signal width must be a multiple of 8 bits. *)valto_ascii_string_lsb:t->string(** Convert into a string, with the first character being from the most-significant bits
of the signal. The signal width must be a multiple of 8 bits. *)valto_ascii_string_msb:t->string(** create binary string from signal *)valto_bstr:t->string(** Convert bits to a Zarith.t *)valto_bigint:t->signedness:Signedness.t->Bigint.t(** convert signal to a list of bits with msb at head of list *)valbits_msb:t->tlist(** convert signal to a list of bits with lsb at head of list *)valbits_lsb:t->tlist(** repeat signal [count] times *)valrepeat:t->count:int->t(** Split signal in half. The most significant bits will be in the left half of the
returned tuple.
- If [msbs] is not provided, the signal will be split in half with the MSB part
possibly containing one more bit.
- If [msbs] is provided, [msbs] most significant bits will be split off. *)valsplit_in_half_msb:?msbs:int->t->t*t(** Same as [split_in_half_msb], but
- If [lsbs] is not provided, the LSB part might have one more bit.
- If [lsbs] is provided, [lsbs] least significant bits will be split off.
The most significant bits will still be in the left half of the tuple. *)valsplit_in_half_lsb:?lsbs:int->t->t*tvalbswap:t->t(** shift left logical *)valsll:t->by:int->t(** shift right logical *)valsrl:t->by:int->t(** shift right arithmetic *)valsra:t->by:int->t(** rotate left *)valrotl:t->by:int->t(** rotate right *)valrotr:t->by:int->t(** shift by variable amount *)vallog_shift:f:(t->by:int->t)->t->by:t->t(** [uresize t ~width:w] returns the unsigned resize of [t] to width [w]. If
[w = width t], this is a no-op. If [w < width t], this [select]s the [w] low bits of
[t]. If [w > width t], this extends [t] with [zero (w - width t)]. *)valuresize:t->width:int->t(** [sresize t ~width:w] returns the signed resize of [t] to width [w]. If
[w = width t], this is a no-op. If [w < width t], this [select]s the [w] low bits of
[t]. If [w > width t], this extends [t] with [w - width t] copies of [msb t]. *)valsresize:t->width:int->t(** [uextend t ~width:w] behaves similarly to [uresize t ~width:w] but asserts that
[w >= width] to prevent inadvertently chopping the signal. *)valuextend:t->width:int->t(** [sextend t ~width:w] behaves similarly to [sresize t ~width:w] but asserts that
[w >= width] to prevent inadvertently chopping the signal. *)valsextend:t->width:int->t(** unsigned resize by +1 bit *)value:t->t(** signed resize by +1 bit *)valse:t->t(** [resize_list ~resize l] finds the maximum width in [l] and applies [resize el max]
to each element. *)valresize_list:resize:(t->int->t)->tlist->tlist(** [resize_op2 ~resize f a b] applies [resize x w] to [a] and [b] where [w] is the
maximum of their widths. It then returns [f a b] *)valresize_op2:resize:(t->int->t)->(t->t->t)->t->t->t(** fold 'op' though list *)valreduce:f:('a->'a->'a)->'alist->'a(** reverse bits *)valreverse:t->t(** [mod_counter max t] is [if t = max then 0 else (t + 1)], and can be used to count
from 0 to [max] then from zero again. If [max == (1<<n - 1)], then a comparator is
not generated and overflow arithmetic is used instead. *)valmod_counter:max:int->t->t(** [compute_arity ~steps num_values] computes the tree arity required to reduce
[num_values] in [steps]. [steps<=0] raises. *)valcompute_arity:steps:int->int->int(** [compute_tree_branches ~steps num_values] returns a list of length [steps] of
branching factors required to reduce [num_values]. This tends to produce a slightly
more balanced sequence than just applying [compute_arity] at every step. *)valcompute_tree_branches:steps:int->int->intlist(** [tree ~arity ~f input] creates a tree of operations. The arity of the operator is
configurable. [tree] raises if [input = []]. *)valtree:arity:int->f:('alist->'a)->'alist->'a(** [priority_select cases] returns the value associated with the first case whose
[valid] signal is high. [valid] will be set low in the returned [with_valid] if no
case is selected. *)valpriority_select:(twith_validlist->twith_valid)optional_branching_factor(** Same as [priority_select] except returns [default] if no case matches. *)valpriority_select_with_default:(twith_validlist->default:t->t)optional_branching_factor(** Select a case where one and only one [valid] signal is enabled. If more than one
case is [valid] then the return value is undefined. If no cases are valid, [0] is
returned by the current implementation, though this should not be relied upon. *)valonehot_select:(twith_validlist->t)optional_branching_factor(** [popcount t] returns the number of bits set in [t]. *)valpopcount:(t->t)optional_branching_factor(** [binary_to_byte_qualifier ~num_bytes t] returns a byte qualifier encoding of a
binary size for use when encoding contiguous byte enables or byte keep signals. *)valbinary_to_byte_qualifier:num_bytes:int->t->t(** [is_pow2 t] returns a bit to indicate if [t] is a power of 2. *)valis_pow2:(t->t)optional_branching_factor(** [leading_ones t] returns the number of consecutive [1]s from the most significant
bit of [t] down. *)valleading_ones:(t->t)optional_branching_factor(** [trailing_ones t] returns the number of consecutive [1]s from the least significant
bit of [t] up. *)valtrailing_ones:(t->t)optional_branching_factor(** [leading_zeros t] returns the number of consecutive [0]s from the most significant
bit of [t] down. *)valleading_zeros:(t->t)optional_branching_factor(** [trailing_zeros t] returns the number of consecutive [0]s from the least significant
bit of [t] up. *)valtrailing_zeros:(t->t)optional_branching_factor(** [floor_log2 x] returns the floor of log-base-2 of [x]. [x] is treated as unsigned
and an error is indicated by [valid = gnd] in the return value if [x = 0]. *)valfloor_log2:(t->twith_valid)optional_branching_factor(** [ceil_log2 x] returns the ceiling of log-base-2 of [x]. [x] is treated as unsigned
and an error is indicated by [valid = gnd] in the return value if [x = 0]. *)valceil_log2:(t->twith_valid)optional_branching_factor(** convert binary to onehot *)valbinary_to_onehot:t->t(** convert onehot to binary *)valonehot_to_binary:t->t(** convert binary to gray code *)valbinary_to_gray:t->t(** convert gray code to binary *)valgray_to_binary:t->t(** Increment a gray code value. The implementation converts to binary, increments the
binary value, then converts back to gray code. *)valgray_increment:t->by:int->t(** [any_bit_set t] returns [vdd] if at least one bit if set in [t] and [gnd] otherwise. *)valany_bit_set:t->t(** [all_bits_set t] returns [vdd] if all bits in [t] are set and [gnd] otherwise. *)valall_bits_set:t->t(** [no_bits_set t] returns [vdd] if no bits in [t] are set and [gnd] otherwise. *)valno_bits_set:t->t(** Increment (defaults to 1). Wrap on overflow. *)valincr:?by:int->t->t(** Decrement (defaults to 1). Wrap on overflow. *)valdecr:?by:int->t->t(** Concatention, selection and resizing functions for signals encoded as an option
where [None] means zero width. *)moduleWith_zero_width:sigtypenon_zero_width=t[@@derivingsexp_of]typet=non_zero_widthoption[@@derivingsexp_of]valof_non_zero_width:non_zero_width->tvalto_non_zero_width:?default:non_zero_width->t->non_zero_widthvalzero_width:tvalzero:int->tvalone:int->tvalones:int->tvalconcat_msb:tlist->tvalconcat_lsb:tlist->tvalselect:t->high:int->low:int->tvallsbs:t->tvalmsbs:t->tvaldrop_bottom:t->width:int->tvaldrop_top:t->width:int->tvalsel_bottom:t->width:int->tvalsel_top:t->width:int->tvalrepeat:t->count:int->tvalsplit_in_half_msb:?msbs:int->t->t*tvalsplit_in_half_lsb:?lsbs:int->t->t*tvalmux:t->non_zero_widthlist->non_zero_widthendmoduletypeTyped_math=Typed_mathwithtypet:=t(** Unsigned vector operations (ie may operate on [Bits.t] or [Signal.t] directly). *)moduleUnsigned:Typed_math(** Signed vector operations (ie may operate on [Bits.t] or [Signal.t] directly). *)moduleSigned:Typed_mathvaltype_equal_id:tType_equal.Id.tendmoduletypeGen_cases_from_mux=sigtypetvalmux:t->tlist->tval(==:):t->t->tendmoduletypeComb=sigmoduletypeGates=GatesmoduletypePrimitives=PrimitivesmoduletypeS=Stypenonrec'aoptional_branching_factor='aoptional_branching_factortypenonrec('a,'b)with_valid2=('a,'b)with_valid2={valid:'a;value:'b}typenonrec'awith_valid=('a,'a)with_valid2moduleMake_primitives(Gates:Gates):Primitiveswithtypet=Gates.t(** Generates the full combinational API *)moduleMake(Primitives:Primitives):Swithtypet=Primitives.tmoduleExpert:sig(** Generate the implementation of [cases] based on equality and muxs. *)moduleGen_cases_from_mux(Comb:Gen_cases_from_mux):sigopenCombvalcases:default:t->t->(t*t)list->tendendend