@@ -297,9 +297,18 @@ mpr_map mpr_map_new(int num_src, mpr_sig *src, int num_dst, mpr_sig *dst)
297297 mpr_list maps ;
298298 unsigned char i , j , is_local = 0 ;
299299
300+ /* we will allow simple self-maps to support "sourceless" maps */
301+ if (0 == num_src && 1 == num_dst ) {
302+ num_src = 1 ;
303+ src = dst ;
304+ }
305+
300306 RETURN_ARG_UNLESS (src && * src && dst && * dst , 0 );
301307 RETURN_ARG_UNLESS (num_src > 0 && num_src <= MAX_NUM_MAP_SRC , 0 );
302308
309+ /* Only 1 destination supported for now */
310+ RETURN_ARG_UNLESS (1 == num_dst , 0 );
311+
303312 for (i = 0 ; i < num_src ; i ++ ) {
304313 mpr_dev src_dev = mpr_sig_get_dev (src [i ]);
305314 /* check to make sure a src signal is not included more than once */
@@ -311,8 +320,8 @@ mpr_map mpr_map_new(int num_src, mpr_sig *src, int num_dst, mpr_sig *dst)
311320 }
312321 for (j = 0 ; j < num_dst ; j ++ ) {
313322 mpr_dev dst_dev = mpr_sig_get_dev (dst [j ]);
314- if (src [i ] == dst [j ]) {
315- trace ("Cannot connect signal '%s:%s' to itself.\n" ,
323+ if (src [i ] == dst [j ] && num_src > 1 ) {
324+ trace ("Cannot connect signal '%s:%s' to itself in a convergent map .\n" ,
316325 mpr_dev_get_name (src_dev ), mpr_sig_get_name (src [i ]));
317326 return 0 ;
318327 }
@@ -323,16 +332,14 @@ mpr_map mpr_map_new(int num_src, mpr_sig *src, int num_dst, mpr_sig *dst)
323332 trace ("Cannot create map between uninitialized devices unless they share a graph." );
324333 return 0 ;
325334 }
326- if (0 == mpr_sig_compare_names (src [i ], dst [j ])) {
327- trace ("Cannot connect signal '%s:%s' to itself.\n" ,
335+ if (0 == mpr_sig_compare_names (src [i ], dst [j ]) && num_src > 1 ) {
336+ trace ("Cannot connect signal '%s:%s' to itself in a convergent map .\n" ,
328337 mpr_dev_get_name (src_dev ), mpr_sig_get_name (src [i ]));
329338 return 0 ;
330339 }
331340 }
332341 is_local += mpr_obj_get_is_local ((mpr_obj )src [i ]);
333342 }
334- /* Only 1 destination supported for now */
335- RETURN_ARG_UNLESS (1 == num_dst , 0 );
336343 is_local += mpr_obj_get_is_local ((mpr_obj )* dst );
337344 g = mpr_obj_get_graph ((mpr_obj )* dst );
338345
@@ -1022,7 +1029,8 @@ mpr_time mpr_map_process(mpr_local_map m, mpr_time t_now)
10221029 /* check if source signals have a value for this instance */
10231030 /* TODO: check whether source signal is actually referenced in the map expression */
10241031 for (j = 0 ; j < m -> num_src ; j ++ ) {
1025- if (!mpr_value_get_has_value (src_vals [0 ], i ))
1032+ if ( mpr_local_slot_get_is_used (m -> src [0 ])
1033+ && !mpr_value_get_has_value (src_vals [0 ], i ))
10261034 break ;
10271035 }
10281036 if (j < m -> num_src )
@@ -1716,14 +1724,27 @@ static int set_expr(mpr_local_map m, const char *expr_str)
17161724 /* Special case: if we are the receiver and the new expression evaluates to
17171725 * a constant we can update immediately. */
17181726 /* TODO: should call handler for all instances updated through this map. */
1719- if (mpr_expr_get_num_src (m -> expr ) <= 0 && !m -> use_inst && mpr_obj_get_is_local ((mpr_obj )dst_sig )) {
1720- /* call handler if it exists */
1721- mpr_sig_call_handler ((mpr_local_sig )dst_sig , MPR_STATUS_UPDATE_REM , 0 , 0 );
1727+ if (!m -> use_inst && mpr_obj_get_is_local ((mpr_obj )dst_sig )) {
1728+ int num_src = mpr_expr_get_num_src (m -> expr ), i ;
1729+ for (i = 0 ; i < num_src ; i ++ ) {
1730+ if (mpr_expr_get_src_is_used (m -> expr , i )) {
1731+ break ;
1732+ }
1733+ }
1734+ if (i >= num_src ) {
1735+ /* apply update to all active destination instances */
1736+ mpr_value dst_val = mpr_slot_get_value (m -> dst );
1737+ void * value = mpr_value_get_value (dst_val , i , 0 );
1738+ mpr_local_sig_set_inst_value ((mpr_local_sig )dst_sig , value , -1 , & m -> id_map , EXPR_UPDATE ,
1739+ mpr_expr_get_manages_inst (m -> expr ), t_now );
1740+ }
17221741 }
17231742
1724- /* check whether each source slot causes computation */
1725- for (i = 0 ; i < m -> num_src ; i ++ )
1743+ /* check whether each source slot is referenced and should trigger evaluation */
1744+ for (i = 0 ; i < m -> num_src ; i ++ ) {
1745+ mpr_local_slot_set_is_used (m -> src [i ], mpr_expr_get_src_is_used (m -> expr , i ));
17261746 mpr_slot_set_causes_update ((mpr_slot )m -> src [i ], mpr_expr_get_src_causes_update (m -> expr , i ));
1747+ }
17271748
17281749 /* check whether expression manages recalculation scheduling */
17291750 if ((m -> is_self_timed = mpr_expr_get_manages_time (m -> expr ))) {
@@ -2236,7 +2257,6 @@ mpr_map mpr_map_new_from_str(const char *expr, ...)
22362257 va_end (aq );
22372258
22382259 TRACE_RETURN_UNLESS (dst , NULL , "Map format string '%s' has no output signal!\n" , expr );
2239- TRACE_RETURN_UNLESS (num_src , NULL , "Map format string '%s' has no input signals!\n" , expr );
22402260
22412261 /* create the map */
22422262 map = mpr_map_new (num_src , srcs , 1 , & dst );
0 commit comments