@@ -188,20 +188,27 @@ struct SmtrModule {
188188 Functional::IR ir;
189189 SmtrScope scope;
190190 std::string name;
191-
191+ bool use_assoc_list_helpers;
192+ std::optional<std::string> input_helper_name;
193+ std::optional<std::string> output_helper_name;
194+
192195 SmtrStruct input_struct;
193196 SmtrStruct output_struct;
194197 SmtrStruct state_struct;
195198
196- SmtrModule (Module *module )
197- : ir(Functional::IR::from_module(module ))
198- , scope()
199- , name(scope.unique_name(module ->name))
200- , input_struct(scope.unique_name(module ->name.str() + " _Inputs" ), scope)
201- , output_struct(scope.unique_name(module ->name.str() + " _Outputs" ), scope)
202- , state_struct(scope.unique_name(module ->name.str() + " _State" ), scope)
199+ SmtrModule (Module *module , bool assoc_list_helpers)
200+ : ir(Functional::IR::from_module(module )), scope(), name(scope.unique_name(module ->name)), use_assoc_list_helpers(assoc_list_helpers),
201+ input_struct (scope.unique_name(module ->name.str() + "_Inputs"), scope),
202+ output_struct(scope.unique_name(module ->name.str() + "_Outputs"), scope),
203+ state_struct(scope.unique_name(module ->name.str() + "_State"), scope)
203204 {
204205 scope.reserve (name + " _initial" );
206+ if (assoc_list_helpers) {
207+ input_helper_name = scope.unique_name (module ->name .str () + " _inputs_helper" );
208+ scope.reserve (*input_helper_name);
209+ output_helper_name = scope.unique_name (module ->name .str () + " _outputs_helper" );
210+ scope.reserve (*output_helper_name);
211+ }
205212 for (auto input : ir.inputs ())
206213 input_struct.insert (input->name , input->sort );
207214 for (auto output : ir.outputs ())
@@ -257,6 +264,45 @@ struct SmtrModule {
257264 w.pop ();
258265 }
259266
267+ void write_assoc_list_helpers (SExprWriter &w)
268+ {
269+ log_assert (output_helper_name && input_helper_name);
270+
271+ // Input struct keyword-based constructor.
272+ w.push ();
273+ w.open (list (" define" ));
274+ const auto inputs_name = " inputs" ;
275+ w.open (list (*input_helper_name, inputs_name));
276+ w.close ();
277+ w.open (list (input_struct.name ));
278+ for (auto input : ir.inputs ()) {
279+ w.push ();
280+ w.open (list (" let" ));
281+ w.push ();
282+ w.open (list ());
283+ w.open (list (" assoc-result" ));
284+ w << list (" assoc" , " \" " + RTLIL::unescape_id (input->name ) + " \" " , inputs_name);
285+ w.pop ();
286+ w.open (list (" if" , " assoc-result" ));
287+ w << list (" cdr" , " assoc-result" );
288+ w.open (list (" begin" ));
289+ w << list (" fprintf" , list (" current-error-port" ), " \" %s not found in inputs\" " );
290+ w << " 'not-found" ;
291+ w.pop ();
292+ }
293+ w.pop ();
294+ // Output struct keyword-based destructuring
295+ w.push ();
296+ w.open (list (" define" ));
297+ const auto outputs_name = " outputs" ;
298+ w << list (*output_helper_name, outputs_name);
299+ w.open (list (" list" ));
300+ for (auto output : ir.outputs ()) {
301+ w << list (" cons" , " \" " + RTLIL::unescape_id (output->name ) + " \" " , output_struct.access (" outputs" , output->name ));
302+ }
303+ w.pop ();
304+ }
305+
260306 void write (std::ostream &out)
261307 {
262308 SExprWriter w (out);
@@ -265,6 +311,10 @@ struct SmtrModule {
265311 output_struct.write_definition (w);
266312 state_struct.write_definition (w);
267313
314+ if (use_assoc_list_helpers) {
315+ write_assoc_list_helpers (w);
316+ }
317+
268318 write_eval (w);
269319 write_initial (w);
270320 }
@@ -282,12 +332,16 @@ struct FunctionalSmtrBackend : public Backend {
282332 log (" \n " );
283333 log (" -provides\n " );
284334 log (" include 'provide' statement(s) for loading output as a module\n " );
335+ log (" -assoc-list-helpers\n " );
336+ log (" provide helper functions which convert inputs/outputs from/to association lists\n " );
337+ log (" \n " );
285338 log (" \n " );
286339 }
287340
288341 void execute (std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
289342 {
290343 auto provides = false ;
344+ auto assoc_list_helpers = false ;
291345
292346 log_header (design, " Executing Functional Rosette Backend.\n " );
293347
@@ -296,6 +350,8 @@ struct FunctionalSmtrBackend : public Backend {
296350 {
297351 if (args[argidx] == " -provides" )
298352 provides = true ;
353+ else if (args[argidx] == " -assoc-list-helpers" )
354+ assoc_list_helpers = true ;
299355 else
300356 break ;
301357 }
@@ -307,8 +363,8 @@ struct FunctionalSmtrBackend : public Backend {
307363 }
308364
309365 for (auto module : design->selected_modules ()) {
310- log (" Processing module `%s`.\n " , module ->name );
311- SmtrModule smtr (module );
366+ log (" Processing module `%s`.\n " , module ->name . c_str () );
367+ SmtrModule smtr (module , assoc_list_helpers );
312368 smtr.write (*f);
313369 }
314370 }
0 commit comments