> **⚠ SUPERSEDED** — This was an early syntax sketch. The canonical grammar > is `dfasm.lark` (Lark/Earley parser, 38+ tests in `tests/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 `cfg` token 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`/`asr` mnemonics — see `alu-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 ```vhdl @output <| op L, R ; or op L, R |> @out1, @out2 ``` direction doesn't dictate number of outputs direction could dictate strong/weak connections - `@name` refers 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 - `$name` refers 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 ```vhdl @serial <| r dest=0x45, addr=0x91, data=0x43 ``` function definition: ```vhdl $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 ```typescript @hello = #str "hello" ``` - `#` denotes a macro, (here, 'str') which expands the above to something more like ```vhdl @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