BitSAD.CircuitModule
— TypeCircuitModule(fn; kwargs...)
A data structure to store information to generate hardware for fn
.
Hardware generation traverses dfg
and uses handlers
to generate Verilog strings.
Keywords:
name::Symbol
: the name of the module (defaults tonameof(fn)
)bitwidth::@NamedTuple{integral::Int, fractional::Int}
: the maximum bit width in the circuitparameters::Dict{String, Number}
: a map from the name of each parameter to its default valuesubmodules::Vector{Type}
: a list of submodule typesdfg::MetaDiGraph{Int, Float64}
: a data flow graph representing the circuit to be generatedhandlers::Dict{Operation, AbstractHandler}
: a map from operation type to a hardware generation handler and state
BitSAD.Net
— TypeNet(; name = "", suffixes = [""], value = missing,
type = :wire, class = :internal, signed = false,
bitwidth = 1, size = (1, 1))
Net(x; kwargs...)
Create a new multi-dimensional SystemVerilog net (for x
).
Arguments
name::String
: the name of the net (this can be a SystemVerilog constant expression too)suffixes::Vector{String}
: set if this net represents multiple wires with suffixes (e.g. a signed stochastic bitstream has suffixes_p
and_m
)value
: the underlying Julia value that this net representstype::Symbol
: one of :logicclass::Symbol
: one of [:input, :output, :internal, :constant, :parameter]signed::Bool
: set true if the net is signed in SystemVerilogbitwidth::Int
: the bit width of each element in the netsize::Tuple{Int, Int, ...}
: the size of the net in terms of number of elements
If x
is specified, then value = x
and size = netsize(x)
. netsize
is like Base.size
, but it expands scalars and vectors to 2D sizes (e.g. (1, 1)
) If x
is a SBitstream
or AbstractArray{<:SBitstream}
, then suffixes = ["_p", "_m"]
.
BitSAD.SBitstream
— TypeSBitstream(value::Real)
SBitstream{T<:Real}(value)
A stochastic bitstream that represents a real (floating-point) number between [-1, 1].
Fields:
bits::Vector{SBit}
: the underlying bitstreamvalue::Float64
: the underlying floating-point number being represented
BitSAD.SL2Normer
— TypeSL2Normer
A stochastic bitstream L2-norm operator.
BitSAD.SSignedAdder
— TypeSSignedAdder
A signed stochastic bitstream add operator.
BitSAD.SSignedDecorrelator
— TypeSSignedDecorrelator
A stochastic bitstream decorrelator.
BitSAD.SSignedDivider
— TypeSSignedDivider
A signed stochastic bitstream divide operator.
BitSAD.SSignedFixedGainDivider
— TypeSSignedFixedGainDivider
A stochastic bitstream fixed gain divide operator.
BitSAD.SSignedMatMultiplier
— TypeSSignedMatMultiplier
A stochastic bitstream matrix multiply operator.
BitSAD.SSignedMultiplier
— TypeSSignedMultiplier
A signed stochastic bitstream multiply operator.
BitSAD.SSignedSubtractor
— TypeSSignedSubtractor
A signed stochastic bitstream subtract operator.
BitSAD.SSquareRoot
— TypeSSquareRoot
A stochastic bitstream square root operator.
BitSAD.SimulatableContext
— TypeSimulatableContext
Used by BitSAD's simulation engine to track bit-level returns and previously transformed calls.
Fields
popmap
: a map from the original call to the simulated bit computationopmap
: a "reverse" map from a function + arguments to returnedGhost.Variable
BitSAD.bitwidth
— Methodbitwidth(x::Net)
Return the bitwidth of elements of x
BitSAD.estimate!
— Methodestimate!(buffer::AbstractVector, b::SBit)
estimate!(buffer::AbstractVector, b::VecOrMat{SBit})
estimate(buffer::AbstractVector)
estimate(s::SBitstream)
Push b
into the buffer
and return the current estimate
.
BitSAD.estimate
— Methodestimate(buffer::AbstractVector)
estimate(s::SBitstream)
Get the empirical mean of the bits in buffer
/s
BitSAD.generate
— Functiongenerate(s::SBitstream, T::Integer = 1)
generate!(s::SBitstream, T::Integer = 1)
Generate T
samples of the bitstream, s
. Add them to the queue for generate!
, otherwise return the vector of bits.
BitSAD.generatehw
— Methodgeneratehw([io::IO = IOBuffer()], f, args...;
top = nameof(f), submodules = [],
transforms = [insertrng!, constantreduction!])
Generate a SystemVerilog module named top
for f(args...)
as a circuit. Apply transforms
to the circuit before generating the SystemVerilog.
BitSAD.gethandler
— Functiongethandler(isbroadcast::Bool, ftype::Type, argtypes::Type...)
Return an instance of the hardware handler for the call of type ftype
on arguments of types argtypes
. isbroadcast
is true if the call is a broadcasted call.
Custom operators should overload this function to generate SystemVerilog for calls to the operator.
See also BitSAD.init_state
.
BitSAD.getsimulator
— Functiongetsimulator(f, args...)
Return a new instance of the simulatable operator for f(args...)
.
Custom operators should overload this function and define BitSAD.is_simulatable_primitive
.
BitSAD.is_simulatable_primitive
— Methodis_simulatable_primitive(ftype::Type, argtypes::Type...)
Return true if calling a callable of type ftype
on arguments of types argtypes
is a BitSAD simulatable primitive operator.
Custom operators should overload BitSAD.is_trace_primitive
before this function. is_simulatable_primitive
should only be overloaded if the primitive behavior is different for only simulation. Defaults to is_trace_primitive
.
BitSAD.is_trace_primitive
— Methodis_trace_primitive(ftype::Type, argtypes::Type...)
Return true if calling a callable of type ftype
on arguments of types argtypes
is a BitSAD primitive operator.
Custom operators should overload this function. Defaults to false.
BitSAD.jltypeof
— Methodjltypeof(x::Net)
Return the type of the underlying Julia value that x
represents.
BitSAD.name
— Methodname(x::Net)
Return the net name for x
. This can be a SystemVerilog constant expression.
BitSAD.netsize
— Methodnetsize(x)
Return the net size of x
. Like Base.size
, but it expands scalars and vectors to 2D sizes (e.g. (1, 1)
).
BitSAD.show_simulatable
— Methodshow_simulatable(f, args...)
Print the simulatable program returned by simulatable
.
BitSAD.simulatable
— Methodsimulatable(f, args...)
Return a simulatable variation of f(args...)
that emulates the bit-level operations for SBitstream
variables. The returned function, call it sim
, can be called via sim(f, args...)
.
This is done by recursively tracing the execution of f(args...)
then replacing each primitive simulatable operation with a simulatable operator.
BitSAD.simulator
— Methodsimulator(f, args...)
Return a simulatable Ghost.Tape
for f(args...)
. End-users should use simulatable
instead.
BitSAD.squashable
— Methodsquashable(ftype::Type)
Return true if a callable of type ftype
is a "squashable" 2-arg function. Defaults to false.
Functions like +
are n-arg functions in Julia, but most hardware designers think of them as 2-arg. When squashable
returns true, BitSAD's tracing engine will "squash" a single n-arg call into nested 2-arg calls.
BitSAD.suffixes
— Methodsuffixes(x::Net)
Return the suffixes for x
.
BitSAD.trace
— Methodtrace(f, args; is_primitive = is_trace_primitive,
submodules = [],
ctx = Dict{Any, Any}())
Trace the function call f(args...)
and return the Ghost.Tape
. Callables in submodules
are considered primitive operators.
This function is not meant to be called by users. Users should use simulatable
or generatehw
instead.
BitSAD.transform!
— Methodtransform!(f, [fctx,] tape::Ghost.Tape)
Transform tape
by applying f
to each entry in the tape.
f(tape.ctx, entry)
cannot manipulate tape
directly. Instead, f
should return a tuple of the form ([calls...], idx)
where [calls...]
is a vector of tape entries that should replace entry
. idx
specifies that references to entry
in tape
should be rebound to calls[idx]
. If calls
is empty, then entry
is deleted from the tape, and references to it are rebound to idx
. Note that if entry isa Ghost.Input
, then it cannot be deleted from tape
.
fctx(tape.ctx, calls)
can be used to update tape.ctx
. calls
is the same list of entries returned by f
except that the ID for each entry in calls
is the ID after being rebound in tape
. If calls
was empty, then fctx
is not called. If not specified, fctx
is a no-op.
BitSAD.value
— Methodvalue(x::Net)
Return the underlying Julia value that x
represents.
BitSAD.@nosim
— Macro@nosim f(x, y::T, ...) [kwargs=false]
Mark a function call of the form f(x, y::T, ...)
as a simulation primitive. This will prevent BitSAD's simulation engine for recursing this function, and instead use the return value of f
directly (without simulating it). Arguments may or may not have a type specified.
Set kwargs=true
if f
accepts keyword arguments. Note that the type and name of keywords cannot be specified.
If f(x, y, ...)
has a corresponding simulatable operator, then define BitSAD.getsimulator
for f
.