Skip to content

Instantly share code, notes, and snippets.

@darius
Last active August 29, 2015 14:22
Show Gist options
  • Save darius/a406529efa563f3b75f5 to your computer and use it in GitHub Desktop.
Save darius/a406529efa563f3b75f5 to your computer and use it in GitHub Desktop.
"""
machine = assignment*.
assignment = lvalue _? '=' _? expr _? '\n'.
expr = lvalue _ lvalue _ lvalue.
lvalue = name ('.' literal)*.
literal = '0' | '1' | name.
name = /[^.]+/.
_ = /\s+/.
comment = /#.*/.
"""
def eval_hdl(text, env):
"""`text` is a machine description following the grammar above.
`env` is a dict, shared for two purposes:
* sequential-circuit state (and RAM)
* I/O devices
(It's also used as a scratchpad for combinational-logic state;
no separation of that state is enforced here.)
To use this for a particular machine, call eval_hdl() in a loop,
once for each most-basic machine cycle, reading/writing the data
of any special devices from/to env."""
env['0'] = 0
env['1'] = 1
def key(lvalue):
if '.' not in lvalue: return lvalue
name, subscrs = lvalue.split('.', 1)
return (name,) + tuple(env.get(s, 0) for s in subscrs)
for line in text.splitlines():
if '#' in line: line = line[:line.index('#')]
if not line: continue
dest, eq, test, if0, if1 = line.split()
assert eq == '='
env[key(dest)] = env.get(key(if1 if env.get(key(test)) else if0),
0)
"""
Some lacks that occur to me:
* Assertions (to help future implementors get it right)
* Some way to reduce the verbosity of:
* ROM tables
* bit-parallel logic
* Maybe a syntactic distinction between devices/memory and combinational logic?
* Like device names start with '%'? Though nothing's stopping you from writing that way.
Adding a way to define and access ROM tables would let us dispense with the
built-in MUX gate (implemented on the last line). You'd just define whatever
gates you want, as look-up tables.
"""
@darius
Copy link
Author

darius commented Jun 7, 2015

Let's consider another design with ROM tables and assertions. Example program:

not:10          # Table definition, arity 1.
1=not 0         # Assertion (as documentation/check)
0=not 1
and:0001        # Table definition, arity 2.
0=and 0 0
0=and 0 1
0=and 1 0
1=and 1 1
or:0111
0=or 0 0
1=or 0 1
1=or 1 0
1=or 1 1
mux:00110101    # Table definition, arity 3.
t<and 0 0       # Assignment, arity 0.
1=not t         # Use of an assigned variable (in an assertion).
t<and 1 1       # It can be reassigned. (The last assignment to a variable persists into the next cycle.)
0=not t
mem 0 t<or t 1  # Assignment, arity 2. Use for addressable memories.
1=mem 0 t
0=mem 1 1       # Unassigned variables are 0 (unless set by the simulator, e.g. an input device).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment