@@ -447,6 +447,179 @@ exprt verilog_typecheck_exprt::bits(const exprt &expr)
447447
448448/* ******************************************************************\
449449
450+ Function: verilog_typecheck_exprt::left
451+
452+ Inputs:
453+
454+ Outputs:
455+
456+ Purpose:
457+
458+ \*******************************************************************/
459+
460+ constant_exprt verilog_typecheck_exprt::left (const exprt &expr)
461+ {
462+ // unpacked array: left bound
463+ // packed array: index of most significant element
464+ // 0 otherwise
465+ auto left = [](const typet &type) -> mp_integer {
466+ if (
467+ type.id () == ID_unsignedbv || type.id () == ID_signedbv ||
468+ type.id () == ID_verilog_unsignedbv || type.id () == ID_verilog_signedbv ||
469+ type.id () == ID_bool)
470+ {
471+ auto offset = type.get_int (ID_C_offset);
472+ if (type.get_bool (ID_C_little_endian))
473+ return offset + get_width (type) - 1 ;
474+ else
475+ return offset;
476+ }
477+ else if (type.id () == ID_array)
478+ {
479+ auto offset = numeric_cast_v<mp_integer>(
480+ to_constant_expr (static_cast <const exprt &>(type.find (ID_offset))));
481+ if (type.get_bool (ID_C_little_endian))
482+ return offset +
483+ numeric_cast_v<mp_integer>(
484+ to_constant_expr (to_array_type (type).size ())) -
485+ 1 ;
486+ else
487+ return offset;
488+ }
489+ else
490+ return 0 ;
491+ };
492+
493+ return from_integer (left (expr.type ()), integer_typet{});
494+ }
495+
496+ /* ******************************************************************\
497+
498+ Function: verilog_typecheck_exprt::right
499+
500+ Inputs:
501+
502+ Outputs:
503+
504+ Purpose:
505+
506+ \*******************************************************************/
507+
508+ constant_exprt verilog_typecheck_exprt::right (const exprt &expr)
509+ {
510+ // unpacked array: right bound
511+ // packed array: index of least significant element
512+ // 0 otherwise
513+ auto right = [](const typet &type) -> mp_integer {
514+ if (
515+ type.id () == ID_unsignedbv || type.id () == ID_signedbv ||
516+ type.id () == ID_verilog_unsignedbv || type.id () == ID_verilog_signedbv ||
517+ type.id () == ID_bool)
518+ {
519+ auto offset = type.get_int (ID_C_offset);
520+ if (type.get_bool (ID_C_little_endian))
521+ return offset;
522+ else
523+ return offset + get_width (type) - 1 ;
524+ }
525+ else if (type.id () == ID_array)
526+ {
527+ auto offset = numeric_cast_v<mp_integer>(
528+ to_constant_expr (static_cast <const exprt &>(type.find (ID_offset))));
529+ if (type.get_bool (ID_C_little_endian))
530+ return offset;
531+ else
532+ return offset +
533+ numeric_cast_v<mp_integer>(
534+ to_constant_expr (to_array_type (type).size ())) -
535+ 1 ;
536+ }
537+ else
538+ return 0 ;
539+ };
540+
541+ return from_integer (right (expr.type ()), integer_typet{});
542+ }
543+
544+ /* ******************************************************************\
545+
546+ Function: verilog_typecheck_exprt::increment
547+
548+ Inputs:
549+
550+ Outputs:
551+
552+ Purpose:
553+
554+ \*******************************************************************/
555+
556+ constant_exprt verilog_typecheck_exprt::increment (const exprt &expr)
557+ {
558+ // fixed-size dimension: 1 if $left >= $right, -1 otherwise
559+ auto increment = [](const typet &type) -> mp_integer {
560+ if (
561+ type.id () == ID_unsignedbv || type.id () == ID_signedbv ||
562+ type.id () == ID_verilog_unsignedbv || type.id () == ID_verilog_signedbv ||
563+ type.id () == ID_array)
564+ {
565+ if (type.get_bool (ID_C_little_endian))
566+ return 1 ;
567+ else
568+ return -1 ;
569+ }
570+ else
571+ return -1 ;
572+ };
573+
574+ return from_integer (increment (expr.type ()), integer_typet{});
575+ }
576+
577+ /* ******************************************************************\
578+
579+ Function: verilog_typecheck_exprt::low
580+
581+ Inputs:
582+
583+ Outputs:
584+
585+ Purpose:
586+
587+ \*******************************************************************/
588+
589+ constant_exprt verilog_typecheck_exprt::low (const exprt &expr)
590+ {
591+ // $left if $increment returns –1
592+ // $right otherwise
593+ if (numeric_cast_v<mp_integer>(increment (expr)) == -1 )
594+ return left (expr);
595+ else
596+ return right (expr);
597+ }
598+
599+ /* ******************************************************************\
600+
601+ Function: verilog_typecheck_exprt::high
602+
603+ Inputs:
604+
605+ Outputs:
606+
607+ Purpose:
608+
609+ \*******************************************************************/
610+
611+ constant_exprt verilog_typecheck_exprt::high (const exprt &expr)
612+ {
613+ // $right if $increment returns –1
614+ // $left otherwise
615+ if (numeric_cast_v<mp_integer>(increment (expr)) == -1 )
616+ return right (expr);
617+ else
618+ return left (expr);
619+ }
620+
621+ /* ******************************************************************\
622+
450623Function: verilog_typecheck_exprt::convert_system_function
451624
452625 Inputs:
@@ -549,12 +722,14 @@ exprt verilog_typecheck_exprt::convert_system_function(
549722 expr.type () = arguments.front ().type ();
550723 return std::move (expr);
551724 }
552- else if (identifier == " $bits" )
725+ else if (
726+ identifier == " $bits" || identifier == " $left" || identifier == " $right" ||
727+ identifier == " $increment" || identifier == " $low" || identifier == " $high" )
553728 {
554729 if (arguments.size () != 1 )
555730 {
556731 throw errort ().with_location (expr.source_location ())
557- << " $bits takes one argument" ;
732+ << identifier << " takes one argument" ;
558733 }
559734
560735 // The return type is integer.
@@ -1370,6 +1545,31 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
13701545 DATA_INVARIANT (arguments.size () == 1 , " $bits has one argument" );
13711546 return bits (arguments[0 ]);
13721547 }
1548+ else if (identifier == " $low" )
1549+ {
1550+ DATA_INVARIANT (arguments.size () == 1 , " $low has one argument" );
1551+ return low (arguments[0 ]);
1552+ }
1553+ else if (identifier == " $high" )
1554+ {
1555+ DATA_INVARIANT (arguments.size () == 1 , " $high has one argument" );
1556+ return high (arguments[0 ]);
1557+ }
1558+ else if (identifier == " $left" )
1559+ {
1560+ DATA_INVARIANT (arguments.size () == 1 , " $left has one argument" );
1561+ return left (arguments[0 ]);
1562+ }
1563+ else if (identifier == " $right" )
1564+ {
1565+ DATA_INVARIANT (arguments.size () == 1 , " $right has one argument" );
1566+ return right (arguments[0 ]);
1567+ }
1568+ else if (identifier == " $increment" )
1569+ {
1570+ DATA_INVARIANT (arguments.size () == 1 , " $increment has one argument" );
1571+ return increment (arguments[0 ]);
1572+ }
13731573 else if (identifier == " $clog2" )
13741574 {
13751575 // the ceiling of the log with base 2 of the argument
0 commit comments