@@ -447,6 +447,179 @@ exprt verilog_typecheck_exprt::bits(const exprt &expr)
447
447
448
448
/* ******************************************************************\
449
449
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
+
450
623
Function: verilog_typecheck_exprt::convert_system_function
451
624
452
625
Inputs:
@@ -549,12 +722,14 @@ exprt verilog_typecheck_exprt::convert_system_function(
549
722
expr.type () = arguments.front ().type ();
550
723
return std::move (expr);
551
724
}
552
- else if (identifier == " $bits" )
725
+ else if (
726
+ identifier == " $bits" || identifier == " $left" || identifier == " $right" ||
727
+ identifier == " $increment" || identifier == " $low" || identifier == " $high" )
553
728
{
554
729
if (arguments.size () != 1 )
555
730
{
556
731
throw errort ().with_location (expr.source_location ())
557
- << " $bits takes one argument" ;
732
+ << identifier << " takes one argument" ;
558
733
}
559
734
560
735
// The return type is integer.
@@ -1370,6 +1545,31 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
1370
1545
DATA_INVARIANT (arguments.size () == 1 , " $bits has one argument" );
1371
1546
return bits (arguments[0 ]);
1372
1547
}
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
+ }
1373
1573
else if (identifier == " $clog2" )
1374
1574
{
1375
1575
// the ceiling of the log with base 2 of the argument
0 commit comments