OR-1 dataflow CPU sketch
at ba08ffded3d3b2badb2a7e22816feafaacea5ded 95 lines 3.4 kB view raw
1from pathlib import Path 2 3import pytest 4from hypothesis import strategies as st 5from lark import Lark 6 7from cm_inst import ArithOp, LogicOp, MemOp, Port, RoutingOp 8from tokens import CMToken, DyadToken, MonadToken, SMToken 9 10GRAMMAR_PATH = Path(__file__).parent.parent / "dfasm.lark" 11 12uint16 = st.integers(min_value=0, max_value=0xFFFF) 13int16 = st.integers(min_value=-32768, max_value=32767) 14shift_amount = st.integers(min_value=0, max_value=15) 15 16arith_dyadic_ops = st.sampled_from([ArithOp.ADD, ArithOp.SUB]) 17arith_monadic_ops = st.sampled_from([ArithOp.INC, ArithOp.DEC]) 18shift_ops = st.sampled_from([ArithOp.SHIFT_L, ArithOp.SHIFT_R, ArithOp.ASHFT_R]) 19logic_dyadic_ops = st.sampled_from([LogicOp.AND, LogicOp.OR, LogicOp.XOR]) 20comparison_ops = st.sampled_from([LogicOp.EQ, LogicOp.LT, LogicOp.LTE, LogicOp.GT, LogicOp.GTE]) 21branch_ops = st.sampled_from([RoutingOp.BREQ, RoutingOp.BRGT, RoutingOp.BRGE]) 22switch_ops = st.sampled_from([RoutingOp.SWEQ, RoutingOp.SWGT, RoutingOp.SWGE]) 23overflow_ops = st.sampled_from([RoutingOp.BROF, RoutingOp.SWOF]) 24data_routing_ops = st.sampled_from([RoutingOp.SEL, RoutingOp.MRGE]) 25 26 27@st.composite 28def dyad_token(draw, target: int = 0, offset: int | None = None, ctx: int | None = None, gen: int | None = None) -> DyadToken: 29 return DyadToken( 30 target=target, 31 offset=draw(st.integers(min_value=0, max_value=63)) if offset is None else offset, 32 ctx=draw(st.integers(min_value=0, max_value=3)) if ctx is None else ctx, 33 data=draw(uint16), 34 port=draw(st.sampled_from(list(Port))), 35 gen=draw(st.integers(min_value=0, max_value=3)) if gen is None else gen, 36 wide=False, 37 ) 38 39 40@st.composite 41def monad_token(draw, target: int = 0, offset: int | None = None, ctx: int | None = None) -> MonadToken: 42 return MonadToken( 43 target=target, 44 offset=draw(st.integers(min_value=0, max_value=63)) if offset is None else offset, 45 ctx=draw(st.integers(min_value=0, max_value=3)) if ctx is None else ctx, 46 data=draw(uint16), 47 inline=False, 48 ) 49 50 51# SM ops: implemented for T1 are READ, WRITE, CLEAR, RD_INC, RD_DEC, CMP_SW, ALLOC, FREE, EXEC 52# Unimplemented: SET_PAGE, WRITE_IMM, RAW_READ, EXT 53sm_implemented_ops = [ 54 MemOp.READ, MemOp.WRITE, MemOp.CLEAR, MemOp.RD_INC, MemOp.RD_DEC, 55 MemOp.CMP_SW, MemOp.ALLOC, MemOp.FREE, MemOp.EXEC 56] 57sm_all_ops = st.sampled_from(sm_implemented_ops) 58 59 60@st.composite 61def sm_token(draw, addr=None, op=None, data=None): 62 # By default, generate T1 addresses (below tier_boundary of 256) 63 # Tests that specifically need T0 addresses should pass them explicitly 64 _addr = draw(st.integers(min_value=0, max_value=255)) if addr is None else addr 65 _op = draw(sm_all_ops) if op is None else op 66 _data = draw(uint16) if data is None else data 67 ret = CMToken(target=0, offset=0, ctx=0, data=0) 68 return SMToken( 69 target=0, 70 addr=_addr, 71 op=_op, 72 flags=None, 73 data=_data, 74 ret=ret, 75 ) 76 77 78@st.composite 79def sm_return_route(draw, target=0): 80 return CMToken( 81 target=target, 82 offset=draw(st.integers(min_value=0, max_value=63)), 83 ctx=draw(st.integers(min_value=0, max_value=3)), 84 data=0, 85 ) 86 87 88@pytest.fixture(scope="session") 89def parser(): 90 """Get the dfasm parser.""" 91 return Lark( 92 GRAMMAR_PATH.read_text(), 93 parser="earley", 94 propagate_positions=True, 95 )