1+ from pathlib import Path
2+ from unittest import TestCase
3+
4+ import accelforge as af
5+
6+ INPUT_FILES_DIR = Path (__file__ ).parent / "input_files" / "networked"
7+
8+
9+ class TestParsing (TestCase ):
10+ def test_hierarchical (self ):
11+ spec = af .Spec .from_yaml (
12+ # af.examples.arches.networked.hierarchical,
13+ INPUT_FILES_DIR
14+ / "hierarchical.yaml" ,
15+ )
16+ self .assertIn ("PeArray" , spec .arch .nodes )
17+ self .assertEqual (spec .arch .nodes ["PeArray" ].get_fanout (), 1 )
18+ self .assertIn ("Scratchpad" , spec .arch .nodes )
19+ self .assertEqual (spec .arch .nodes ["Scratchpad" ].get_fanout (), 4 )
20+ self .assertIn ("MacArray" , spec .arch .nodes )
21+ self .assertEqual (spec .arch .nodes ["MacArray" ].get_fanout (), 1 )
22+
23+ try :
24+ spec = spec .calculate_component_area_energy_latency_leak ()
25+ except af .EvaluationError as e :
26+ self .fail (e .message )
27+
28+ def test_flat (self ):
29+ spec = af .Spec .from_yaml (
30+ # af.examples.arches.networked.flat,
31+ INPUT_FILES_DIR
32+ / "flat.yaml" ,
33+ )
34+ self .assertIn ("NoC" , spec .arch .nodes )
35+ self .assertEqual (spec .arch .nodes ["NoC" ].get_fanout (), 1 )
36+ self .assertEqual (
37+ {n .name for n in spec .arch .get_nodes_of_type (af .spec .Leaf )},
38+ {
39+ "MainMemory" ,
40+ "GlobalBuffer" ,
41+ "NoC" ,
42+ "RowBuffer" ,
43+ "ColumnBuffer" ,
44+ "DistributedBuffer" ,
45+ "Scratchpad" ,
46+ "MAC" ,
47+ },
48+ )
49+
50+ try :
51+ spec = spec .calculate_component_area_energy_latency_leak ()
52+ except af .EvaluationError as e :
53+ self .fail (e .message )
54+
55+
56+ class TestModel (TestCase ):
57+ def test_hierarchical_1d (self ):
58+ M = 8
59+ KN = 8
60+ MAC_TILE = 2
61+ M_TILE = 4
62+ BITS_PER_VALUE = 8
63+
64+ spec = af .Spec .from_yaml (
65+ af .examples .workloads .matmuls ,
66+ # af.examples.arches.networked.hierarchical,
67+ INPUT_FILES_DIR / "hierarchical_1d.yaml" ,
68+ # af.examples.mappings.one_matmul_to_networked_hierarchical,
69+ INPUT_FILES_DIR / "one_matmul_to_networked_hierarchical_1d.yaml" ,
70+ jinja_parse_data = {
71+ "N_EINSUMS" : 1 ,
72+ "M" : 8 ,
73+ "KN" : 8 ,
74+ "MAC_TILE" : MAC_TILE ,
75+ "M_TILE" : M_TILE ,
76+ },
77+ )
78+ result = spec .evaluate_mapping ()
79+ self .assertEqual (
80+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>T0<SEP>hops" ].iloc [0 ],
81+ (M / M_TILE )
82+ * (KN / MAC_TILE ) # number of used Scratchpad
83+ * M_TILE
84+ * KN # temporal for n1 in mapping
85+ * sum (i + 1 for i in range (MAC_TILE )) # unicast along X-axis of MacArray
86+ * BITS_PER_VALUE ,
87+ )
88+ # NOTE: assuming XY routing (as defined in mapping)
89+ self .assertEqual (
90+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>T1<SEP>hops" ].iloc [0 ],
91+ (M / M_TILE )
92+ * (KN / MAC_TILE )
93+ * M_TILE
94+ * KN # temporal for n1 in mapping
95+ * MAC_TILE # multicast along X-axis of MacArray
96+ * BITS_PER_VALUE ,
97+ )
98+ self .assertEqual (
99+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>W0<SEP>hops" ].iloc [0 ],
100+ (M / M_TILE )
101+ * (KN / MAC_TILE )
102+ * M_TILE
103+ * KN
104+ * sum (i + 1 for i in range (MAC_TILE ))
105+ * BITS_PER_VALUE ,
106+ )
107+
108+ self .assertEqual (
109+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>T0<SEP>hops" ].iloc [0 ],
110+ (M / M_TILE )
111+ * sum (i + 1 for i in range (KN // MAC_TILE )) # unicast along X-axis of PeArray
112+ * M_TILE
113+ * MAC_TILE
114+ * BITS_PER_VALUE ,
115+ )
116+ # NOTE: assuming XY routing (as defined in mapping)
117+ self .assertEqual (
118+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>T1<SEP>hops" ].iloc [0 ],
119+ (M / M_TILE )
120+ * KN // MAC_TILE # multicast along X-axis of PeArray
121+ * M_TILE
122+ * KN
123+ * BITS_PER_VALUE ,
124+ )
125+ self .assertEqual (
126+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>W0<SEP>hops" ].iloc [0 ],
127+ (M / M_TILE )
128+ * sum (i + 1 for i in range (KN // MAC_TILE )) # unicast along PeArray
129+ * MAC_TILE
130+ * KN
131+ * BITS_PER_VALUE ,
132+ )
133+
134+ def test_hierarchical (self ):
135+ M = 8
136+ KN = 8
137+ MAC_TILE = 2
138+ PE_TILE = KN // MAC_TILE
139+ M_TILE = 4
140+ BITS_PER_VALUE = 8
141+
142+ spec = af .Spec .from_yaml (
143+ af .examples .workloads .matmuls ,
144+ # af.examples.arches.networked.hierarchical,
145+ INPUT_FILES_DIR / "hierarchical.yaml" ,
146+ # af.examples.mappings.one_matmul_to_networked_hierarchical,
147+ INPUT_FILES_DIR / "one_matmul_to_networked_hierarchical.yaml" ,
148+ jinja_parse_data = {
149+ "N_EINSUMS" : 1 ,
150+ "M" : 8 ,
151+ "KN" : 8 ,
152+ "MAC_TILE" : MAC_TILE ,
153+ "M_TILE" : M_TILE ,
154+ },
155+ )
156+ result = spec .evaluate_mapping ()
157+ self .assertEqual (
158+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>T0<SEP>hops" ].iloc [0 ],
159+ (M / M_TILE )
160+ * (KN / MAC_TILE ) ** 2
161+ * M_TILE
162+ * (
163+ sum (i + 1 for i in range (MAC_TILE )) # unicasting along X
164+ +
165+ MAC_TILE * MAC_TILE # multicast along Y for each column
166+ )
167+ * BITS_PER_VALUE ,
168+ )
169+ # NOTE: assuming XY routing (as defined in mapping)
170+ self .assertEqual (
171+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>T1<SEP>hops" ].iloc [0 ],
172+ (M / M_TILE )
173+ * (KN / MAC_TILE ) ** 2
174+ * M_TILE
175+ * (
176+ MAC_TILE * MAC_TILE # multicast along X (the tile is shape N1, which is MAC_TILE here)
177+ +
178+ MAC_TILE * sum (i + 1 for i in range (MAC_TILE )) # unicasting along Y for each row
179+ )
180+ * BITS_PER_VALUE ,
181+ )
182+ self .assertEqual (
183+ result .data ["Matmul0<SEP>action<SEP>MacArray<SEP>W0<SEP>hops" ].iloc [0 ],
184+ (M / M_TILE )
185+ * (KN / MAC_TILE ) ** 2
186+ * M_TILE
187+ * (
188+ MAC_TILE * sum (i + 1 for i in range (MAC_TILE )) # unicast along X (the tile is shape N1, which is MAC_TILE here)
189+ +
190+ MAC_TILE * sum (i + 1 for i in range (MAC_TILE )) # unicasting along Y for each row
191+ )
192+ * BITS_PER_VALUE ,
193+ )
194+
195+ self .assertEqual (
196+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>T0<SEP>hops" ].iloc [0 ],
197+ (M / M_TILE )
198+ * (
199+ sum (i + 1 for i in range (PE_TILE ))
200+ +
201+ PE_TILE * PE_TILE
202+ )
203+ # tile shape
204+ * M_TILE
205+ * MAC_TILE
206+ * BITS_PER_VALUE ,
207+ )
208+ # NOTE: assuming XY routing (as defined in mapping)
209+ self .assertEqual (
210+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>T1<SEP>hops" ].iloc [0 ],
211+ (M / M_TILE )
212+ * (
213+ PE_TILE * PE_TILE
214+ +
215+ PE_TILE * sum (i + 1 for i in range (PE_TILE ))
216+ )
217+ * M_TILE
218+ * MAC_TILE
219+ * BITS_PER_VALUE ,
220+ )
221+ self .assertEqual (
222+ result .data ["Matmul0<SEP>action<SEP>PeArray<SEP>W0<SEP>hops" ].iloc [0 ],
223+ (M / M_TILE )
224+ * (
225+ PE_TILE * sum (i + 1 for i in range (PE_TILE ))
226+ +
227+ PE_TILE * sum (i + 1 for i in range (PE_TILE ))
228+ )
229+ * MAC_TILE ** 2
230+ * BITS_PER_VALUE ,
231+ )
232+
233+
234+ class TestMapper (TestCase ):
235+ def test_hierarchical (self ):
236+ M = 8
237+ KN = 8
238+ MAC_TILE = 2
239+ PE_TILE = KN // MAC_TILE
240+ M_TILE = 4
241+ BITS_PER_VALUE = 8
242+
243+ spec = af .Spec .from_yaml (
244+ af .examples .workloads .matmuls ,
245+ # af.examples.arches.networked.hierarchical,
246+ INPUT_FILES_DIR / "hierarchical.yaml" ,
247+ jinja_parse_data = {
248+ "N_EINSUMS" : 1 ,
249+ "M" : 8 ,
250+ "KN" : 8 ,
251+ "MAC_TILE" : MAC_TILE ,
252+ "M_TILE" : M_TILE ,
253+ },
254+ )
255+ result = spec .map_workload_to_arch ()
0 commit comments