Expand description
Spatial source emission for a counted loop — the bridge from the certified fabric IR to the open Plasticine toolchain (Spatial → PIR → plastiroute → Tungsten; Koeplinger et al., PLDI 2018; the chain is mirrored at gitlab.com/dataplane-ai). P4 of the Plasticine lane.
A LoopFabric is one Foreach controller: its carried state registers become Regs, the induction
variable the counter, the body cells vals in SSA order, a predicated select a mux, and the next-state
sources the register writes at the end of the iteration (computed first, assigned after — the parallel
register-update semantics the fabric has). Every LOGOS Int is a 64-bit Long. What this emitter does
not spell (sequence tiles, heap islands, the wider FuncUnit family) is refused TYPED so a program never
reaches the toolchain with silently different meaning.
Structs§
- GdaColumn
- One array a scatter row term reads, as the GDA app declares it: its name, its axis and its host data.
- GdaPar
- The knobs of Spatial’s
GDAregression app (pir/regression/GDA.scala): the rows a tile of the data loads (ts), how many such tiles run at once (op), the rows of a tile reduced at once (mp1), the covariance rows one rank-1 update writes at once (mp2), and the lanes of the loads, the store and the column loops (ip). - Gemm
Unroll - Emit a Spatial REGRESSION-HARNESS GEMM app for
C[m×n] = A[m×k] · B[k×n]— the structure of Spatial’s ownregression/GEMM.scala(an output tileits × tsaccumulated overkints-chunks by aMemReduce, anip-laneReduceper dot product) with OUR shape and tiles, so a LOGOS matmul runs through the public chain as the toolchain’s authors would write it. Host data are small residues so the 32-bit sums stay exact and the harness’sPASSline means equality. Typed refusal when the tiles do not divide the shape (the template streams whole tiles). How wide each loop of the GEMM nest runs. Spatial’s own regression variants set exactly these, and a factor left at 1 is a loop we run serially where the hand-written app runs it wide. - Kmeans
Par - The knobs of Spatial’s
Kmeansregression app (pir/regression/Kmeans.scala): the points a tile loads (ts), the lanes of the loads, the store and the feature loops (ip), how many tiles run at once (op), and how many points, centroids and centroid updates run at once (mp1,mp2,mp3). - MapColumn
- One column of a zip map as the app declares it: its name, its element type and the host data the program fills it with.
- MapPar
- The knobs of Spatial’s
BlackScholesregression app (pir/regression/BlackScholes.scala): the tiletsof every column each outer iteration streams through FIFOs, how many tiles run at once (op), and the lanes of the loads, the map and the store (ip). - Outer
Par - The knobs of Spatial’s
OuterProductregression app (pir/regression/OuterProduct.scala): the tiles of the two vectors (ts1,ts2), the lanes of the loads and the store (ip), the lanes of the tile’s column and row loops (ip1,ip2), and how many tiles of each vector run at once (op1,op2). - ZipColumn
- One column of a zip sum as the app declares it: its name (a Scala identifier the app does not otherwise use) and the host data the program fills it with.
- ZipPar
- The knobs of Spatial’s reduce-over-tiles regression apps (
pir/regression/DotProduct.scala,TPCHQ6.scala): the tiletseach outer iteration loads of every column, how many tiles run at once (op), and the lanes of the loads and of the inner reduce (ip).
Functions§
- emit_
spatial_ counted_ loop - Emit Spatial source for the counted loop
lfof LOGOS functionfn_nameas a standaloneSpatialApp(arguments from the command line, the result printed), or a typed reason it cannot. - emit_
spatial_ counted_ loop_ test - Emit a Spatial REGRESSION-HARNESS app (
class <class_name> extends SpatialTest) for the counted loop: the sampleparamsare itsruntimeArgs, the VM’s answergoldis checked on the host, and the harness’sPASS: true (<class_name>)line is what the toolchain ledger parses. Values are 64-bitLong: PIR’s Tungsten codegen lowersFix(true,64,0)to Clong, so the simulation computes what the VM computes (the ISCA’17 FU is 32-bit; a silicon run would need the narrower type). - emit_
spatial_ gda_ test - Emit a Spatial REGRESSION-HARNESS scatter accumulation
S = Σ_{r<R} d_r d_rᵀ(C × C) with the structure of Spatial’s ownGDAapp — the column-axis arrays loaded once, aMemReduceoverts-row tiles of the row-axis arrays and of the row-major data, inside it aMemReduceover the tile’s rows that computes each row’sdintosubTileand its outer product intosigmaTile— at our shape, over the program’s own data. The app computes in Spatial’s 32-bitInt; a sum that would wrap there (where the VM’s 64-bitIntdoes not) is refused, as is a tile that does not divide the rows. - emit_
spatial_ gemm_ test - emit_
spatial_ gemm_ test_ with - The same emission with the loop widths given explicitly — the form the parity corpus uses to reproduce a Spatial variant’s exact configuration.
- emit_
spatial_ kmeans_ test - Emit a Spatial REGRESSION-HARNESS k-means clustering with the structure of Spatial’s own
Kmeansapp — the centroids loaded from the firstKpoints,itersepochs each aMemReduceoverts-point tiles of aMemReduceover the tile’s points (each point’s distance to every centroid aReduceover the features, the nearest found by a min and an index reduce, the point added to its centroid’s row as a one-hot tile), then every centroid set to its row over its count — at our shape and the app’s runtime arguments, over the program’s own data, written at the app’sX = Int(the app’skmeans[T:Num]instantiated). The app keeps each centroid’s count as a last feature of every point fixed at 1 (D = f + 1columns), where the program keeps counts; equally near centroids go to the last (the app’smaxof the matching indices) or, for a program keeping the first, to the first (amin). The gold is the clustering the program computes, evaluated on the host the way the accelerator computes it, the nearest centroid chosen by distance and then by index whichever way the host folds. The app computes in Spatial’s 32-bitInt; a distance or a sum that would wrap there is refused, as is a tile that does not divide the points. - emit_
spatial_ outer_ test - Emit a Spatial REGRESSION-HARNESS outer product
out[i][j] = a[i]·b[j](m × n) with the structure of Spatial’s ownOuterProductapp — ats1-tile ofaper outer iteration, ats2-tile ofbper inner one, thets1 × ts2product tile computed in SRAM and stored whole — at our shape. Host data are small residues; the harness’sPASSline means equality. Typed refusal when a tile does not divide its vector or a tile loop is wider than its tile. - emit_
spatial_ zip_ map_ test - Emit a Spatial REGRESSION-HARNESS zip map
out[t] = f(c₀[t], c₁[t], …)with the structure of Spatial’s ownBlackScholesapp: perts-element tile, a FIFO of every column loaded in the order the program declares its columns (declared, a permutation of the columns, which are in the order the term reads them), anip-laneForeachdequeuing one element of every column and enqueuing the term’s value, the output tile stored,optiles at once — at our length, over the program’s own data, with the variant’s PIR arguments (pir_args, the suffix itspirArgsoverride appends). The term is printed as its DAG: a function the program calls twice is two copies, as Spatial stages it, and a subterm used twice is computed once. The app computes in Spatial’s 32-bitIntandFloat; a term whoseIntwould wrap there or whoseRealwould leave theFloat’s range is refused, as is a division by zero on any path (the host’s gold would trap), a tile that does not divide the length, or a map wider than its tile. The gold is the host’s own evaluation of the term: aFloatresult passes within 0.1% (and 0.001) of it, anIntone exactly. - emit_
spatial_ zip_ sum_ test - Emit a Spatial REGRESSION-HARNESS zip sum
Σ_{t<n} f(c₀[t], c₁[t], …)with the structure of Spatial’s own reduce-over-tiles apps (DotProduct,TPCHQ6): ats-element tile of every column loaded in parallel,optiles reduced at once, each tile’s sum anip-laneReduceof the term (the body ofspatial.lib.ML.sum_flat) — at our length, over the program’s own column data, so the app’s gold is the LOGOS program’s answer. The app computes in Spatial’s 32-bitInt, as the regression apps do; a sum that would wrap there (where the VM’s 64-bitIntdoes not) is refused, as is a tile that does not divide the length or a reduce wider than its tile.