A 32 bit signed integer, either a function-specific success value or one of of the following failure values:
Name | Value | Description |
---|---|---|
NullPointer |
-0x0000_0001 |
A pointer was null |
PointerMisaligned |
-0x0000_0002 |
A pointer did not have the required alignment for its type |
InvalidArgument |
-0x0000_0003 |
An argument was invalid |
ArgumentOutOfRange |
-0x0000_0004 |
An argument was outside of its valid range |
Utf8Encoding |
-0x0000_0005 |
A string did not have valid UTF8 encoding |
Io |
-0x0000_0006 |
An IO error occurred |
InvalidOperation |
-0x0000_0007 |
The operation was invalid |
ResourceLimitReached |
-0x0001_0001 |
The simulation reached its resource limit |
WireWidthMismatch |
-0x0001_0002 |
The width of two or more wires mismatched |
WireWidthIncompatible |
-0x0001_0003 |
The width of a wire is incompatible with a component |
OffsetOutOfRange |
-0x0001_0004 |
An offset was out of its valid range |
TooFewInputs |
-0x0001_0005 |
Too few inputs were given for a component |
InvalidInputCount |
-0x0001_0006 |
An invalid number of inputs was given for a component |
InvalidComponentType |
-0x0001_0007 |
The type of a component was invalid for an operation |
Conflict |
-0x0002_0001 |
The simulation caused a driver conflict |
InvalidWireId |
-0x0002_0002 |
A wire id was not a valid wire in the simulation |
InvalidComponentId |
-0x0002_0003 |
A component id was not a valid component in the simulation |
MalformedFormat |
-0x0003_0001 |
The format of some data was invalid |
Unsupported |
-0x0003_0002 |
An opperation was not supported |
A 32 bit unsigned integer uniquely identifying a wire in a simulation.
A value of 0xFFFFFFFF
corresponds to the invalid ID. This ID will never be returned by the API.
A 32 bit unsigned integer uniquely identifying a component in a simulation.
A value of 0xFFFFFFFF
corresponds to the invalid ID. This ID will never be returned by the API.
An opaque type representing a logic state of up to 255 bits.
Use only behind a pointer.
struct PortList {
usize len;
char** names;
WireId* wires;
}
struct SimulationErrors {
usize conflicts_len;
WireId* conflicts;
}
An opaque type used to build up a simulation graph.
Use only behind a pointer.
An opaque type representing a simulation.
Use only behind a pointer.
Result string_free(char* s)
Frees a string that was returned by other functions in the API.
Returns 0
on success.
Result port_list_free(PortList port_list)
Frees all allocations of a PortList
struct that was returned by other functions in the API.
Returns 0
on success.
Result simulation_errors_free(SimulationErrors errors)
Frees all allocations of a SimulationErrors
struct that was returned by other functions in the API.
Returns 0
on success.
LogicState* logic_state_high_z()
Creates a LogicState
with all bits set to the high impedance state.
The returned LogicState
must be freed by calling logic_state_free
.
LogicState* logic_state_undefined()
Creates a LogicState
with all bits set to an undefined state.
The returned LogicState
must be freed by calling logic_state_free
.
LogicState* logic_state_logic_0()
Creates a LogicState
with all bits set to the logic low state.
The returned LogicState
must be freed by calling logic_state_free
.
LogicState* logic_state_logic_1()
Creates a LogicState
with all bits set to the logic high state.
The returned LogicState
must be freed by calling logic_state_free
.
LogicState* logic_state_from_int(u32 value)
Creates a LogicState
representing the given integer. High bits are set to 0.
The returned LogicState
must be freed by calling logic_state_free
.
Result logic_state_from_big_int(u32* value, usize word_len, LogicState** clone)
Creates a LogicState
representing the given integer. Integer words are given in little endian order, high bits are set to 0.
Will fail if word_len
is not between 1 and 8 inclusive.
Returns 0
on success.
The returned LogicState
must be freed by calling logic_state_free
.
Result logic_state_parse(char* s, LogicState** state)
Parses a LogicState
from a string representation. High bits are set to high impedance.
Will fail if the string is longer than 255 characters, shorter than one character, or contains characters other than 'z'
, 'Z'
, 'x'
, 'X'
, '0'
and '1'
.
Returns 0
on success.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Result logic_state_clone(LogicState* state, LogicState** clone)
Clones a LogicState
into a new allocation.
Returns 0
on success.
The cloned LogicState
must be freed separately by calling logic_state_free
, only if the operation succeeded.
Result logic_state_to_int(LogicState* state, u8 width, u32* value)
Attempts to convert the first width
bits of a LogicState
to an integer.
width
must be between 1 and 32 inclusive. Will fail if any of the bits are either in the Z
or X
state.
Returns 0
on success.
Result logic_state_to_big_int(LogicState* state, u8 width, u32* value)
Attempts to convert the first width
bits of a LogicState
to an integer. Integer words are returned in little endian order.
value
must contain at least width / 32
words rounded up. Will fail if any of the bits are either in the Z
or X
state.
Returns 0
on success.
Result logic_state_get_bit_state(LogicState* state, u8 bit_index)
Gets the state of a single bit in a LogicState
.
On success, returns one of the following values:
0
: high impedance1
: undefined2
: logic low3
: logic high
Result logic_state_print(LogicState* state, u8 width, char* buffer)
Prints the string representation of a LogicState
into a buffer.
The buffer must be big enough to hold at least width
bytes and will not be null terminated by this function.
Since the buffer is owned by the caller, it must not be freed by string_free
.
Returns 0
on success.
Result logic_state_eq(LogicState* a, LogicState* b, u8 width)
Checks the first width
bits of two LogicState
objects for equality.
On success, returns one of the following values:
0
: not equal1
: equal
Result logic_state_free(LogicState* state)
Frees a LogicState
that was returned by other functions in the API.
Returns 0
on success.
Result builder_new(Builder** builder)
Creates a new Builder
object.
The resulting Builder
must be freed by calling simulator_build
, only if the operation succeeded.
Returns 0
on success.
Result builder_write_dot(Builder* builder, char* dot_file)
Writes the simulation graph into a Graphviz DOT file.
Returns 0
on success.
Result builder_get_wire_width(Builder* builder, WireId wire, u8* width)
Gets the width of a wire.
Returns 0
on success.
Result builder_set_wire_drive(Builder* builder, WireId wire, LogicState* drive)
Drives a wire to a certain state without needing a component.
Returns 0
on success.
Result builder_get_wire_drive(Builder* builder, WireId wire, LogicState** drive)
Gets the current drive of a wire.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result builder_get_register_width(Builder* builder, ComponentId register, u8* width)
Gets the width of a register in the simulation.
The ID passed to register
must refer to a register component.
Returns 0
on success.
Result builder_read_register_state(Builder* builder, ComponentId register, LogicState** state)
Gets the current state of a register in the simulation.
The ID passed to register
must refer to a register component.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result builder_write_register_state(Builder* builder, ComponentId register, LogicState* state)
Sets the state of a register in the simulation.
The ID passed to register
must refer to a register component.
Returns 0
on success.
Result builder_get_memory_metrics(Builder* builder, ComponentId memory, usize* size, u8* width)
Gets the size and width of a memory block in the simulation.
The ID passed to memory
must refer to a memory component.
Returns 0
on success.
Result builder_read_memory_state(Builder* builder, ComponentId memory, usize addr, LogicState** state)
Gets the current state of a memory location in the simulation.
The ID passed to memory
must refer to a memory component.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result builder_write_memory_state(Builder* builder, ComponentId memory, usize addr, LogicState* state)
Sets the state of a memory location in the simulation.
The ID passed to memory
must refer to a memory component.
Returns 0
on success.
Result builder_set_wire_name(Builder* builder, WireId wire, char** name)
Sets the name of a wire.
Returns 0
on success.
Result builder_get_wire_name(Builder* builder, WireId wire, char** name)
Gets the name of a wire, if one has been assigned.
If no name has been assigned to the wire, name will be set to null
.
The resulting string (if any) must be freed by calling string_free
, only if the operation succeeded.
Returns 0
on success.
Result builder_set_component_name(Builder* builder, ComponentId component, char* name)
Sets the name of a component.
Returns 0
on success.
Result builder_get_component_name(Builder* builder, ComponentId component, char** name)
Gets the name of a component, if one has been assigned.
If no name has been assigned to the component, name will be set to null
.
The resulting string (if any) must be freed by calling string_free
, only if the operation succeeded.
Returns 0
on success.
Result builder_add_wire(Builder* builder, u8 width, WireId* wire)
Adds a wire to the simulation.
Returns 0
on success.
Result builder_add_and_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds an AND gate component to the simulation.
Returns 0
on success.
Result builder_add_or_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds an OR gate component to the simulation.
Returns 0
on success.
Result builder_add_xor_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds an XOR gate component to the simulation.
Returns 0
on success.
Result builder_add_nand_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds a NAND gate component to the simulation.
Returns 0
on success.
Result builder_add_nor_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds a NAND gate component to the simulation.
Returns 0
on success.
Result builder_add_xnor_gate(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds an XNOR gate component to the simulation.
Returns 0
on success.
Result builder_add_merge(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds a merge component to the simulation.
Returns 0
on success.
Result builder_add_priority_decoder(Builder* builder, WireId* inputs, usize input_len, WireId output, ComponentId* component)
Adds a priority decoder component to the simulation.
Returns 0
on success.
Result builder_add_buffer(Builder* builder, WireId input, WireId enable, WireId output, ComponentId* component)
Adds a buffer component to the simulation.
Returns 0
on success.
Result builder_add_add(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds an addition component to the simulation.
Returns 0
on success.
Result builder_add_sub(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a subtraction component to the simulation.
Returns 0
on success.
Result builder_add_mul(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a multiplication component to the simulation.
Returns 0
on success.
Result builder_add_left_shift(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a left shift component to the simulation.
Returns 0
on success.
Result builder_add_logical_right_shift(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a logical right shift component to the simulation.
Returns 0
on success.
Result builder_add_arithmetic_right_shift(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds an arithmetic right shift component to the simulation.
Returns 0
on success.
Result builder_add_compare_equal(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_not_equal(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_less_than(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_greater_than(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_less_than_or_equal(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_greater_than_or_equal(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_less_than_signed(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_greater_than_signed(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_less_than_or_equal_signed(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_compare_greater_than_or_equal_signed(Builder* builder, WireId input_a, WireId input_b, WireId output, ComponentId* component)
Adds a comparator component to the simulation.
Returns 0
on success.
Result builder_add_not_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a NOT gate component to the simulation.
Returns 0
on success.
Result builder_add_neg(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a negation component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_and_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal AND gate component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_or_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal OR gate component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_xor_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal XOR gate component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_nand_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal NAND gate component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_nor_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal NOR gate component to the simulation.
Returns 0
on success.
Result builder_add_horizontal_xnor_gate(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a horizontal XNOR gate component to the simulation.
Returns 0
on success.
Result builder_add_zero_extend(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a zero extension component to the simulation.
Returns 0
on success.
Result builder_add_sign_extend(Builder* builder, WireId input, WireId output, ComponentId* component)
Adds a sign extension component to the simulation.
Returns 0
on success.
Result builder_add_slice(Builder* builder, WireId input, u8 offset, WireId output, ComponentId* component)
Adds a slice component to the simulation.
Returns 0
on success.
Result builder_add_adder(Builder* builder, WireId input_a, WireId input_b, WireId carry_in, WireId output, WireId carry_out, ComponentId* component)
Adds an adder component to the simulation.
Returns 0
on success.
Result builder_add_multiplexer(Builder* builder, WireId* inputs, usize input_len, WireId select, WireId output, ComponentId* component)
Adds a multiplexer component to the simulation.
Returns 0
on success.
Result builder_add_register(Builder* builder, WireId data_in, WireId data_out, WireId enable, WireId clock, u8 clock_polarity, ComponentId* component)
Adds a register component to the simulation.
For clock_polarity
, valid values are 0
(falling edge) and 1
(rising edge). Any other values are invalid.
Returns 0
on success.
Result builder_add_ram(Builder* builder, WireId write_addr, WireId data_in, WireId read_addr, WireId data_out, WireId write, WireId clock, u8 clock_polarity, ComponentId* component)
Adds a RAM component to the simulation.
For clock_polarity
, valid values are 0
(falling edge) and 1
(rising edge). Any other values are invalid.
Returns 0
on success.
Result builder_add_rom(Builder* builder, WireId addr, WireId data, ComponentId* component)
Adds a ROM component to the simulation.
Returns 0
on success.
Result builder_import_yosys_module(Builder* builder, char* json_file, PortList* inputs, PortList* outputs)
Imports a module defined by a Yosys netgraph into the circuit.
On success, inputs
and outputs
will contain a list of the imported modules ports.
The resulting PortList
objects must be freed by calling port_list_free
, only if the operation succeeded.
Returns 0
on success.
Valid netgraphs can be generated with this command:
yosys -p "read_verilog <VERILOG-FILE>; synth -top <TOP-MODULE> -flatten -noalumacc -nordff -run begin:fine; hierarchy -check; check; write_json <OUTPUT-FILE>
Result simulator_build(Builder** builder, Simulator** simulator)
Creates a new Simulator
object from a Builder
.
If the operation succeeded, the specified Builder
will be freed and be set to null
.
The resulting Simulator
must be freed by calling simulator_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_build_with_trace(Builder** builder, char* trace_file, Simulator** simulator)
Creates a new Simulator
object from a Builder
, with VCD tracing enabled.
If the operation succeeded, the specified Builder
will be freed and be set to null
.
The Builder
may be freed even if the operation failed. In this case it will also be set to null
.
The resulting Simulator
must be freed by calling simulator_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_write_dot(Simulator* simulator, char* dot_file, u8 show_states)
Writes the simulation graph into a Graphviz DOT file.
If show_states
is non-zero, the exported graph will display the state of wires and registers.
Returns 0
on success.
Result simulator_get_wire_width(Simulator* simulator, WireId wire, u8* width)
Gets the width of a wire.
Returns 0
on success.
Result simulator_set_wire_drive(Simulator* simulator, WireId wire, LogicState* drive)
Drives a wire to a certain state without needing a component.
Returns 0
on success.
Result simulator_get_wire_drive(Simulator* simulator, WireId wire, LogicState** drive)
Gets the current drive of a wire.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_get_wire_state(Simulator* simulator, WireId wire, LogicState** state)
Gets the current state of a wire.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_get_register_width(Simulator* simulator, ComponentId register, u8* width)
Gets the width of a register in the simulation.
The ID passed to register
must refer to a register component.
Returns 0
on success.
Result simulator_read_register_state(Simulator* simulator, ComponentId register, LogicState** state)
Gets the current state of a register in the simulation.
The ID passed to register
must refer to a register component.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_write_register_state(Simulator* simulator, ComponentId register, LogicState* state)
Sets the state of a register in the simulation.
The ID passed to register
must refer to a register component.
Returns 0
on success.
Result simulator_get_memory_metrics(Simulator* simulator, ComponentId memory, usize* size, u8* width)
Gets the size and width of a memory block in the simulation.
The ID passed to memory
must refer to a memory component.
Returns 0
on success.
Result simulator_read_memory_state(Simulator* simulator, ComponentId memory, usize addr, LogicState** state)
Gets the current state of a memory location in the simulation.
The ID passed to memory
must refer to a memory component.
The resulting LogicState
must be freed by calling logic_state_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_write_memory_state(Simulator* simulator, ComponentId memory, usize addr, LogicState* state)
Sets the state of a memory location in the simulation.
The ID passed to memory
must refer to a memory component.
Returns 0
on success.
Result simulator_get_wire_name(Simulator* simulator, WireId wire, char** name)
Gets the name of a wire, if one has been assigned.
If no name has been assigned to the wire, name will be set to null
.
The resulting string (if any) must be freed by calling string_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_get_component_name(Simulator* simulator, ComponentId component, char** name)
Gets the name of a component, if one has been assigned.
If no name has been assigned to the component, name will be set to null
.
The resulting string (if any) must be freed by calling string_free
, only if the operation succeeded.
Returns 0
on success.
Result simulator_reset(Simulator* simulator)
Resets the simulation.
Returns 0
on success.
Result simulator_run_sim(Simulator* simulator, u64 max_steps, SimulationErrors* errors)
Runs the simulation until it settles, but at most for max_steps
steps.
On success, returns one of the following values:
0
: the simulation settled withinmax_steps
steps1
: the simulation did not settle withinmax_steps
steps
If a Conflict
failure is reported, errors
will contain additional information about which wires had a driver conflict.
In this case, errors
must later be freed by calling simulation_errors_free
.
Result simulator_trace(Simulator* simulator, u64 time)
Writes the current state of the simulation into the simulators associated VCD file at the specified time in nanoseconds.
Calling this function with a Simulator
that was not constructed by simulator_build_with_trace
is not illegal, but will have no effect.
Returns 0
on success.
Result simulator_free(Simulator* simulator)
Frees a Simulator
object.
Returns 0
on success.