⚠ SUPERSEDED — This was an early syntax sketch. The canonical grammar is
dfasm.lark(Lark/Earley parser, 38+ tests intests/test_parser.py). Mnemonics, naming conventions, and some semantics have diverged from this sketch. Preserved for historical context and design rationale only.
Ops#
CM tokens#
Type 1 (0b00)
- token carries operand for a dyadic (two-input) instruction. requires matching store lookup. Type 2 (0b01)
- token carries operand for a monadic (single-input) instruction. bypasses matching store.
Fields#
- offset instruction slot
- ctx execution context (data) slot
- port L/R operand discriminator (dyadic)
- gen generation counter (dyadic)
- inl|wid inline flag on monadic ops, width flag on dyadic ops
- data
ALU - Arithmetic Logic Unit (Control Memory module)#
- 5-bit opcode (initial)
- opcodes not present on bus except as part of
cfgtoken data words
Arithmetic#
- add
- sub
- inc (monadic)
- dec (monadic)
NOTE: could we re-use the same opcodes for add/sub and inc/dec? everything about them is essentially the same except for dyadic/monadic
Shifts (monadic)
- shiftl - Shift A left by N+1 bits. N from IRAM immediate field (1-8 allow for shifting of a full byte's width)
- shiftr - Logical shift A right by N+1 bits. Zero-fill. N from immediate.
- ashftr - Arithmetic shift A right by N bits. Sign-extend. N from immediate.
(NOTE: implementation uses
shl/shr/asrmnemonics — seealu-and-output-design.md)
Logical#
- and
- or
- xor
- not (monadic)
Comparison
- eq
- lt (do we want explicit signed/unsigned?)
- lte
- gt
- gte
Routing/switching/branching#
All of these have perhaps odd wire semantics (see alu-and-output-design.md)
- br(eq/gt/ge/of/ty) - branch plus continue|local bit
- sw(eq/gt/ge/of/ty) - branch plus output enable
- gate - pass or suppress
- sel
- merge
Data (all monadic)#
- pass
- const - constant load
- free_ctx - dealloc context slot, no data output
System (Type 4)#
PE_id bits repurposed as subtype
iop
- r
- w
- rw fields:
- dest
- addr|payload1
- data|payload2 cfg
- load_inst
- fields:
- dest
- addr
- data_l
- data_h
- ...chainable (data_l, data_h) to enable efficient loading of sequential addresses
- route_set
- fields:
- dest
- data (address mapping)
plus 2 reserved
MLU - Memory Logic Unit (Structure Memory module)#
Type 3 (0b10) token
- 3-4 bit ext opcode + 9-8 bit internal addr
- 4+ bit internal opcode + 12-bit internal addr
Fields#
- SM id
- opcode
- flags (in extended mode)
- data
- return route
Syntax#
@output <| op L, R
; or
op L, R |> @out1, @out2
direction doesn't dictate number of outputs direction could dictate strong/weak connections
@namerefers to a node- can be chained with | to manually specify a PE (e.g.
@sum|pe0) - opcode or node can be chained with
:to manually specify an iram addr or context slot (e.g.sub:0x02) or L|R - NO spaces allowed in chains
$namerefers to a function/subroutine/subgraph label, same rules as above- alternatively an opcode plus any const arg can be labeled as:
&label <| op, arg ;for comments, as is tradition, this is ASM- named args for clarity are allowed
@serial <| r dest=0x45, addr=0x91, data=0x43
function definition:
$fib |> {
&const_n <| const, 10
&sub1 <| sub
&sub2 <| sub
&branch <| switch
&const_n |> &branch:L
&const_n |> &sub1:L
&const_n |> &sub1:R
&const_n |> &sub2:R
&sub1 |> &recurse_a:L
; ...
}
for initial data:
- if it should start resident in SM, use
=with a name or label expression
@hello = #str "hello"
#denotes a macro, (here, 'str') which expands the above to something more like
@hello|sm0:0 = 0x05 ; length
@hello|sm0:1 = 'h','e' ; 16-bit data slots can hold 2 utf8/ascii chars
@hello|sm0:2 = 'l','l'
...
loading:
- initial program loading happens via a generated (or explicit) series of cfg and sm instructions
inst_defs and adjacent edges are collected and transformed into a series of load_inst calls