2f7e264db7eef56136ec6f28e8563dcdb196d848
1 # SPDX-License-Identifier: LGPL-3-or-later
2 # See Notices.txt for copyright information
4 SimdScope class - provides context for SIMD signals to make them useable
5 under the exact same API as scalar nmigen Signals.
7 Copyright (C) 2021 Jacob Lifshay
8 Copyright (C) 2021 Luke Kenneth Casson Leighton
13 s = SimdScope(m, elwid)
14 a = s.Signal(width=64, ....)
20 from nmigen
.hdl
.ast
import Signal
24 """The global scope object for SimdSignal and friends
27 * vec_el_counts: SimdMap
28 a map from `ElWid` values `k` to the number of elements in a vector
29 when `self.elwid == k`.
32 vec_el_counts = SimdMap({
40 vec_el_counts = SimdMap({
46 * elwid: ElWid or nmigen Value with a shape of some ElWid class
47 the current elwid (simd element type). example: Signal(2)
51 def __init__(self
, module
, elwid
, vec_el_counts
, scalar
=False):
54 self
.vec_el_counts
= vec_el_counts
56 self
.set_module(module
)
58 def set_module(self
, module
):
59 # in SIMD mode, must establish module as part of context and inform
60 # the module to operate under "SIMD" Type 1 (AST) casting rules,
61 # not the # default "Value.cast" rules.
65 from ieee754
.part
.partsig
import SimdSignal
66 if module
is not None:
67 module
._setAstTypeCastFn
(SimdSignal
.cast
)
69 def __call__(self
, module
=None, elwid
=None):
70 """use as: newscope = scope(newmodule) or with scope(m) as newscope
71 allows for scope to be established and carry parameters then
72 later copied and used inside an Elaboratable. a new elwid
73 can be specified so that pipelines can carry properly sync'd
80 return SimdScope(module
, elwid
, self
.vec_el_counts
, self
.scalar
)
83 return (f
"SimdScope(\n"
84 f
" elwid={self.elwid},\n"
85 f
" vec_el_counts={self.vec_el_counts},\n")
88 # from here, the functions are context-aware variants of standard
89 # nmigen API (Signal, Signal.like, Shape) which are to be redirected
90 # to either their standard scalar nmigen equivalents (verbatim)
91 # or to the SimdSignal equivalents. each one is to be documented
92 # CAREFULLY and CLEARLY.
95 def Signal(self
, shape
=None, *, name
=None, reset
=0, reset_less
=False,
96 attrs
=None, decoder
=None, src_loc_at
=0):
98 # scalar mode, just return a nmigen Signal. THIS IS IMPORTANT.
99 # when passing in SimdShape it should go "oh, this is
100 # an isinstance Shape, i will just use its width and sign"
101 # which is the entire reason why SimdShape had to derive
103 return Signal(shape
=shape
, name
=name
, reset
=reset
,
104 reset_less
=reset_less
, attrs
=attrs
,
105 decoder
=decoder
, src_loc_at
=src_loc_at
)
107 # recursive module import resolution
108 from ieee754
.part
.partsig
import SimdSignal
109 # SIMD mode. shape here can be either a SimdShape,
110 # a Shape, or anything else that Signal can take (int or
111 # a tuple (int,bool) for (width,sign)
112 s
= SimdSignal(mask
=self
, # should contain *all* context needed,
113 # which goes all the way through to
114 # the layout() function, passing
115 # 1) elwid 2) vec_el_counts
116 shape
=shape
, # should contain the *secondary*
117 # part of the context needed for
118 # the layout() function:
119 # 3) lane_shapes 4) fixed_width
120 name
=name
, reset
=reset
,
121 reset_less
=reset_less
, attrs
=attrs
,
122 decoder
=decoder
, src_loc_at
=src_loc_at
)
123 # set the module context so that the SimdSignal can create
124 # its own submodules during AST creation
125 s
.set_module(self
.module
)
129 def Signal_like(self
):
131 # scalar mode, just return nmigen Signal.like. THIS IS IMPORTANT.
137 def Shape(self
, width
=1, signed
=False):
139 # scalar mode, just return nmigen Shape. THIS IS IMPORTANT.
140 return Shape(width
, signed
)
142 # SIMD mode. NOTE: for compatibility with Shape, the width
143 # is assumed to be the widths_at_elwid parameter NOT the
144 # fixed width. this ensures that code that is converted
145 # straight from scalar to SIMD will have the exact same
146 # width at all elwidths, because layout() detects the integer
147 # case and converts it, preserving the width at all elwidths
148 # the names are preserved to ensure parameter-compatibility
150 return SimdShape(self
, width
=width
, # actually widths_at_elwid