Preprocessor for Verilog, SystemVerilog

DownLoad PDF Version Here

Contents

  1. Introduction
  2. Operation
  3. Syntax, Keywords
  4. Command Line options
  5. Example of input file
  6. Output of vpp.pl
  7. Complete script: vpp.pl

Introduction

This is a generic Preprocessor / Macro Processor / Template Processor.

Syntax is different from m4, C preprocessor, Verilog preprocessor.

Since this is a generic text preprocessor, can be used for C, Verilog …

vpp.pl includes documentation of Syntax of input file. Jump to last section for the script.

Why to have another preprocessor for SystemVerilog?

SV is a verbose language. This preprocessor can be used to create template for reuse.

Vpp.pl has more features like for loop, can use perl data types, etc.

For example, UVM testbench skeleton can be made as a template; Use vpp.pl to generate files for agent, driver, monitor, … with uniform naming convention.

Operation

vpp.pl converts input files into perl code. Vpp.pl -p will show generated perl code.

The generated perl code is written as input to perl.

If there are no syntax errors, output is printed. If -o file option is used,

output is written to file instead of stdout.

If there are any syntax errors, error message may be about {, }, (, ), bad words, …,

Exact error in input file can’t be shown. Only location of line, file will be printed.

Syntax, Keywords

Syntax All Keywords Must start at begin of line and end with newline char

Leading spaces will be removed.

Exceptions: $get, $esc, macro calls – $user_defined_macro(…)

Keywords Meaning and Usage

$dnl Delete till newline character. Can be used to write comments

Example: This a line^ $dnl Read all comments. Leading spaces removed

This line will get joined to previous line, immediately after ‘^’

$macro Start of macro definition. Example:

$macro name $dnl Use ‘name’ for definition, Use $name for macro call

arg1 is $get($_[0])

arg2 is $get($_[1])

$end

Macro call: $name(‘arg1′,’arg2’)

$for Example:

$for my $i (1..10)

Iterator is $get($i)

$end

$set Perl Statement that ends with a ‘;’

Example:

$set $x = 5 $dnl Omit ending ‘;’

Value of $x is $get($x)

