|
|
%TODO
|
|
|
Here lies the details of the different functions coming into play in the netlist simulator, so you can understand the source code better.
|
|
|
|
|
|
Here lies the details of the different functions coming into play in the netlist simulator, so you can understand the source code better. |
|
|
\ No newline at end of file |
|
|
# Graph
|
|
|
|
|
|
## `mk_graph : unit -> 'a graph`
|
|
|
Creates an empty graph.
|
|
|
|
|
|
## `add_node : 'a graph -> 'a -> unit`
|
|
|
Modifies the graph to add a node to it.
|
|
|
|
|
|
## `node_for_label` : 'a graph -> 'a -> 'a node`
|
|
|
Give the node corresponding to the label. Raises `Not_found` if no such node exists.
|
|
|
|
|
|
## `add_edge : 'a graph -> 'a -> 'a -> unit`
|
|
|
Modifies the graph to add an edge to it (both nodes have to exist previously, raises `Not_found` otherwise).
|
|
|
|
|
|
## `clear_marks : 'a graph -> unit`
|
|
|
Modifies the graph to put all its nodes to the `NotVisited` state.
|
|
|
|
|
|
## `find_roots : 'a graph -> 'a node list`
|
|
|
Returns the list of the nodes of the graph that is a root, i.e. one which is not linked to by any other node.
|
|
|
|
|
|
## `has_cycle : 'a graph -> bool`
|
|
|
Searches through the graph with a recursively-written DFS to look for a cycle. Returns `true` if there is a cycle.
|
|
|
|
|
|
## `topological : 'a graph -> 'a list`
|
|
|
Traverses the graph with a DFS to create a topologically ordered list of labels (if two labels `x` and `y` are such that there are two nodes labelled by them, noted `nx` and `ny`, and there is a link from `nx` to `ny`, `x<y`). This algorithm fails if the graph has a cycle, and therefore raises the exception `Cycle`.
|
|
|
|
|
|
# Scheduler
|
|
|
|
|
|
## `read_arg : Netlist_ast.arg -> Netlist_ast.ident list`
|
|
|
Returns the list of the identifiers in an arguments (which is either of size one or zero).
|
|
|
|
|
|
## `read_expr : Netlist_ast.exp -> Netlist_ast.ident list`
|
|
|
Returns the list of the identifiers for which the single expression given as an argument depends on. Note however, that some arguments won't be taken into account as an argument.
|
|
|
These are : the indexes in `Eselect` and `Eslice`, the address size, word size in both `Eram` and `Erom`, as well as the `write_enable` flag, write address and write data for `Eram`, and the only argument on `Ereg`.
|
|
|
|
|
|
## `read_exp : Netlist_ast.equation -> Netlist_ast.ident list`
|
|
|
Returns the list of dependencies for the equation, preceded by its identifier, while keeping unicity.
|
|
|
|
|
|
## `schedule : Netlist_ast.program -> Netlist_ast.program`
|
|
|
Returns a sorted netlist, so that by evaluating line by line, the dependencies are respected. Raises `Combinational_cycle` if no such cycle exists (which means the netlist is doing some very weird stuff it's not really supposed to do, and you probably know what you're doing enough to find a solution to your own problem).
|
|
|
|
|
|
It works in the following way :
|
|
|
- Create an oriented graph $`G=(V,E)`$ with $`V`$ being all the identifiers that are present in the program.
|
|
|
- Complete it by setting $`E`$ such that a node $`x`$ points to a node $`y`$ if the identifier `x` depends on the value of the identifier `y` to be computed.
|
|
|
- Sort the node labels with the topological sort. If the topological sort fails, raise `Combinational_cycle`
|
|
|
- Meddle a bit to convert the `Netlist_ast.ident list` to a `Netlist_ast.program`.
|
|
|
|
|
|
# Simulator
|
|
|
|
|
|
## `find : Netlist_ast.ident -> Netlist_ast.value`
|
|
|
Gives the value of the identifier in the current context. Raises `Not_found` if it has not be computed yet.
|
|
|
|
|
|
## `add : Netlist_ast.ident -> Netlist_ast.value -> unit`
|
|
|
Adds the value of the identifier to the context.
|
|
|
|
|
|
## `val_arg : Netlist_ast.arg -> Netlist_ast.value`
|
|
|
Gives the value of the argument in the current context. If it does not exist, it raises `Failure "error val_arg : [id]` with [id] the name of the identifier without value.
|
|
|
|
|
|
## `anot : Netlist_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to the opposite of the argument provided, bitwise in the case of a bus.
|
|
|
|
|
|
## `abinop : Netlist_ast.binop -> Netlist_ast.arg -> Netlist_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to the corresponding boolean binary operator provided applied to the two arguments, bitwise in case of a bus.
|
|
|
Raises `Failure "Binop on two buses of different sizes"` if the function is called on two buses of different sizes or `Failure "Type Mismatch"` if it is called on a wire and a bus.
|
|
|
|
|
|
## `amux : Netlist_ast.arg -> Netlist_ast.arg -> Netlisr_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to : given the three arguments, of value `s`, `x0`, `x1`, if `s`=0, then `x0`, else `x1`.
|
|
|
If called on buses, it will raise `Failure "Multplexer incompatible with buses"`.
|
|
|
|
|
|
## `aconcat : Netlist_ast.arg -> Netlist_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to a bus consisting of the concatenation of the two buses/wires provided.
|
|
|
|
|
|
## `aslice : int -> int -> Netlist_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to : if `aslice` is called with `i1`, `i2` and an argument of value `v`, `then v[i..j]`.
|
|
|
Raises `Failure "Nothing to slice"` if the argument provided is not a bus.
|
|
|
|
|
|
## `aselect : int -> Netlist_ast.arg -> Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the identifier provided is mapped to : if `aselect`is called with `i`and an argument of value `v`, then `v[i]` if it is a bus, or `v` if it a wire.
|
|
|
|
|
|
## `sim_eq : Netlist_ast.equation -> unit`
|
|
|
Simulates the result of a single equation `(id, exp)`, by updating the register. If the expression `exp` is combinational, then just call the corresponding function, as they are described above. If it is a memory operation, try to read in the corresponding memory.
|
|
|
Raises `Failure "No register [id]"` if the register labelled `[id]` does not exist; `Failure "Non existing RAM/ROM [id]"` if the RAM/ROM labelle `[id]` does not exist.
|
|
|
|
|
|
## `write_mem : Netlist_ast.program -> unit`
|
|
|
Updates the memory context such that all the memories are updated to their current values.
|
|
|
Raises `Failure "Register [id] is not connected"` if the value the register labelled by `[id]`is supposed to be taking is not present in the context ; `Failure "write_enable input for RAM [id] is a bus"` if the RAM registered by `id` has its argument `write_enable` represented as a bus.
|
|
|
|
|
|
## `init : Netlist_ast.program -> unit`
|
|
|
Initiallizes the memory to be full of zeroes at the good size.
|
|
|
|
|
|
## `input_wire : Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the provided identifier is mapped to the bit given by the user in `stdin`, in the form of an integer.
|
|
|
Note : any non nil integer is mapped to `true`, 0 is mapped to `false`.
|
|
|
|
|
|
## `input_bus : Netlist_ast.ident -> unit`
|
|
|
Updates the context such that the provided identifier is mapped to the bits given by the user, bit by bit, in `stdin` (it asks the value of every wire).
|
|
|
|
|
|
## `input : Netlist_ast.program -> unit`
|
|
|
Calls [input_wire](## \`input_wire : Netlist_ast.ident -> unit\`) or [input_bus](\`input_bus : Netlist_ast.ident -> unit\`) on every identifier marked as an input in the program.
|
|
|
|
|
|
## `output : Netlist_ast.program -> unit`
|
|
|
Prints on `stdout` all the identifiers and corresponding values marked as an output in the program.
|
|
|
Note : the values are in the form of integers.
|
|
|
|
|
|
## `sim_step : Netlist_ast.program -> unit`
|
|
|
Calls [`sim_eq`](## `sim_eq : Netlist_ast.equation -> unit`) for each equation in the program. Will run smoothly if the equations are ordered according to their dependencies.
|
|
|
|
|
|
## `cycle : Netlist_ast.program -> unit`
|
|
|
Executes a full cycle of the simulation :
|
|
|
- Reinitiallize the context.
|
|
|
- Takes the input from the user ([input](## \`input : Netlist_ast.program -> unit\`)).
|
|
|
- Simulates a step. ([sim_step](## \`sim_step : Netlist_ast.program -> unit\`))
|
|
|
- Writes in memory. ([write_mem](## \`write_mem : Netlist_ast.program -> unit\`))
|
|
|
- Outputs the results. ([output](## \`output : Netlist_ast.program -> unit\`))
|
|
|
|
|
|
## `simulator : Netlist_ast.program -> int -> unit`
|
|
|
Runs as many cycles ( [cycle](## \`cycle : Netlist_ast.program -> unit\`) ) as instructed, with an infinite loop if the step number is -1.
|
|
|
|
|
|
## `compile : string -> unit`
|
|
|
Reads the netlist file via some voodoo magic happening in the [netlist.ml](netlist.ml) file, then sorts it according to the dependencies of the variables ([Scheduler.schedule](## \`schedule : Netlist_ast.program -> Netlist_ast.program\`)), then simulates it ([simulator](## \`simulator : Netlist_ast.program -> int -> unit\`).
|
|
|
Fails with error message `The netlist has a combinatory cycle` if the dependencies cannot be resolves, and with a parse error if there is a problem in the format of the netlist.
|
|
|
|
|
|
## `main : unit -> unit`
|
|
|
Gathers the arguments from the CLI and then calls [compile](## \`compile : string -> unit\`). |
|
|
\ No newline at end of file |