Architecture-aware General Templating #129
Replies: 2 comments
-
After chatting w/ @gussmith23 and @yzh119 yesterday we've settled on a new architecture. We are going to implement Sketch Generation, which will be a modular component of our overall design. Roughly we have:
The idea is that:
|
Beta Was this translation helpful? Give feedback.
-
I'm tring to figure out how to define arch primitives. The first way was via:
which produces a struct. The problem is that this has inputs bound to it on creation, which won't work in an architecture configuration (we are defining primitives here before we bind them to inputs). I'd like to be able to create an
This suffers from a problem that I can't inspect the value: if I want to know if a primitie is a LUT or a MUX I need to instantiate it and then check the type. E.g., the following function fails at runtime:
The |
Beta Was this translation helpful? Give feedback.
-
Lakeroad Templates
Lakeroad uses a solver to search for an PFGA program P that implements a bitvec program B. To do this Lakeroad uses program synthesis to synthesize a program L in the Lakeroad DSL, and then compiles this to P (in Verilog).
The space of all programs in the Lakeroad DSL is too large to search exhaustively. For efficiency's sake we chose to introduce templates: program shapes that the solver tries to fill in. This is one design choice, and maybe not the best design choice (e.g., maybe using grammars is better? This is an open question). However, the up side of using templates is that we can easily constrain the search space so that it doesn't blow up too big.
Ad Hoc Templates
Initially Lakeroad used what I will call ad hoc program templating: each architecture has a set of templates that we feed to the solver. When the current set of templates doesn't cover all program functionality we introduce a new template to cover that functionality. The same basic templates are used across different architectures, and there is very little code reuse.
General Templates
To fix this we started hacking on general templates. These are templates that have generic constructs like
lr:lut
andlr:mux
. These have generic implementations in the interpreter, and the compiler is then tasked with lowering these to architecture specific Verilog.This addresses the problem of code reuse but has the following problems:
We are not synthesizing over hardware-specific code, and this loses some of the guarantees that we'd like to have (e.g., "correct by construction")
We are tasking the compiler writer with potentially non-trivial code writing to translate generic constructs to verilog. LUTs should be easy, but how do we handle DSPs?
Some New Approaches
@gussmith23 and I have been chatting about how to handle the above issues, and @ztatlock has also weighed in. There are two variants of the same idea, which is essentially:
Idea 1: Template Schemas
This was my first idea. Basically, instead of writing general templates we write template schemas. These look almost identical, but with one crucial difference: rather than having the interpreter run on general LR constructs such as
lr:lut
we replace these general LR constructs w/ architecture-specific LR constructs prior to passing to the interpreter. Thus, when we go to synthesis we are synthesizing over architecture-specific primitives rather than general LR constructs.Idea 2: Multiple Lowering Stages
@ztatlock argued (and I think @gussmith23 also argued last wednesday) that we could use multiple stages:
Beta Was this translation helpful? Give feedback.
All reactions