$begin Use this for perl statements that have ‘{‘

Example:

$begin if($_[0])

$begin while(1)

infinite loop

$end

$end

$begin elsif($_[1])

$begin if($_[2])

true part

$end

$begin else

false part

$end

$end

$end $macro, $for, $begin must end with matching $end

$esc Used to escape characters: ‘$’, ‘(‘, ‘)’

Example:

Use $name(‘$esc(left paran’) in place of $name(‘(left paran’)

Escape keywords: $esc$macro becomes $macro

$get Used to insert value of variables in plain text. See above examples

Can’t be used in lines with $macro, $for, $begin, $set, $end

Example: $get(‘string’) For ‘(‘, ‘)’ within $get, $esc must be used

Same rules of $get apply for user-defined-macro calls

Command line options

USAGE ./vpp.pl files [-o file] [-p] [-s] [-h]

-o Write/Over-Write to file

-p Show Generated Perl Code

-s Show Syntax for input file

-h Show Command line options

Example of input file

******* input.v begins after this line *******

1 abcdefghijklmnopqrstuvwxyz

$macro func

2 ab$get($_[0])cdefg$get (“$esc)”)hijklmnopqrstuvwxyz

$end

3 abcdefghi<<$esc$display>>jklmnopqrstuvwxyz

4 abcdefghijklmnopqrstuvwxyz

5 abcdefg<<$esc($esc)>>hijklmnopqrstuvwxyz

6 abcdefghijklmnopqrstuvwxyz

7 abcdefgh$esc$$$ijklmnopqrs$dnltuvwxyz

8 abcdefghijklmnopqrstuvwxy$esc$escz

9 abcdefghijklmnopqrstuvwxyz

$func(‘FIRST_ARGUMENT’)

$for(1..10) $dnl

$set $x = “argument”

$get($x) is $get($_)

$end

Printing all keyboard characters

a b c d e f g h i j k l m n o p q r s t u v w x y z

A B C D E F G H I J K L M N O P Q R S T U V W Z Y Z

1 2 3 4 5 6 7 8 9 0

! @ # $ % ^ & * ( )

` ~ – _ = +

[ { ] } \ |

; : ‘ ”

, < . > / ?

Output of vpp.pl

1 abcdefghijklmnopqrstuvwxyz

3 abcdefghi<<$display>>jklmnopqrstuvwxyz

4 abcdefghijklmnopqrstuvwxyz

5 abcdefg<<()>>hijklmnopqrstuvwxyz

6 abcdefghijklmnopqrstuvwxyz

7 abcdefgh$$$ijklmnopqrs8 abcdefghijklmnopqrstuvwxy$escz

9 abcdefghijklmnopqrstuvwxyz

2 abFIRST_ARGUMENTcdefg)hijklmnopqrstuvwxyz

argument is 1

argument is 2

argument is 3

argument is 4

argument is 5

argument is 6

argument is 7

argument is 8

argument is 9

argument is 10

Printing all keyboard characters

a b c d e f g h i j k l m n o p q r s t u v w x y z

A B C D E F G H I J K L M N O P Q R S T U V W Z Y Z

1 2 3 4 5 6 7 8 9 0

! @ # $ % ^ & * ( )

` ~ – _ = +

[ { ] } \ |

; : ‘ “

, < . > / ?

Complete Script: vpp.pl

******* vpp.pl begins after this line *******

#!/usr/bin/perl

# Author : A.G.Raja

# Description : m4 < This Preprocessor <= perl

############## PART1 : Parse Arguments #########################

my $outf = “STDOUT”; my $args = “”; my @infiles; my $genpl=0; my @cmd_out;

sub help { print STDERR “\n$_[0]\n\nUSAGE\t$0 files [-o file] [-p] [-s] [-h]\n\n”;

print STDERR “\t-o\tWrite/Over-Write to file\n”;

print STDERR “\t-p\tShow Generated Perl Code\n”;

print STDERR “\t-s\tShow Syntax for input file\n”;

print STDERR “\t-h\tShow Command line options\n”;

exit; }

sub parse_arguments {

for(my $in=0;$in<=$#ARGV;$in++) {

if($ARGV[$in] =~ /^\-o/) { $in++; $outf=$ARGV[$in]; }

elsif($ARGV[$in] =~ /^\-h/) { &help(“$0 converts input->perl_code->output”); }

elsif($ARGV[$in] =~ /^\-s/) { while(<DATA>) {print;} &help(“Command line options”); }

elsif($ARGV[$in] =~ /^\-p/) { $genpl=1; }

elsif($ARGV[$in] =~ /^\-/) { &help(“ERROR\tInvalid option ‘$ARGV[$in]’\n”); }

else { $args .= “$ARGV[$in] “; push(@infiles,$ARGV[$in]); } }

if($args !~ /\w+/) { &help(“ERROR\tNo input files specified\n”); }

if($outf =~ />\s*$/) { &help(“ERROR\tNo output file specified\n”); } }

############## PART2 : Text2Perl Conversion ####################

my $tt = “TEXT”; my $ee = “ESCAPE”; my $bt=”BEGIN$tt”; my $et=”END$tt”;

my $esn = $ee.”N”; my $esl = $ee.”L”; my $esr = $ee.”R”; my $esd = $ee.”D”;

my %hash; $hash{“get”}=”print”;

sub define_macro { my $n = shift; $n=~ s/\s//g; $hash{$n}=$n; }

sub macro_call {

my $out=””; my $func=””; my @l;

@l = split(/(\$\w+\s*\(|\))/,shift);

for(my $i=0;$i<=$#l;$i++) {

if($l[$i]=~/\$(\w+)/) {

$func=$hash{$1};

if($func ne “”) {

$out .= “$et $func(” ; $i++;

$out .= $l[$i] ; $i++;

$out .= “$l[$i]; $bt”; next; } }

$out .= $l[$i]; }

return $out; }

sub print_text {

my $in = shift;

if($in eq “”) { return “”; }

$in =~ s/\\/\\\\/g;

$in =~ s/\’/\\\’/g;

return “print ‘$in’;”; }

sub perl_code {

my ($prefix,$middle,$suffix,) = @_; my $ret;

$ret = “$et $prefix”;

if($middle =~ /(.*)$et($esn$bt)/) {

$ret .= “$1 $suffix$2”;

if($prefix eq “sub”) { &define_macro($1); } }

else {

if($prefix eq “sub”) { &define_macro($middle); }

$ret .= “$middle $suffix\n$bt”; }

return $ret; }

sub parse {

my $l = shift;

#$l=~s/\r//; # Uncomment This Line to run on Windows OS

$l=~s/[\$]esc\$/$esd/g;

$l=~s/[\$]esc\(/$esl/g;

$l=~s/[\$]esc\)/$esr/g;

$l=~s/[\$]dnl.*\n/$et$esn$bt/;

if($l=~/^\s*[\$]macro(.*)/) { $l = &perl_code(“sub”,$1,”{“); }

elsif($l=~/^\s*[\$]for(.*)/) { $l = &perl_code(“for”,$1,”{“); }

elsif($l=~/^\s*[\$]begin(.*)/) { $l = &perl_code(“” ,$1,”{“); }

elsif($l=~/^\s*[\$]set(.*)/) { $l = &perl_code(“” ,$1,”;”); }

elsif($l=~/^\s*[\$]end.*/) { $l = &perl_code(“}” ,””,”” ); }

else { $l = &macro_call($l); }

$l=~s/$esl/(/g;

$l=~s/$esr/)/g;

$l=~s/$esd/\$/g;

$l=~s/$esn/\n/g;

return $l; }

sub text2perl {

my $Text = shift;

my $out=””; my $pl=0; my @l;

@l = split(/($bt|$et|\n)/,$$Text);

for(@l) {

if($_ eq “$bt”) { $pl=0; }

elsif($_ eq “$et”) { $pl=1; }

elsif($_ eq “\n”) { $out .= $pl ? “\n” : “print \”\\n\”;\n”; }

else { $out .= $pl ? $_ : &print_text($_); } }

print “$out print \”Text2Perl Completed\”;”; }

############## PART3 : VPP – Generate Output ###################

sub vpp {

@cmd_out = `$0 -p $args | perl 2>&1`;

if($cmd_out[$#cmd_out]=~/Text2Perl Completed$/) {

$cmd_out[$#cmd_out]=~s/Text2Perl Completed$//;

if($outf eq “STDOUT”) { for(@cmd_out) {print;} exit; }

open(FILE,”>$outf”) or &help(“Can’t Write file ‘$outf'”);

for(@cmd_out) {print FILE;}

close(FILE);

return 1; }

return 0; }

my @b; my @e;

sub file_name {

my $ln = shift; my $act;

for(my $i=0;$i<=$#b;$i++) {

if( ($ln>$b[$i]) && ($ln<=$e[$i]+1) ) {

$act = $ln-$b[$i];

return “$act in ‘$infiles[$i]'”; } }

return “$ln”; }

sub report_errors {

my $line; my $curr=0;

for my $inf (@infiles) {

push(@b,$curr);

open(TEMP,”<$inf”) or last;

$line=0; while(<TEMP>) {$line++;}

close(TEMP);

$curr+=$line;

push(@e,$curr); }

for(@cmd_out) {

if(/\-\s*line\s*(\d+)/) {

$actual = &file_name($1);

s/(\-\s*line\s*)\d+/$1$actual/; }

print $_; } }

############## PART4 : Select Text2Perl / VPP ##################

&parse_arguments();

if(!$genpl) {

if(!&vpp()) { &report_errors(); }

exit; }

my $text=””;

for my $inf (@infiles) {

open(TEMP,”<$inf”) or last;

while(<TEMP>) { $text.=&parse($_); }

close(TEMP); }

&text2perl(\$text);

__DATA__

Syntax, Keywords, Usage Examples

Syntax All Keywords Must start at begin of line and end with newline char

Leading spaces will be removed.

Exceptions: $get, $esc, macro calls – $user_defined_macro(…)

Keywords Meaning and Usage

$dnl Delete till newline character. Can be used to write comments

Example: This a line^ $dnl Read all comments. Leading spaces removed

This line will get joined to previous line, immediately after ‘^’

$macro Start of macro definition. Example:

$macro name $dnl Use ‘name’ for definition, Use $name for macro call

arg1 is $get($_[0])

arg2 is $get($_[1])

$end

Macro call: $name(‘arg1′,’arg2’)

$for Example:

$for my $i (1..10)

Iterator is $get($i)

$end

$set Perl Statement that ends with a ‘;’

Example:

$set $x = 5 $dnl Omit ending ‘;’

Value of $x is $get($x)

$begin Use this for perl statements that have ‘{‘

Example:

$begin if($_[0])

$begin while(1)

infinite loop

$end

$end

$begin elsif($_[1])

$begin if($_[2])

true part

$end

$begin else

false part

$end

$end

$end $macro, $for, $begin must end with matching $end

$esc Used to escape characters: ‘$’, ‘(‘, ‘)’

Example:

Use $name(‘$esc(left paran’) in place of $name(‘(left paran’)

Escape keywords: $esc$macro becomes $macro

$get Used to insert value of variables in plain text. See above examples

Can’t be used in lines with $macro, $for, $begin, $set, $end

Example: $get(‘string’) For ‘(‘, ‘)’ within $get, $esc must be used

Same rules of $get apply for user-defined-macro calls

Advertisements

System Verilog Singleton Example

Purpose of a singleton:
To have a class which has only one instance(object)
All the objects of this class refer to same global object
that is created only once
This design pattern provides a mechanism for providing
namespaces to global variables

Download here. singleton-design-pattern
C++ example for singleton design pattern: click here

System Verilog example for singleton design pattern

// Filename  : singleton.sv
// Author    : A.G.Raja
// License   : GPL
// Website   : https://agraja.wordpress.com

module tb;

class Singleton;
// object that is created only once
extern static Singleton single;
// constructor that is called only once
extern function new;
// method to get object
extern function Singleton get_instance;
// data to check the functionality
int data;
endclass

initial Singleton::single = null;

function Singleton::new;
data = 14;
endfunction

function Singleton Singleton::get_instance;
// call the constructor for the first time
// if the object has been created already
// return reference to the object already created
if(single==null) single = new;
// return the reference to the object
return single;
endfunction

Singleton s, t;

initial begin
// don’t use s= new;
// since it will create new instances
// instead use the get_instance method
s = s.get_instance();
t = t.get_instance();
$display(“initial value of s.data  = “,s.data);
s.data = 25;
$display(“modified value of s.data = “,s.data);
$display(“value of t.data          = “,t.data);
end
endmodule

Result:
initial value of s->data  = 14
modified value of s->data = 25
value of t->data          = 25
Download here. singleton-design-pattern

C++ Singleton Example

Download here.  singleton-design-pattern

Purpose of a singleton:
To have a class which has only one instance(object)
All the objects of this class refer to same global object
that is created only once
This design pattern provides a mechanism for providing
namespaces to global variables

C++ example for singleton design pattern

// Filename  : singleton.cpp
// Author    : A.G.Raja
// License   : GPL
// Website   : https://agraja.wordpress.com

#include <iostream>

using namespace std;

class Singleton {
// constructor that is called only once
Singleton();
// object that is created only once
static Singleton *single;
public:
// method to get object
Singleton* get_instance();
// data to check the functionality
int data;
};

Singleton* Singleton::single = NULL;

Singleton* Singleton::get_instance() {
// call the constructor for the first time
// if the object has been created already
// return reference to the object already created
if(single==NULL) single = new Singleton();
return single;
}

Singleton::Singleton() {
data = 14;
}

int main() {
Singleton *s, *t ;
s = s->get_instance();
cout<<“initial value of s->data  = “<<s->data<<endl;
s->data = 25;
cout<<“modified value of s->data = “<<s->data<<endl;
t = t->get_instance();
cout<<“value of t->data          = “<<t->data<<endl;
}
// end of file singleton.cpp

Result:
initial value of s->data  = 14
modified value of s->data = 25
value of t->data          = 25

Download here.  singleton-design-pattern

C++ string, wstring conversion functions

Download here. string-wstring-conversion-functions

// Filename    : string_wstring.cpp
// Author      : A.G.Raja
// License     : GPL
// Website     : https://agraja.wordpress.com

#include <iostream>

using namespace std;

string wstring2string(wstring wstr) {
string str(wstr.length(),’ ‘);
copy(wstr.begin(),wstr.end(),str.begin());
return str;
}

wstring string2wstring(string str) {
wstring wstr(str.length(),L’ ‘);
copy(str.begin(),str.end(),wstr.begin());
return wstr;
}

int main() {
wstring wstr = string2wstring(“raja”);
string str = wstring2string(wstr);
cout<<str<<endl;
}

Download here. string-wstring-conversion-functions

C++ String Getline Class

Download here. getline

Features of the below string getline class

1) Can be used like getline function for streams

2) Can have multiple delimiters as opposed to the getline function for streams

3) Delimiter need not be single char. It can be a string

4) Pointer to current position in the string is automatically incremented

similar to that in stringstream

5) It is possible to rewind the pointer position to zero using the rewind() method.

6) It is also possible to get single char at the current position of pointer from the string

7) It is possible to get single char at current pointer position if it is one of the

characters of the list.  This is an optional argument to the get method

8) stream getline feature can be realized by calling the getline method of this

class without passing any arguments. No arguments to getline method defaults to

newline char as delimiter

// File : Getline.hh
// Author : A.G.Raja
// License : GPL
// Website : https://agraja.wordpress.com

#include <iostream>

using namespace std;

class Getline {
string text, buffer;
int pos,p;
public:
int str(string txt) {
pos = 0;
this->text = txt;
}
string getline(string delim = “\n”, int delim_type = 1);
char get(string delim = “”);
int unget(int decr = 1) {
pos -= decr;
}
int end() {
if(pos>=text.size()) return 1;
else return 0;
}
int rewind() {
pos = 0;
}
};

string Getline::getline(string delim, int delim_type) {
p = delim_type ? text.find(delim,pos)
: text.find_first_of(delim,pos);
if(p!=-1) {
buffer = text.substr(pos,p-pos);
pos = delim_type ? p+delim.length() : p +1;
} else {
buffer = text.substr(pos);
pos += buffer.length();
} return buffer;
}

char Getline::get(string delim) {
if(delim.empty() and pos<text.size()) return text[pos++];
if(delim.find(text[pos])!=-1) {
pos++;
return text[pos-1];
}
return 0; // must
}

// End of File Getline.hh

// File : test_Getline.cpp
// Author : A.G.Raja
// License : GPL
// Website : https://agraja.wordpress.com

#include <iostream>
#include “Getline.hh”

using namespace std;

int main() {
Getline g;
g.str(“Hi, my name is Raja\nI’m an Engineer”);
// Get the substring terminated by “y na”
cout<<g.getline(“y na”)<<endl;
// Result: “Hi, m”

// Get substring terminated by first of “sji”
cout<<g.getline(“sji”,0)<<endl;

// Get line terminated by ‘\n’
cout<<g.getline()<<endl;
// Result: “s Raja”

// Get single char at current position of pointer
cout<<g.get()<<endl;
// Result: “I”

// Get a char at current position of pointer
// if it is in the list “_$%’#”
cout<<g.get(“_$%’#”)<<endl;
// Result: “‘”

// Unget single char, unget 4 chars
g.unget(); g.unget(4);
}

Download here. getline

Perl script to display comments

Download here. c_help.pdf

 

#!/usr/bin/perl

# Filename: chelp.pl

# Author : A. G. Raja

# Website : agraja.wordpress.com

# License : GPL

# pass c file as argument to this script

# this script displays all the comments

use strict;

use warnings;

open(FILE,$ARGV[0]) or die “File not Found”;

my $line;

my $start=0;

while ( $line = <FILE> ) {

if($line =~ /\/\//)

{

$line=~ s/(.*)\/\/(.*)/$2/;

print $line;

}

if($line =~ /\/\*/)

{

$start=1;

$line=~ s/(.*)\/\*(.*)/$2/;

}

if($line =~ /\*\//)

{

$line=~ s/(.*)\*\//$1/;

print $line;

$start=0;

}

if($start) { print $line; }

}

close FILE;

 

Tips:

Use a shell script to redirect the output

of the above script to another program.

Example

#!/bin/bash

# Filename: help.sh

# Author : A.G.Raja

# Website : agraja.wordpress.com

# License : GPL

# rename chelp.pl to chelp

# Install chelp and add to path

chelp $1 | less

Demo:

 

Below is a C file

 

// Filename : demo.c

// Author : cfile.pl

// License : GPL

#include <stdio.h>

#define print(x) printf(“str=%s\n”,x);

int main(int argc, char **argv)

{

/* this is a multi-

line comment */

char *str=”File name:”;// this will print file name

print(argv[0])

return 0;

}

 

Type at the terminal:

[raja@agraja ]$ chelp demo.c

 

The following will be printed to stdout

 

Filename : demo.c

Author : cfile.pl

License : GPL

this is a multi-

line comment

this will print file name

Download here. c_help.pdf

C Find Replace Program

Download here. string_replace.pdf

// Filename : string_replace.c

// Author : A.G.Raja

// Website : agraja.wordpress.com

// License : GPL

#include <stdio.h>

 

 

char* string_replace(unsigned char *from, char *find, char *replace)

{

const char *p;

char *q, *to;

int i,d, match;

to=malloc(sizeof(char)*strlen(from)*strlen(replace)/strlen(find));

 

for(p = from, q = to; *p != ”; p++)

{

// find logic

for(d=0;d<strlen(find);d++)

{

if (*(p+d) == *(find+d)) match=1;

else match =0;

}

// replace logic

if (match)

{

for(i=0;i<strlen(replace);i++)

{

*(q+i)=*(replace+i);

}

q=q+i; p=p+d-1;

}

else // copy unchanged chars

{ *q=*p; q++; }

 

} *q = ”;

return to;

}

 

 

 

 

 

 

 

 

 

 

// Test code

int main()

{

unsigned char *str = “this is original text” ;

char f[]=”original”;

char r[]=”new”;

unsigned char *str2;

printf(“before:%s\n”,str);

str2=string_replace(str,f,r);

printf(“after:%s\n”,str2);

return 0;

}

 

Download here. string_replace.pdf

Tips:

See the following pages for char replace, trim spaces

char replace

trim spaces