OR-1 dataflow CPU sketch
at pe-frame-redesign 115 lines 4.1 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, FrameOp, LogicOp, MemOp, Port, RoutingOp 8from tokens import CMToken, DyadToken, FrameControlToken, MonadToken, PELocalWriteToken, 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.SHL, ArithOp.SHR, ArithOp.ASR]) 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, act_id: 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 act_id=draw(st.integers(min_value=0, max_value=7)) if act_id is None else act_id, 33 data=draw(uint16), 34 port=draw(st.sampled_from(list(Port))), 35 ) 36 37 38@st.composite 39def monad_token(draw, target: int = 0, offset: int | None = None, act_id: int | None = None) -> MonadToken: 40 return MonadToken( 41 target=target, 42 offset=draw(st.integers(min_value=0, max_value=63)) if offset is None else offset, 43 act_id=draw(st.integers(min_value=0, max_value=7)) if act_id is None else act_id, 44 data=draw(uint16), 45 inline=False, 46 ) 47 48 49# SM ops: implemented for T1 are READ, WRITE, CLEAR, RD_INC, RD_DEC, CMP_SW, ALLOC, FREE, EXEC 50# Unimplemented: SET_PAGE, WRITE_IMM, RAW_READ, EXT 51sm_implemented_ops = [ 52 MemOp.READ, MemOp.WRITE, MemOp.CLEAR, MemOp.RD_INC, MemOp.RD_DEC, 53 MemOp.CMP_SW, MemOp.ALLOC, MemOp.FREE, MemOp.EXEC 54] 55sm_all_ops = st.sampled_from(sm_implemented_ops) 56 57 58@st.composite 59def sm_token(draw, addr=None, op=None, data=None): 60 # By default, generate T1 addresses (below tier_boundary of 256) 61 # Tests that specifically need T0 addresses should pass them explicitly 62 _addr = draw(st.integers(min_value=0, max_value=255)) if addr is None else addr 63 _op = draw(sm_all_ops) if op is None else op 64 _data = draw(uint16) if data is None else data 65 ret = CMToken(target=0, offset=0, act_id=0, data=0) 66 return SMToken( 67 target=0, 68 addr=_addr, 69 op=_op, 70 flags=None, 71 data=_data, 72 ret=ret, 73 ) 74 75 76@st.composite 77def sm_return_route(draw, target=0): 78 return CMToken( 79 target=target, 80 offset=draw(st.integers(min_value=0, max_value=63)), 81 act_id=draw(st.integers(min_value=0, max_value=7)), 82 data=0, 83 ) 84 85 86@st.composite 87def pe_local_write_token(draw, target: int = 0, act_id: int | None = None) -> PELocalWriteToken: 88 return PELocalWriteToken( 89 target=target, 90 act_id=draw(st.integers(min_value=0, max_value=7)) if act_id is None else act_id, 91 region=draw(st.integers(min_value=0, max_value=1)), 92 slot=draw(st.integers(min_value=0, max_value=63)), 93 data=draw(uint16), 94 is_dest=draw(st.booleans()), 95 ) 96 97 98@st.composite 99def frame_control_token(draw, target: int = 0, act_id: int | None = None) -> FrameControlToken: 100 return FrameControlToken( 101 target=target, 102 act_id=draw(st.integers(min_value=0, max_value=7)) if act_id is None else act_id, 103 op=draw(st.sampled_from(list(FrameOp))), 104 payload=draw(uint16), 105 ) 106 107 108@pytest.fixture(scope="session") 109def parser(): 110 """Get the dfasm parser.""" 111 return Lark( 112 GRAMMAR_PATH.read_text(), 113 parser="earley", 114 propagate_positions=True, 115 )