Behavioral simulator utility for sequential logic circuits, written in Clojure.
Switch branches/tags
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Behavioral simulator utility for sequential logic circuits.

Warning: This library needs to be rewritten. The current version's wire-and-block model contains a misconception that will make certain circuits impossible to code. I've forgotten the precise details, but it has something to do with the overly clever feature of registers taking their value from wires of the same name.

Simulate a sequential circuit at a high level by defining combinational logic blocks, their interconnections, and the placement of registers. After initializing all the registers, step the simulation forward one logical clock cycle at a time.

Each logic block can take multiple inputs and produce multiple outputs, with support for shared computation among output functions. Each output is uniquely named (usually with a :keyword); these names define the inputs available to other logic blocks. (In the nomenclature of, these are called "wires".) Registers are specified at the initialization step. Any register with the same name as a wire will intercept the value and accept it on the next tick of the clock. Logic block inputs matching registers always recieve the value of the register in the current cycle.


Following is a contrived example using the hailstone sequence (see Collatz conjecture for details) implemented as a logic circuit. The :n wire is the current sequence value, and a register is placed on that wire with the starting value. Each logic block in this example only produces one output. (See the documentation for add for more options.) Note that the :done block provides a boolean output, but that all other blocks are providing numerical output. does not constrain you to boolean logic—output may be of any type, including collections.

(require '[ :as circuit])

(def hailstone
   [:next #(if (zero? %1) %2 %3) [:parity :half :trinc] :n]
   [:done #(= 1 %) [:n] :halt]
   [:decoder #(mod % 2) [:n] :parity]
   [:down #(quot % 2) [:n] :half]
   [:up1 #(* 3 %) [:n] :tri]
   [:up2 #(inc %) [:tri] :trinc]))

(def hailstones-27
  (iterate circuit/step (circuit/init hailstone {:n 27})))

(circuit/read-register (nth hailstones-27 45) :n)
;; => 502

(circuit/read-register (nth hailstones-27 111) :n)
;; => 1
(circuit/read-wire (nth hailstones-27 111) :halt)
;; => true

Please feel free to contact me with any suggestions. See the file for ideas I'm already considering.


Source copyright (c) 2011 Tim McCormack Source licensed under GNU General Public License v3.0 and Eclipse Public License v1.0.