@@ -57,13 +57,11 @@ compileWith bsSettings prefix spec
5757
5858 | otherwise
5959 = do let typesBsFile = render $ pPrint $ compileTypesBS bsSettings prefix spec
60- ifcBsFile = render $ pPrint $ compileIfcBS bsSettings prefix spec
6160 bsFile = render $ pPrint $ compileBS bsSettings prefix spec
6261
6362 let dir = bluespecSettingsOutputDirectory bsSettings
6463 createDirectoryIfMissing True dir
6564 writeFile (dir </> specTypesPkgName prefix ++ " .bs" ) typesBsFile
66- writeFile (dir </> specIfcPkgName prefix ++ " .bs" ) ifcBsFile
6765 writeFile (dir </> " bs_fp.c" ) copilotBluespecFloatingPointC
6866 writeFile (dir </> " BluespecFP.bsv" ) copilotBluespecFloatingPointBSV
6967 writeFile (dir </> prefix ++ " .bs" ) bsFile
@@ -93,86 +91,166 @@ compile :: String -> Spec -> IO ()
9391compile = compileWith mkDefaultBluespecSettings
9492
9593-- | Generate a @<prefix>.bs@ file from a 'Spec'. This is the main payload of
96- -- the Bluespec backend.
97- --
98- -- The generated Bluespec file will import a handful of files from the standard
99- -- library, as well as the following generated files:
100- --
101- -- * @<prefix>Ifc.bs@, which defines the interface containing the trigger
102- -- functions and external variables.
103- --
104- -- * @<prefix>Types.bs@, which defines any structs used in the 'Spec'.
105- --
106- -- It will also generate a @mk<prefix> :: Module <prefix>Ifc -> Module Empty@
107- -- function, which defines the module structure for this 'Spec'. The
108- -- @mk<prefix>@ function has the following structure:
109- --
110- -- * First, bind the argument of type @Module <prefix>Ifc@ so that trigger
111- -- functions can be invoked and external variables can be used.
112- --
113- -- * Next, declare stream buffers and indices.
114- --
115- -- * Next, declare generator functions for streams, accessor functions for
116- -- streams, and guard functions for triggers.
117- --
118- -- * Next, declare rules for each trigger function.
119- --
120- -- * Finally, declare a single rule that updates the stream buffers and
121- -- indices.
94+ -- the Bluespec backend. See the @copilot-bluespec/DESIGN.md@ document for a
95+ -- high-level description of what this file contains.
12296compileBS :: BluespecSettings -> String -> Spec -> BS. CPackage
12397compileBS _bsSettings prefix spec =
12498 BS. CPackage
12599 (BS. mkId BS. NoPos (fromString prefix))
126100 (Right [] )
127101 (stdLibImports ++ genImports)
128102 []
129- [moduleDef]
103+ [ ifcDef
104+ , mkModuleDefPragma
105+ , mkModuleDef
106+ , ifcRulesDef
107+ , mkModuleRulesDef
108+ , addModuleRulesDef
109+ ]
130110 []
131111 where
132112 -- import <prefix>Types
133- -- import <prefix>Ifc
134113 genImports :: [BS. CImport ]
135114 genImports =
136115 [ BS. CImpId False $ BS. mkId BS. NoPos $ fromString
137116 $ specTypesPkgName prefix
138- , BS. CImpId False $ BS. mkId BS. NoPos $ fromString
139- $ specIfcPkgName prefix
140117 , BS. CImpId False $ BS. mkId BS. NoPos " BluespecFP"
141118 ]
142119
143- moduleDef :: BS. CDefn
144- moduleDef = BS. CValueSign $
120+ -- interface <prefix>Ifc {-# always_ready, always_enabled #-} =
121+ -- ...
122+ ifcDef :: BS. CDefn
123+ ifcDef = BS. Cstruct
124+ True
125+ (BS. SInterface [BS. PIAlwaysRdy , BS. PIAlwaysEnabled ])
126+ (BS. IdK ifcId)
127+ [] -- No type variables
128+ ifcFields
129+ [] -- No derived instances
130+
131+ -- {-# properties mkFibs = { verilog } #-}
132+ mkModuleDefPragma :: BS. CDefn
133+ mkModuleDefPragma = BS. CPragma $ BS. Pproperties mkModuleDefId [BS. PPverilog ]
134+
135+ -- mk<prefix> :: Module <prefix>Ifc
136+ -- mk<prefix> =
137+ -- module
138+ -- ...
139+ mkModuleDef :: BS. CDefn
140+ mkModuleDef = BS. CValueSign $
145141 BS. CDef
146- (BS. mkId BS. NoPos $ fromString $ " mk" ++ prefix)
147- -- :: Module <prefix>Ifc -> Module Empty
142+ mkModuleDefId
148143 (BS. CQType
149144 []
150- (BS. tArrow
151- `BS. TAp ` (BS. tModule `BS. TAp ` ifcTy)
152- `BS. TAp ` (BS. tModule `BS. TAp ` emptyTy)))
153- [ BS. CClause [BS. CPVar ifcModId] [] $
154- BS. Cmodule BS. NoPos $
155- BS. CMStmt
156- (BS. CSBind (BS. CPVar ifcArgId) Nothing [] (BS. CVar ifcModId))
157- : map BS. CMStmt mkGlobals ++
158- [ BS. CMStmt $ BS. CSletrec genFuns
159- , BS. CMrules $ BS. Crules [] rules
160- ]
145+ (BS. tModule `BS. TAp ` ifcTy))
146+ [ BS. CClause [] [] $
147+ BS. Cmodule BS. NoPos $
148+ wireGlobalStmts ++ genFunStmts ++ ruleIfcStmts
161149 ]
162-
163- ifcArgId = BS. mkId BS. NoPos $ fromString ifcArgName
164- ifcModId = BS. mkId BS. NoPos " ifcMod"
165-
166- rules :: [BS. CRule ]
167- rules = map mkTriggerRule uniqueTriggers ++ maybeToList (mkStepRule streams)
150+ where
151+ wireGlobalStmts :: [BS. CMStmt ]
152+ wireGlobalStmts = map BS. CMStmt (mkExtWires ++ mkGlobals)
153+
154+ genFunStmts :: [BS. CMStmt ]
155+ genFunStmts =
156+ -- language-bluespec's pretty-printer will error if it encounters a
157+ -- CSletrec with an empty list of definitions, so avoid generating a
158+ -- CSletrec if there are no streams.
159+ [ BS. CMStmt $ BS. CSletrec genFuns | not (null genFuns) ]
160+
161+ ruleIfcStmts :: [BS. CMStmt ]
162+ ruleIfcStmts =
163+ [ BS. CMrules $ BS. Crules [] $ maybeToList $ mkStepRule streams
164+ , BS. CMinterface $ BS. Cinterface BS. NoPos (Just ifcId) ifcMethodImpls
165+ ]
166+
167+ -- interface <prefix>RulesIfc =
168+ -- ...
169+ ifcRulesDef :: BS. CDefn
170+ ifcRulesDef =
171+ BS. Cstruct
172+ True
173+ (BS. SInterface [] )
174+ (BS. IdK ifcRulesId)
175+ [] -- No type variables
176+ ifcRulesFields
177+ [] -- No derived instances
178+
179+ -- mk<prefix>Rules :: <prefix>Ifc -> <prefix>RulesIfc -> Rules
180+ -- mk<prefix>Rules ifc ifcRules =
181+ -- rules
182+ -- ...
183+ mkModuleRulesDef :: BS. CDefn
184+ mkModuleRulesDef =
185+ BS. CValueSign $
186+ BS. CDef
187+ mkModuleRulesDefId
188+ (BS. CQType [] mkModuleRulesType)
189+ [BS. CClause
190+ (map BS. CPVar [ifcArgId, ifcRulesArgId])
191+ []
192+ (BS. Crules [] moduleRules)]
193+ where
194+ -- <prefix>Ifc -> <prefix>RulesIfc -> Rules
195+ mkModuleRulesType :: BS. CType
196+ mkModuleRulesType =
197+ BS. tArrow `BS. TAp ` ifcTy `BS. TAp `
198+ (BS. tArrow `BS. TAp ` ifcRulesTy `BS. TAp ` BS. tRules)
199+
200+ -- rules
201+ -- ...
202+ moduleRules :: [BS. CRule ]
203+ moduleRules = map mkTriggerRule uniqueTriggers ++ map mkExtRule exts
204+
205+ -- add<prefix>Rules :: <prefix>Ifc -> <prefix>RulesIfc -> Module Empty
206+ -- add<prefix>Rules ifc ifcRules = addRules (mk<prefix>Rules ifc ifcRules)
207+ addModuleRulesDef :: BS. CDefn
208+ addModuleRulesDef =
209+ BS. CValueSign $
210+ BS. CDef
211+ addModuleRulesDefId
212+ (BS. CQType [] addModuleRulesType)
213+ [BS. CClause
214+ (map BS. CPVar [ifcArgId, ifcRulesArgId])
215+ []
216+ addModuleRulesExpr]
217+ where
218+ -- <prefix>Ifc -> <prefix>RulesIfc -> Module Empty
219+ addModuleRulesType :: BS. CType
220+ addModuleRulesType =
221+ BS. tArrow `BS. TAp ` ifcTy `BS. TAp `
222+ (BS. tArrow `BS. TAp ` ifcRulesTy `BS. TAp `
223+ (BS. tModule `BS. TAp ` emptyTy))
224+
225+ -- addRules (mk<prefix>Rules ifc ifcRules)
226+ addModuleRulesExpr :: BS. CExpr
227+ addModuleRulesExpr =
228+ BS. CApply
229+ (BS. CVar (BS. idAddRules BS. NoPos ))
230+ [BS. CApply
231+ (BS. CVar mkModuleRulesDefId)
232+ (map BS. CVar [ifcArgId, ifcRulesArgId])]
233+
234+ mkModuleDefId =
235+ BS. mkId BS. NoPos $ fromString $ " mk" ++ prefix
236+ mkModuleRulesDefId =
237+ BS. mkId BS. NoPos $ fromString $ " mk" ++ prefix ++ " Rules"
238+ addModuleRulesDefId =
239+ BS. mkId BS. NoPos $ fromString $ " add" ++ prefix ++ " Rules"
168240
169241 streams = specStreams spec
170242 triggers = specTriggers spec
171243 uniqueTriggers = mkUniqueTriggers triggers
172244 exts = gatherExts streams triggers
173245
246+ -- Remove duplicates due to multiple guards for the same trigger.
247+ triggersNoDups = nubBy compareTrigger triggers
248+
249+ ifcArgId = BS. mkId BS. NoPos $ fromString ifcArgName
250+ ifcRulesArgId = BS. mkId BS. NoPos $ fromString ifcRulesArgName
251+
174252 ifcId = BS. mkId BS. NoPos $ fromString $ specIfcName prefix
175- ifcFields = mkSpecIfcFields triggers exts
253+ ifcFields = mkSpecIfcFields uniqueTriggers exts
176254 ifcTy = BS. TCon (BS. TyCon
177255 { BS. tcon_name = ifcId
178256 , BS. tcon_kind = Just BS. KStar
@@ -181,81 +259,90 @@ compileBS _bsSettings prefix spec =
181259 (map BS. cf_name ifcFields)
182260 })
183261
262+ ifcRulesId = BS. mkId BS. NoPos $ fromString $ specIfcRulesName prefix
263+ ifcRulesFields = mkSpecIfcRulesFields triggersNoDups exts
264+
265+ ifcRulesTy =
266+ BS. TCon $
267+ BS. TyCon
268+ { BS. tcon_name = ifcRulesId
269+ , BS. tcon_kind = Just BS. KStar
270+ , BS. tcon_sort =
271+ BS. TIstruct (BS. SInterface [] ) (map BS. cf_name ifcRulesFields)
272+ }
273+
184274 emptyTy = BS. TCon (BS. TyCon
185275 { BS. tcon_name = BS. idEmpty
186276 , BS. tcon_kind = Just BS. KStar
187277 , BS. tcon_sort = BS. TIstruct (BS. SInterface [] ) []
188278 })
189279
280+ -- Bind @Wire@ variables for each extern stream.
281+ mkExtWires :: [BS. CStmt ]
282+ mkExtWires = map extWireStmt exts
283+ where
284+ extWireStmt :: External -> BS. CStmt
285+ extWireStmt (External name ty) = mkExtWireDecln name ty
286+
190287 -- Make buffer and index declarations for streams.
191288 mkGlobals :: [BS. CStmt ]
192289 mkGlobals = concatMap buffDecln streams ++ map indexDecln streams
193290 where
194291 buffDecln (Stream sId buff _ ty) = mkBuffDecln sId ty buff
195292 indexDecln (Stream sId _ _ _ ) = mkIndexDecln sId
196293
197- -- Make generator functions, including trigger arguments .
294+ -- Make generator functions for streams .
198295 genFuns :: [BS. CDefl ]
199- genFuns = map accessDecln streams
200- ++ map streamGen streams
201- ++ concatMap triggerGen uniqueTriggers
296+ genFuns = map accessDecln streams ++ map streamGen streams
202297 where
203298 accessDecln :: Stream -> BS. CDefl
204299 accessDecln (Stream sId buff _ ty) = mkAccessDecln sId ty buff
205300
206301 streamGen :: Stream -> BS. CDefl
207302 streamGen (Stream sId _ expr ty) = mkGenFun (generatorName sId) expr ty
208303
209- triggerGen :: UniqueTrigger -> [BS. CDefl ]
210- triggerGen (UniqueTrigger uniqueName (Trigger _name guard args)) =
211- guardDef : argDefs
304+ -- Make interface methods for @<prefix>Ifc@.
305+ ifcMethodImpls :: [BS. CDefl ]
306+ ifcMethodImpls =
307+ concatMap triggerMethodImpls uniqueTriggers
308+ ++ map extMethodImpl exts
309+ where
310+ -- interface
311+ -- ext val = ext_wire := val
312+ extMethodImpl :: External -> BS. CDefl
313+ extMethodImpl (External name _) =
314+ BS. CLValue extMethodId [extMethodClause] []
315+ where
316+ extMethodId = BS. mkId BS. NoPos (fromString name)
317+ valId = BS. mkId BS. NoPos " val"
318+
319+ -- ext val = ext_wire := val
320+ extMethodClause :: BS. CClause
321+ extMethodClause =
322+ BS. CClause
323+ [BS. CPVar valId]
324+ []
325+ (BS. Cwrite
326+ BS. NoPos
327+ (BS. CVar (BS. mkId BS. NoPos (fromString (wireName name))))
328+ (BS. CVar valId))
329+
330+ -- interface
331+ -- trig_guard = ...
332+ -- trig_arg0 = ...
333+ -- ...
334+ -- trig_arg(n-1) = ...
335+ triggerMethodImpls :: UniqueTrigger -> [BS. CDefl ]
336+ triggerMethodImpls uniqueTrigger = guardDef : argDefs
212337 where
338+ UniqueTrigger uniqueName (Trigger _name guard args) = uniqueTrigger
339+
213340 guardDef = mkGenFun (guardName uniqueName) guard Bool
214341 argDefs = map argGen (zip (argNames uniqueName) args)
215342
216343 argGen :: (String , UExpr ) -> BS. CDefl
217344 argGen (argName, UExpr ty expr) = mkGenFun argName expr ty
218345
219- -- | Generate a @<prefix>Ifc.bs@ file from a 'Spec'. This contains the
220- -- definition of the @<prefix>Ifc@ interface, which declares the types of all
221- -- trigger functions and external variables. This is put in a separate file so
222- -- that larger applications can use it separately.
223- compileIfcBS :: BluespecSettings -> String -> Spec -> BS. CPackage
224- compileIfcBS _bsSettings prefix spec =
225- BS. CPackage
226- ifcPkgId
227- (Right [] )
228- (stdLibImports ++ genImports)
229- []
230- [ifcDef]
231- []
232- where
233- -- import <prefix>Types
234- genImports :: [BS. CImport ]
235- genImports =
236- [ BS. CImpId False $ BS. mkId BS. NoPos $ fromString
237- $ specTypesPkgName prefix
238- ]
239-
240- ifcId = BS. mkId BS. NoPos $ fromString $ specIfcName prefix
241- ifcPkgId = BS. mkId BS. NoPos $ fromString $ specIfcPkgName prefix
242- ifcFields = mkSpecIfcFields triggers exts
243-
244- streams = specStreams spec
245- exts = gatherExts streams triggers
246-
247- -- Remove duplicates due to multiple guards for the same trigger.
248- triggers = nubBy compareTrigger (specTriggers spec)
249-
250- ifcDef :: BS. CDefn
251- ifcDef = BS. Cstruct
252- True
253- (BS. SInterface [] )
254- (BS. IdK ifcId)
255- [] -- No type variables
256- ifcFields
257- [] -- No derived instances
258-
259346-- | Generate a @<prefix>Types.bs@ file from a 'Spec'. This declares the types
260347-- of any structs used by the Copilot specification. This is put in a separate
261348-- file so that larger applications can more easily substitute their own struct
0 commit comments