123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618open!Import(** 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 by [ceil_log_{X} N]. *)type'aoptional_branching_factor=?branching_factor:int(** default is 2 *)->'amoduletypeTypedMath=sigtypettypevvalof_signal:t->vvalto_signal:v->tval(+:):v->v->vval(-:):v->v->vval(*:):v->v->vval(<:):v->v->vval(>:):v->v->vval(<=:):v->v->vval(>=:):v->v->vval(==:):v->v->vval(<>:):v->v->vvalresize:v->int->vendmoduletypeGates=sigtypet[@@derivingsexp_of]includeEqual.Swithtypet:=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->t(** select a range of bits *)valselect:t->int->int->t(** names a signal *)val(--):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->tend(** Full combinational API *)moduletypeS=sigtypet[@@derivingsexp_of]includeEqual.Swithtypet:=t(** the empty signal *)valempty:tvalis_empty:t->bool(** names a signal
[let a = a -- "a" in ...]
signals may have multiple names. *)val(--):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->intvalof_constant:Constant.t->tvalto_constant:t->Constant.t(** convert binary string to constant *)valconstb:string->tvalof_bit_string:string->t(** convert integer to constant *)valof_int:width:int->int->tvalof_int32:width:int->int32->tvalof_int64:width:int->int64->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:Constant.Signedness.t(** default is [Unsigned] *)->width:int->string->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->tvalconstv:string->t[@@deprecated"[since 2019-11] constv]"]valconsti:width:int->int->t[@@deprecated"[since 2019-11] consti]"]valconsti32:width:int->int32->t[@@deprecated"[since 2019-11] consti32]"]valconsti64:width:int->int64->t[@@deprecated"[since 2019-11] consti64]"]valconstibl:intlist->t[@@deprecated"[since 2019-11] constibl]"]valconsthu:width:int->string->t[@@deprecated"[since 2019-11] consthu]"]valconsths:width:int->string->t[@@deprecated"[since 2019-11] consths]"]valconst:string->t[@@deprecated"[since 2019-11] const"]valconstd:width:int->string->t[@@deprecated"[since 2019-11] constd]"](** [concat ts] concatenates a list of signals - the msb of the head of the list will
become the msb of the result.
[let c = concat \[ a; b; c \] in ...]
[concat] raises if [ts] is empty or if any [t] in [ts] is empty. *)valconcat_msb:tlist->t(** Similar to [concat_msb] except the lsb of the head of the list will become the lsb
of the result. *)valconcat_lsb:tlist->t(** same as [concat_msb] except empty signals are first filtered out *)valconcat_msb_e:tlist->t(** same as [concat_lsb] except empty signals are first filtered out *)valconcat_lsb_e:tlist->t(** concatenate two signals.
[let c = a @: b in ...]
equivalent to [concat \[ a; b \]] *)val(@:):t->t->t(** logic 1 *)valvdd:tvalis_vdd:t->bool(** logic 0 *)valgnd:tvalis_gnd:t->bool(** [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->t(** [select t hi lo] selects from [t] bits in the range [hi]...[lo], inclusive.
[select] raises unless [hi] and [lo] fall within [0 .. width t - 1] and [hi >=
lo]. *)valselect:t->int->int->t(** same as [select] except invalid indices return [empty] *)valselect_e:t->int->int->t(** select a single bit *)valbit:t->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 n] drop bottom [n] bits of [s] *)valdrop_bottom:t->int->t(** [drop_top s n] drop top [n] bits of [s] *)valdrop_top:t->int->t(** [sel_bottom s n] select bottom [n] bits of [s] *)valsel_bottom:t->int->t(** [sel_top s n] select top [n] bits of [s] *)valsel_top:t->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(** multiplexer.
[let m = mux sel inputs in ...]
Given [l] = [List.length inputs] and [w] = [width sel] the following conditions must
hold.
[l] <= 2**[w], [l] >= 2
If [l] < 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->tlist->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(** logical and *)val(&:):t->t->tval(&:.):t->int->t(** a <>:. 0 &: b <>:. 0 *)val(&&:):t->t->t(** logical or *)val(|:):t->t->tval(|:.):t->int->t(** a <>:. 0 |: b <>:. 0 *)val(||:):t->t->t(** logic xor *)val(^:):t->t->tval(^:.):t->int->t(** logical not *)val(~:):t->t(** addition *)val(+:):t->t->tval(+:.):t->int->t(** subtraction *)val(-:):t->t->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->t(** inequality *)val(<>:):t->t->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(** 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:t->int(** [to_sint t] treats [t] as signed and resizes it to fit exactly within an OCaml
[Int.t].
- If [width t > Int.num_bits] then the upper bits are truncated.
- If [t] is [Signal.t] and not a constant value, an exception is raised. *)valto_sint:t->intvalto_int32:t->int32valto_sint32:t->int32valto_int64:t->int64valto_sint64:t->int64(** Convert signal to a [char]. The signal must be 8 bits wide. *)valto_char:t->char(** create binary string from signal *)valto_bstr:t->string(** 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(** [to_array s] convert signal [s] to array of bits with lsb at index 0 *)valto_array:t->tarray(** [of_array a] convert array [a] of bits to signal with lsb at index 0 *)valof_array:tarray->t(** repeat signal n times *)valrepeat:t->int->t(** split signal in half. The most significant bits will be in the left half of the
returned tuple. *)valsplit_in_half_msb:t->t*t(** 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(** default is [true] **)->part_width:int->t->tlist(** 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(** default is [true] **)->part_width:int->t->tlistvalbswap:t->t(** shift left logical *)valsll:t->int->t(** shift right logical *)valsrl:t->int->t(** shift right arithmetic *)valsra:t->int->t(** rotate left *)valrotl:t->int->t(** rotate right *)valrotr:t->int->t(** shift by variable amount *)vallog_shift:(t->int->t)->t->t->t(** [uresize t 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 (width t - w)]. *)valuresize:t->int->t(** [sresize t 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 [width t - w] copies of [msb t]. *)valsresize:t->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-1) then from zero again. If max == 1<<n, then a comparator is not
generated and overflow arithmetic used instead. If *)valmod_counter:max:int->t->t(** [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.t] if
no case is selected. *)valpriority_select:(tWith_valid.tlist->tWith_valid.t)optional_branching_factor(** Same as [priority_select] except returns [default] if no case matches. *)valpriority_select_with_default:(tWith_valid.tlist->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_valid.tlist->t)optional_branching_factor(** [popcount t] returns the number of bits set in [t]. *)valpopcount:(t->t)optional_branching_factor(** [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.t)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.t)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(** create random constant vector of given width *)valrandom:width:int->tmoduletypeTypedMath=TypedMathwithtypet:=t(* General arithmetic on unsigned signals. Operands and results are resized
to fit as appropriate. *)moduleUnsigned:TypedMath(* General arithmetic on signed signals. Operands and results are resized to fit as
appropriate. *)moduleSigned:TypedMath(** Unsigned operations compatible with type t *)moduleUop:TypedMathwithtypev:=t(** Signed operations compatible with type t *)moduleSop:TypedMathwithtypev:=tendmoduletypeComb=sigmoduletypeGates=GatesmoduletypePrimitives=PrimitivesmoduletypeS=Stypenonrec'aoptional_branching_factor='aoptional_branching_factormoduleMake_primitives(Gates:Gates):Primitiveswithtypet=Gates.t(** Generates the full combinational API *)moduleMake(Primitives:Primitives):Swithtypet=Primitives.tend