@@ -443,7 +443,21 @@ exprt verilog_synthesist::expand_function_call(
443443 throw errort ().with_location (call.source_location ())
444444 << " function call cannot call task" ;
445445 }
446-
446+
447+ // preserve the previous call frame, if any
448+ auto old_tf_frame = tf_frame;
449+
450+ // remember the guard
451+ auto entry_guard = value_map->guard ;
452+
453+ // create a fresh call frame
454+ tf_frame = tf_framet{};
455+
456+ const symbolt &return_symbol =
457+ ns.lookup (id2string (symbol.name ) + " ." + id2string (symbol.base_name ));
458+
459+ tf_frame.value ().return_value = return_symbol.symbol_expr ();
460+
447461 const code_typet::parameterst ¶meters=
448462 code_type.parameters ();
449463
@@ -472,14 +486,22 @@ exprt verilog_synthesist::expand_function_call(
472486 for (auto &statement : symbol.value .operands ())
473487 synth_statement (to_verilog_statement (statement));
474488
475- // replace function call by return value symbol
476- const symbolt &return_symbol=
477- ns.lookup (id2string (symbol.name )+" ." +
478- id2string (symbol.base_name ));
489+ // merge in edges from 'return' statements, if any
490+ for (auto &state : tf_frame.value ().return_statement_states )
491+ {
492+ auto guard_expr = conjunction (state.guard );
493+ merge (
494+ guard_expr, state.current , value_map->current , false , value_map->current );
495+ merge (guard_expr, state.final , value_map->final , true , value_map->final );
496+ }
479497
480- // get the current value
498+ // replace function call by return value symbol
481499 auto result = synth_expr (return_symbol.symbol_expr (), symbol_statet::CURRENT);
482500
501+ // restore the previous task/function frame
502+ tf_frame = old_tf_frame;
503+ value_map->guard = entry_guard;
504+
483505 return result;
484506}
485507
@@ -3076,6 +3098,47 @@ void verilog_synthesist::synth_repeat(
30763098
30773099/* ******************************************************************\
30783100
3101+ Function: verilog_synthesist::synth_return
3102+
3103+ Inputs:
3104+
3105+ Outputs:
3106+
3107+ Purpose:
3108+
3109+ \*******************************************************************/
3110+
3111+ void verilog_synthesist::synth_return (const verilog_returnt &statement)
3112+ {
3113+ // There has to be a tf frame
3114+ PRECONDITION (tf_frame.has_value ());
3115+
3116+ auto &frame = tf_frame.value ();
3117+
3118+ // return value?
3119+ if (statement.has_value ())
3120+ {
3121+ // assign to the symbol with the function's name
3122+ DATA_INVARIANT (
3123+ frame.return_value .has_value (),
3124+ " return with value requires return value symbol" );
3125+
3126+ verilog_assignt assignment{
3127+ ID_verilog_blocking_assign,
3128+ frame.return_value .value (),
3129+ statement.value ()};
3130+
3131+ synth_assign (assignment);
3132+ }
3133+
3134+ frame.return_statement_states .push_back (*value_map);
3135+
3136+ // set guard to false
3137+ value_map->guard .push_back (false_exprt{});
3138+ }
3139+
3140+ /* ******************************************************************\
3141+
30793142Function: verilog_synthesist::synth_forever
30803143
30813144 Inputs:
@@ -3132,6 +3195,15 @@ void verilog_synthesist::synth_function_call_or_task_enable(
31323195
31333196 const code_typet &code_type=to_code_type (symbol.type );
31343197
3198+ // preserve the previous call frame, if any
3199+ auto old_tf_frame = tf_frame;
3200+
3201+ // remember the guard
3202+ auto entry_guard = value_map->guard ;
3203+
3204+ // create a fresh call frame
3205+ tf_frame = tf_framet{};
3206+
31353207 const code_typet::parameterst ¶meters=
31363208 code_type.parameters ();
31373209
@@ -3158,6 +3230,23 @@ void verilog_synthesist::synth_function_call_or_task_enable(
31583230 for (auto &statement : symbol.value .operands ())
31593231 synth_statement (to_verilog_statement (statement));
31603232
3233+ // merge in edges from 'return' statements, if any
3234+ for (auto &state : tf_frame.value ().return_statement_states )
3235+ {
3236+ auto guard_expr = conjunction (state.guard );
3237+ merge (
3238+ guard_expr,
3239+ state.current ,
3240+ value_map->current ,
3241+ false ,
3242+ value_map->current );
3243+ merge (guard_expr, state.final , value_map->final , true , value_map->final );
3244+ }
3245+
3246+ // restore the previous task/function frame
3247+ tf_frame = old_tf_frame;
3248+ value_map->guard = entry_guard;
3249+
31613250 // do assignments to output parameters
31623251 for (unsigned i=0 ; i<parameters.size (); i++)
31633252 {
@@ -3266,10 +3355,7 @@ void verilog_synthesist::synth_statement(
32663355 else if (statement.id ()==ID_repeat)
32673356 synth_repeat (to_verilog_repeat (statement));
32683357 else if (statement.id () == ID_return)
3269- {
3270- throw errort ().with_location (statement.source_location ())
3271- << " synthesis of return not supported" ;
3272- }
3358+ synth_return (to_verilog_return (statement));
32733359 else if (statement.id ()==ID_forever)
32743360 synth_forever (to_verilog_forever (statement));
32753361 else if (statement.id ()==ID_function_call)
0 commit comments