Parse UDP primitives all the way to pform.
This commit is contained in:
parent
af8d6fbf01
commit
91aad30e1f
|
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef __PUdp_H
|
||||||
|
#define __PUdp_H
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Stephen Williams (steve@picturel.com)
|
||||||
|
*
|
||||||
|
* This source code is free software; you can redistribute it
|
||||||
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
#if !defined(WINNT)
|
||||||
|
#ident "$Id: PUdp.h,v 1.1 1998/11/25 02:35:53 steve Exp $"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include <vector>
|
||||||
|
# include "verinum.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class represents a parsed UDP. This is a much simpler object
|
||||||
|
* then a module or macromodule.
|
||||||
|
*
|
||||||
|
* - all ports are scaler,
|
||||||
|
* - pin 0 (the first port) is always output,
|
||||||
|
* and the remaining pins are input.
|
||||||
|
*
|
||||||
|
* Thus, the ports can be represented as an ordered list of pin names.
|
||||||
|
* If the output port is declared as a register in the Verilog source,
|
||||||
|
* then this is a sequential UDP and the sequential flag is set to true.
|
||||||
|
*
|
||||||
|
* STATE TABLE
|
||||||
|
* Each entry in the state table is given as a string with the same
|
||||||
|
* number of characters as inputs. If the UDP is sequential, a
|
||||||
|
* character is also included at the end of the string to represent
|
||||||
|
* the current output.
|
||||||
|
*
|
||||||
|
* If the UDP is sequential, the "initial" member is taken to be the
|
||||||
|
* intial value assigned in the source, or 'x' if none is given.
|
||||||
|
*/
|
||||||
|
class PUdp {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PUdp(const string&n, unsigned nports)
|
||||||
|
: ports(nports), sequential(false), initial(verinum::Vx), name_(n) { }
|
||||||
|
|
||||||
|
vector<string>ports;
|
||||||
|
bool sequential;
|
||||||
|
|
||||||
|
vector<string>tinput;
|
||||||
|
vector<char> tcurrent;
|
||||||
|
vector<char> toutput;
|
||||||
|
|
||||||
|
verinum::V initial;
|
||||||
|
|
||||||
|
void dump(ostream&out) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const string name_;
|
||||||
|
|
||||||
|
private: // Not implemented
|
||||||
|
PUdp(const PUdp&);
|
||||||
|
PUdp& operator= (const PUdp&);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Log: PUdp.h,v $
|
||||||
|
* Revision 1.1 1998/11/25 02:35:53 steve
|
||||||
|
* Parse UDP primitives all the way to pform.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
33
lexor.lex
33
lexor.lex
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: lexor.lex,v 1.4 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: lexor.lex,v 1.5 1998/11/25 02:35:53 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//# define YYSTYPE lexval
|
//# define YYSTYPE lexval
|
||||||
|
|
@ -55,7 +55,7 @@ static verinum*make_sized_hex(const char*txt);
|
||||||
[ \t\b\f\r] { ; }
|
[ \t\b\f\r] { ; }
|
||||||
\n { yylloc.first_line += 1; }
|
\n { yylloc.first_line += 1; }
|
||||||
|
|
||||||
"//".* { ; }
|
<*>"//".* { ; }
|
||||||
|
|
||||||
"/*" { BEGIN(CCOMMENT); }
|
"/*" { BEGIN(CCOMMENT); }
|
||||||
<CCOMMENT>. { yymore(); }
|
<CCOMMENT>. { yymore(); }
|
||||||
|
|
@ -82,7 +82,14 @@ static verinum*make_sized_hex(const char*txt);
|
||||||
return STRING; }
|
return STRING; }
|
||||||
<CSTRING>. { yymore(); }
|
<CSTRING>. { yymore(); }
|
||||||
|
|
||||||
<UDPTABLE>[xXbB01\?] { return yytext[0]; }
|
<UDPTABLE>\(\?\?\) { return '*'; }
|
||||||
|
<UDPTABLE>\(01\) { return 'r'; }
|
||||||
|
<UDPTABLE>\(10\) { return 'f'; }
|
||||||
|
<UDPTABLE>[bB] { return 'b'; }
|
||||||
|
<UDPTABLE>[fF] { return 'f'; }
|
||||||
|
<UDPTABLE>[rR] { return 'r'; }
|
||||||
|
<UDPTABLE>[xX] { return 'x'; }
|
||||||
|
<UDPTABLE>[pPnN01\?\*\-] { return yytext[0]; }
|
||||||
|
|
||||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||||
int rc = check_identifier(yytext);
|
int rc = check_identifier(yytext);
|
||||||
|
|
@ -103,13 +110,13 @@ static verinum*make_sized_hex(const char*txt);
|
||||||
yylval.text = new string(yytext);
|
yylval.text = new string(yytext);
|
||||||
return SYSTEM_IDENTIFIER; }
|
return SYSTEM_IDENTIFIER; }
|
||||||
|
|
||||||
([0-9][0-9_])?\'d[0-9][0-9_]* { yylval.number = 0;
|
[0-9][0-9_]*\'d[0-9][0-9_]* { yylval.number = 0;
|
||||||
return NUMBER; }
|
return NUMBER; }
|
||||||
([0-9][0-9_])?\'[bB][0-1xz_]+ { yylval.number = make_sized_binary(yytext);
|
[0-9][0-9_]*\'[bB][0-1xz_]+ { yylval.number = make_sized_binary(yytext);
|
||||||
return NUMBER; }
|
return NUMBER; }
|
||||||
([0-9][0-9_])?\'[oO][0-7xz_]+ { yylval.number = make_sized_octal(yytext);
|
[0-9][0-9_]*\'[oO][0-7xz_]+ { yylval.number = make_sized_octal(yytext);
|
||||||
return NUMBER; }
|
return NUMBER; }
|
||||||
([0-9][0-9_])?\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_sized_hex(yytext);
|
[0-9][0-9_]*\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_sized_hex(yytext);
|
||||||
return NUMBER; }
|
return NUMBER; }
|
||||||
|
|
||||||
[0-9][0-9_]* {
|
[0-9][0-9_]* {
|
||||||
|
|
@ -275,7 +282,7 @@ static verinum*make_sized_binary(const char*txt)
|
||||||
|
|
||||||
verinum::V*bits = new verinum::V[size];
|
verinum::V*bits = new verinum::V[size];
|
||||||
|
|
||||||
unsigned idx = size;
|
unsigned idx = 0;
|
||||||
char*eptr = ptr + strlen(ptr) - 1;
|
char*eptr = ptr + strlen(ptr) - 1;
|
||||||
while ((eptr > ptr) && (idx < size)) {
|
while ((eptr > ptr) && (idx < size)) {
|
||||||
|
|
||||||
|
|
@ -306,7 +313,7 @@ static verinum*make_sized_binary(const char*txt)
|
||||||
|
|
||||||
// Zero-extend binary number, except that z or x is extended
|
// Zero-extend binary number, except that z or x is extended
|
||||||
// if it is the highest supplied digit.
|
// if it is the highest supplied digit.
|
||||||
while (idx > 0) {
|
while (idx < size) {
|
||||||
switch (ptr[1]) {
|
switch (ptr[1]) {
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
case '1':
|
||||||
|
|
@ -336,7 +343,7 @@ static verinum*make_sized_octal(const char*txt)
|
||||||
|
|
||||||
verinum::V*bits = new verinum::V[size];
|
verinum::V*bits = new verinum::V[size];
|
||||||
|
|
||||||
unsigned idx = size;
|
unsigned idx = 0;
|
||||||
char*eptr = ptr + strlen(ptr);
|
char*eptr = ptr + strlen(ptr);
|
||||||
|
|
||||||
while ((eptr > ptr) && (idx < (size-3))) {
|
while ((eptr > ptr) && (idx < (size-3))) {
|
||||||
|
|
@ -363,7 +370,7 @@ static verinum*make_sized_octal(const char*txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero extend octal numbers
|
// zero extend octal numbers
|
||||||
while (idx > 0) switch (ptr[1]) {
|
while (idx < size) switch (ptr[1]) {
|
||||||
case 'x':
|
case 'x':
|
||||||
bits[idx++] = verinum::Vx;
|
bits[idx++] = verinum::Vx;
|
||||||
break;
|
break;
|
||||||
|
|
@ -387,7 +394,7 @@ static verinum*make_sized_hex(const char*txt)
|
||||||
|
|
||||||
verinum::V*bits = new verinum::V[size];
|
verinum::V*bits = new verinum::V[size];
|
||||||
|
|
||||||
unsigned idx = size;
|
unsigned idx = 0;
|
||||||
char*eptr = ptr + strlen(ptr);
|
char*eptr = ptr + strlen(ptr);
|
||||||
|
|
||||||
while ((eptr > ptr) && (idx < (size-4))) {
|
while ((eptr > ptr) && (idx < (size-4))) {
|
||||||
|
|
@ -428,7 +435,7 @@ static verinum*make_sized_hex(const char*txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero extend octal numbers
|
// zero extend octal numbers
|
||||||
while (idx > 0) switch (ptr[1]) {
|
while (idx < size) switch (ptr[1]) {
|
||||||
case 'x':
|
case 'x':
|
||||||
bits[idx++] = verinum::Vx;
|
bits[idx++] = verinum::Vx;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
16
main.cc
16
main.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: main.cc,v 1.5 1998/11/18 04:25:22 steve Exp $"
|
#ident "$Id: main.cc,v 1.6 1998/11/25 02:35:53 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
@ -155,7 +155,8 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
/* Parse the input. Make the pform. */
|
/* Parse the input. Make the pform. */
|
||||||
list<Module*>modules;
|
list<Module*>modules;
|
||||||
int rc = pform_parse(input, modules);
|
map<string,PUdp*>primitives;
|
||||||
|
int rc = pform_parse(input, modules, primitives);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
return rc;
|
return rc;
|
||||||
|
|
@ -163,12 +164,18 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
if (dump_flag) {
|
if (dump_flag) {
|
||||||
ofstream out ("a.pf");
|
ofstream out ("a.pf");
|
||||||
out << "PFORM DUMP:" << endl;
|
out << "PFORM DUMP MODULES:" << endl;
|
||||||
for (list<Module*>::iterator mod = modules.begin()
|
for (list<Module*>::iterator mod = modules.begin()
|
||||||
; mod != modules.end()
|
; mod != modules.end()
|
||||||
; mod ++ ) {
|
; mod ++ ) {
|
||||||
pform_dump(out, *mod);
|
pform_dump(out, *mod);
|
||||||
}
|
}
|
||||||
|
out << "PFORM DUMP PRIMITIVES:" << endl;
|
||||||
|
for (map<string,PUdp*>::iterator idx = primitives.begin()
|
||||||
|
; idx != primitives.end()
|
||||||
|
; idx ++ ) {
|
||||||
|
(*idx).second->dump(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -219,6 +226,9 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: main.cc,v $
|
* $Log: main.cc,v $
|
||||||
|
* Revision 1.6 1998/11/25 02:35:53 steve
|
||||||
|
* Parse UDP primitives all the way to pform.
|
||||||
|
*
|
||||||
* Revision 1.5 1998/11/18 04:25:22 steve
|
* Revision 1.5 1998/11/18 04:25:22 steve
|
||||||
* Add -f flags for generic flag key/values.
|
* Add -f flags for generic flag key/values.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
140
parse.y
140
parse.y
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: parse.y,v 1.6 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: parse.y,v 1.7 1998/11/25 02:35:53 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
|
|
@ -30,6 +30,7 @@ extern void lex_end_table();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
char letter;
|
||||||
string*text;
|
string*text;
|
||||||
list<string>*strings;
|
list<string>*strings;
|
||||||
|
|
||||||
|
|
@ -74,6 +75,13 @@ extern void lex_end_table();
|
||||||
|
|
||||||
%token KK_attribute
|
%token KK_attribute
|
||||||
|
|
||||||
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
|
||||||
|
%type <strings> udp_entry_list udp_comb_entry_list udp_sequ_entry_list
|
||||||
|
%type <strings> udp_body udp_port_list
|
||||||
|
%type <wires> udp_port_decl udp_port_decls
|
||||||
|
%type <statement> udp_initial udp_init_opt
|
||||||
|
|
||||||
%type <text> identifier lvalue register_variable
|
%type <text> identifier lvalue register_variable
|
||||||
%type <strings> list_of_register_variables
|
%type <strings> list_of_register_variables
|
||||||
%type <strings> list_of_variables
|
%type <strings> list_of_variables
|
||||||
|
|
@ -622,46 +630,162 @@ statement_opt
|
||||||
|
|
||||||
udp_body
|
udp_body
|
||||||
: K_table { lex_start_table(); }
|
: K_table { lex_start_table(); }
|
||||||
udp_comb_entry_list
|
udp_entry_list
|
||||||
K_endtable { lex_end_table(); }
|
K_endtable { lex_end_table(); $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_entry_list
|
||||||
|
: udp_comb_entry_list
|
||||||
|
| udp_sequ_entry_list
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_comb_entry
|
udp_comb_entry
|
||||||
: udp_input_list ':' udp_output_sym ';'
|
: udp_input_list ':' udp_output_sym ';'
|
||||||
|
{ string*tmp = $1;
|
||||||
|
*tmp += ':';
|
||||||
|
*tmp += $3;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_comb_entry_list
|
udp_comb_entry_list
|
||||||
: udp_comb_entry
|
: udp_comb_entry
|
||||||
|
{ list<string>*tmp = new list<string>;
|
||||||
|
tmp->push_back(*$1);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
| udp_comb_entry_list udp_comb_entry
|
| udp_comb_entry_list udp_comb_entry
|
||||||
|
{ list<string>*tmp = $1;
|
||||||
|
tmp->push_back(*$2);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_sequ_entry_list
|
||||||
|
: udp_sequ_entry
|
||||||
|
{ list<string>*tmp = new list<string>;
|
||||||
|
tmp->push_back(*$1);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| udp_sequ_entry_list udp_sequ_entry
|
||||||
|
{ list<string>*tmp = $1;
|
||||||
|
tmp->push_back(*$2);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_sequ_entry
|
||||||
|
: udp_input_list ':' udp_input_sym ':' udp_output_sym ';'
|
||||||
|
{ string*tmp = $1;
|
||||||
|
*tmp += ':';
|
||||||
|
*tmp += $3;
|
||||||
|
*tmp += ':';
|
||||||
|
*tmp += $5;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_initial
|
||||||
|
: K_initial IDENTIFIER '=' NUMBER ';'
|
||||||
|
{ PExpr*etmp = new PENumber($4);
|
||||||
|
PAssign*atmp = new PAssign(*$2, etmp);
|
||||||
|
delete $2;
|
||||||
|
$$ = atmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_init_opt
|
||||||
|
: udp_initial { $$ = $1; }
|
||||||
|
| { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_input_list
|
udp_input_list
|
||||||
: udp_input_sym
|
: udp_input_sym
|
||||||
|
{ string*tmp = new string;
|
||||||
|
*tmp += $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
| udp_input_list udp_input_sym
|
| udp_input_list udp_input_sym
|
||||||
|
{ string*tmp = $1;
|
||||||
|
*tmp += $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_input_sym : '0' | '1' | 'x' | 'X' | '?' | 'b' | 'B' ;
|
udp_input_sym
|
||||||
udp_output_sym : '0' | '1' | 'x' | 'X' ;
|
: '0' { $$ = '0'; }
|
||||||
|
| '1' { $$ = '1'; }
|
||||||
|
| 'x' { $$ = 'x'; }
|
||||||
|
| '?' { $$ = '?'; }
|
||||||
|
| 'b' { $$ = 'b'; }
|
||||||
|
| '*' { $$ = '*'; }
|
||||||
|
| 'f' { $$ = 'f'; }
|
||||||
|
| 'r' { $$ = 'f'; }
|
||||||
|
;
|
||||||
|
|
||||||
|
udp_output_sym
|
||||||
|
: '0' { $$ = '0'; }
|
||||||
|
| '1' { $$ = '1'; }
|
||||||
|
| 'x' { $$ = 'x'; }
|
||||||
|
| '-' { $$ = '-'; }
|
||||||
|
;
|
||||||
|
|
||||||
udp_port_decl
|
udp_port_decl
|
||||||
: K_input list_of_variables ';'
|
: K_input list_of_variables ';'
|
||||||
|
{ $$ = pform_make_udp_input_ports($2); }
|
||||||
| K_output IDENTIFIER ';'
|
| K_output IDENTIFIER ';'
|
||||||
|
{ PWire*pp = new PWire(*$2);
|
||||||
|
pp->port_type = NetNet::POUTPUT;
|
||||||
|
list<PWire*>*tmp = new list<PWire*>;
|
||||||
|
tmp->push_back(pp);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_reg IDENTIFIER ';'
|
||||||
|
{ PWire*pp = new PWire(*$2, NetNet::REG);
|
||||||
|
pp->port_type = NetNet::PIMPLICIT;
|
||||||
|
list<PWire*>*tmp = new list<PWire*>;
|
||||||
|
tmp->push_back(pp);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_port_decls
|
udp_port_decls
|
||||||
: udp_port_decl
|
: udp_port_decl
|
||||||
|
{ $$ = $1; }
|
||||||
| udp_port_decls udp_port_decl
|
| udp_port_decls udp_port_decl
|
||||||
|
{ list<PWire*>*tmp = $1;
|
||||||
|
tmp->merge(*$2);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_port_list
|
udp_port_list
|
||||||
: IDENTIFIER { ; }
|
: IDENTIFIER
|
||||||
| udp_port_list ',' IDENTIFIER { ; }
|
{ list<string>*tmp = new list<string>;
|
||||||
|
tmp->push_back(*$1);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| udp_port_list ',' IDENTIFIER
|
||||||
|
{ list<string>*tmp = $1;
|
||||||
|
tmp->push_back(*$3);
|
||||||
|
delete $3;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_primitive
|
udp_primitive
|
||||||
: K_primitive IDENTIFIER '(' udp_port_list ')' ';'
|
: K_primitive IDENTIFIER '(' udp_port_list ')' ';'
|
||||||
udp_port_decls
|
udp_port_decls
|
||||||
|
udp_init_opt
|
||||||
udp_body
|
udp_body
|
||||||
K_endprimitive
|
K_endprimitive
|
||||||
{ yyerror(@1, "Sorry, UDP primitives not supported."); }
|
{ pform_make_udp($2, $4, $7, $9, $8); }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
173
pform.cc
173
pform.cc
|
|
@ -17,12 +17,14 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: pform.cc,v 1.4 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: pform.cc,v 1.5 1998/11/25 02:35:53 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "pform.h"
|
# include "pform.h"
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
|
# include "PUdp.h"
|
||||||
# include <list>
|
# include <list>
|
||||||
|
# include <map>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
|
||||||
|
|
@ -31,6 +33,7 @@ extern int VLparse();
|
||||||
static Module*cur_module = 0;
|
static Module*cur_module = 0;
|
||||||
|
|
||||||
static list<Module*>*vl_modules = 0;
|
static list<Module*>*vl_modules = 0;
|
||||||
|
static map<string,PUdp*> vl_primitives;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function evaluates delay expressions. The result should be a
|
* This function evaluates delay expressions. The result should be a
|
||||||
|
|
@ -74,6 +77,151 @@ void pform_endmodule(const string&name)
|
||||||
cur_module = 0;
|
cur_module = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pform_make_udp(string*name, list<string>*parms,
|
||||||
|
list<PWire*>*decl, list<string>*table,
|
||||||
|
Statement*init_expr)
|
||||||
|
{
|
||||||
|
assert(parms->size() > 0);
|
||||||
|
|
||||||
|
/* Put the declarations into a map, so that I can check them
|
||||||
|
off with the parameters in the list. I will rebuild a list
|
||||||
|
of parameters for the PUdp object. */
|
||||||
|
map<string,PWire*> defs;
|
||||||
|
for (list<PWire*>::iterator cur = decl->begin()
|
||||||
|
; cur != decl->end()
|
||||||
|
; cur ++ )
|
||||||
|
|
||||||
|
if (defs[(*cur)->name] == 0) {
|
||||||
|
defs[(*cur)->name] = *cur;
|
||||||
|
|
||||||
|
} else switch ((*cur)->port_type) {
|
||||||
|
|
||||||
|
case NetNet::PIMPLICIT:
|
||||||
|
case NetNet::POUTPUT:
|
||||||
|
assert(defs[(*cur)->name]->port_type != NetNet::PINPUT);
|
||||||
|
// OK, merge the output definitions.
|
||||||
|
defs[(*cur)->name]->port_type = NetNet::POUTPUT;
|
||||||
|
if ((*cur)->type == NetNet::REG)
|
||||||
|
defs[(*cur)->name]->type = NetNet::REG;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetNet::PINPUT:
|
||||||
|
// Allow duplicate input declarations.
|
||||||
|
assert(defs[(*cur)->name]->port_type == NetNet::PINPUT);
|
||||||
|
delete *cur;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Put the parameters into a vector of wire descriptions. Look
|
||||||
|
in the map for the definitions of the name. */
|
||||||
|
vector<PWire*> pins (parms->size());
|
||||||
|
{ list<string>::iterator cur;
|
||||||
|
unsigned idx;
|
||||||
|
for (cur = parms->begin(), idx = 0
|
||||||
|
; cur != parms->end()
|
||||||
|
; idx++, cur++) {
|
||||||
|
pins[idx] = defs[*cur];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the output is an output and the inputs are
|
||||||
|
inputs. I can also make sure that only the single output is
|
||||||
|
declared a register, if anything. */
|
||||||
|
assert(pins.size() > 0);
|
||||||
|
assert(pins[0]);
|
||||||
|
assert(pins[0]->port_type == NetNet::POUTPUT);
|
||||||
|
for (unsigned idx = 1 ; idx < pins.size() ; idx += 1) {
|
||||||
|
assert(pins[idx]);
|
||||||
|
assert(pins[idx]->port_type == NetNet::PINPUT);
|
||||||
|
assert(pins[idx]->type != NetNet::REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interpret and check the table entry strings, to make sure
|
||||||
|
they correspond to the inputs, output and output type. Make
|
||||||
|
up vectors for the fully interpreted result that can be
|
||||||
|
placed in the PUdp object. */
|
||||||
|
vector<string> input (table->size());
|
||||||
|
vector<char> current (table->size());
|
||||||
|
vector<char> output (table->size());
|
||||||
|
{ unsigned idx = 0;
|
||||||
|
for (list<string>::iterator cur = table->begin()
|
||||||
|
; cur != table->end()
|
||||||
|
; cur ++, idx += 1) {
|
||||||
|
string tmp = *cur;
|
||||||
|
assert(tmp.find(':') == (pins.size() - 1));
|
||||||
|
|
||||||
|
input[idx] = tmp.substr(0, pins.size()-1);
|
||||||
|
tmp = tmp.substr(pins.size()-1);
|
||||||
|
|
||||||
|
if (pins[0]->type == NetNet::REG) {
|
||||||
|
assert(tmp[0] == ':');
|
||||||
|
assert(tmp.size() == 4);
|
||||||
|
current[idx] = tmp[1];
|
||||||
|
tmp = tmp.substr(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tmp[0] == ':');
|
||||||
|
assert(tmp.size() == 2);
|
||||||
|
output[idx] = tmp[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the "initial" statement, if present, to be sure that
|
||||||
|
it only assignes to the output and the output is
|
||||||
|
registered. Then save the initial value that I get. */
|
||||||
|
verinum::V init = verinum::Vx;
|
||||||
|
if (init_expr) {
|
||||||
|
// XXXX
|
||||||
|
assert(pins[0]->type == NetNet::REG);
|
||||||
|
|
||||||
|
PAssign*pa = dynamic_cast<PAssign*>(init_expr);
|
||||||
|
assert(pa);
|
||||||
|
|
||||||
|
// XXXX
|
||||||
|
assert(pa->lval() == pins[0]->name);
|
||||||
|
|
||||||
|
const PENumber*np = dynamic_cast<const PENumber*>(pa->get_expr());
|
||||||
|
assert(np);
|
||||||
|
|
||||||
|
init = np->value()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the primitive into the primitives table
|
||||||
|
if (vl_primitives[*name]) {
|
||||||
|
VLerror("UDP primitive already exists.");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PUdp*udp = new PUdp(*name, parms->size());
|
||||||
|
|
||||||
|
// Detect sequential udp.
|
||||||
|
if (pins[0]->type == NetNet::REG)
|
||||||
|
udp->sequential = true;
|
||||||
|
|
||||||
|
// Make the port list for the UDP
|
||||||
|
for (unsigned idx = 0 ; idx < pins.size() ; idx += 1)
|
||||||
|
udp->ports[idx] = pins[idx]->name;
|
||||||
|
|
||||||
|
udp->tinput = input;
|
||||||
|
udp->tcurrent = current;
|
||||||
|
udp->toutput = output;
|
||||||
|
udp->initial = init;
|
||||||
|
|
||||||
|
vl_primitives[*name] = udp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the excess tables and lists from the parser. */
|
||||||
|
delete name;
|
||||||
|
delete parms;
|
||||||
|
delete decl;
|
||||||
|
delete table;
|
||||||
|
delete init_expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void pform_makegate(PGBuiltin::Type type,
|
void pform_makegate(PGBuiltin::Type type,
|
||||||
const string&name,
|
const string&name,
|
||||||
const vector<PExpr*>&wires,
|
const vector<PExpr*>&wires,
|
||||||
|
|
@ -249,6 +397,22 @@ void pform_set_net_range(list<string>*names, list<PExpr*>*range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list<PWire*>* pform_make_udp_input_ports(list<string>*names)
|
||||||
|
{
|
||||||
|
list<PWire*>*out = new list<PWire*>;
|
||||||
|
|
||||||
|
for (list<string>::const_iterator cur = names->begin()
|
||||||
|
; cur != names->end()
|
||||||
|
; cur ++ ) {
|
||||||
|
PWire*pp = new PWire(*cur);
|
||||||
|
pp->port_type = NetNet::PINPUT;
|
||||||
|
out->push_back(pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete names;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void pform_make_behavior(PProcess::Type type, Statement*st)
|
void pform_make_behavior(PProcess::Type type, Statement*st)
|
||||||
{
|
{
|
||||||
PProcess*pp = new PProcess(type, st);
|
PProcess*pp = new PProcess(type, st);
|
||||||
|
|
@ -284,7 +448,7 @@ Statement* pform_make_calltask(string*name, list<PExpr*>*parms)
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE*vl_input = 0;
|
FILE*vl_input = 0;
|
||||||
int pform_parse(FILE*input, list<Module*>&modules)
|
int pform_parse(FILE*input, list<Module*>&modules, map<string,PUdp*>&prim)
|
||||||
{
|
{
|
||||||
vl_input = input;
|
vl_input = input;
|
||||||
vl_modules = &modules;
|
vl_modules = &modules;
|
||||||
|
|
@ -294,12 +458,17 @@ int pform_parse(FILE*input, list<Module*>&modules)
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cerr << "I give up." << endl;
|
cerr << "I give up." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prim = vl_primitives;
|
||||||
return error_count;
|
return error_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: pform.cc,v $
|
* $Log: pform.cc,v $
|
||||||
|
* Revision 1.5 1998/11/25 02:35:53 steve
|
||||||
|
* Parse UDP primitives all the way to pform.
|
||||||
|
*
|
||||||
* Revision 1.4 1998/11/23 00:20:23 steve
|
* Revision 1.4 1998/11/23 00:20:23 steve
|
||||||
* NetAssign handles lvalues as pin links
|
* NetAssign handles lvalues as pin links
|
||||||
* instead of a signal pointer,
|
* instead of a signal pointer,
|
||||||
|
|
|
||||||
14
pform.h
14
pform.h
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: pform.h,v 1.2 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: pform.h,v 1.3 1998/11/25 02:35:53 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
# include "Statement.h"
|
# include "Statement.h"
|
||||||
# include "PGate.h"
|
# include "PGate.h"
|
||||||
# include "PExpr.h"
|
# include "PExpr.h"
|
||||||
|
# include "PUdp.h"
|
||||||
# include "PWire.h"
|
# include "PWire.h"
|
||||||
# include "verinum.h"
|
# include "verinum.h"
|
||||||
# include <iostream.h>
|
# include <iostream.h>
|
||||||
|
|
@ -77,6 +78,10 @@ struct lgate {
|
||||||
extern void pform_startmodule(const string&, list<PWire*>*ports);
|
extern void pform_startmodule(const string&, list<PWire*>*ports);
|
||||||
extern void pform_endmodule(const string&);
|
extern void pform_endmodule(const string&);
|
||||||
|
|
||||||
|
extern void pform_make_udp(string*name, list<string>*parms,
|
||||||
|
list<PWire*>*decl, list<string>*table,
|
||||||
|
Statement*init);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The makewire functions announce to the pform code new wires. These
|
* The makewire functions announce to the pform code new wires. These
|
||||||
* go into a module that is currently opened.
|
* go into a module that is currently opened.
|
||||||
|
|
@ -92,6 +97,8 @@ extern Statement* pform_make_block(PBlock::BL_TYPE, list<Statement*>*);
|
||||||
extern Statement* pform_make_assignment(string*t, PExpr*e);
|
extern Statement* pform_make_assignment(string*t, PExpr*e);
|
||||||
extern Statement* pform_make_calltask(string*t, list<PExpr*>* =0);
|
extern Statement* pform_make_calltask(string*t, list<PExpr*>* =0);
|
||||||
|
|
||||||
|
extern list<PWire*>* pform_make_udp_input_ports(list<string>*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The makegate function creates a new gate (which need not have a
|
* The makegate function creates a new gate (which need not have a
|
||||||
* name) and connects it to the specified wires.
|
* name) and connects it to the specified wires.
|
||||||
|
|
@ -117,11 +124,14 @@ extern void pform_make_pgassign(const string&lval, PExpr*sel, PExpr*rval);
|
||||||
* parses the source file and places all the modules it finds into the
|
* parses the source file and places all the modules it finds into the
|
||||||
* mod list. The dump function dumps a module to the output stream.
|
* mod list. The dump function dumps a module to the output stream.
|
||||||
*/
|
*/
|
||||||
extern int pform_parse(FILE*, list<Module*>&mod);
|
extern int pform_parse(FILE*, list<Module*>&mod, map<string,PUdp*>&prim);
|
||||||
extern void pform_dump(ostream&out, Module*mod);
|
extern void pform_dump(ostream&out, Module*mod);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: pform.h,v $
|
* $Log: pform.h,v $
|
||||||
|
* Revision 1.3 1998/11/25 02:35:53 steve
|
||||||
|
* Parse UDP primitives all the way to pform.
|
||||||
|
*
|
||||||
* Revision 1.2 1998/11/23 00:20:23 steve
|
* Revision 1.2 1998/11/23 00:20:23 steve
|
||||||
* NetAssign handles lvalues as pin links
|
* NetAssign handles lvalues as pin links
|
||||||
* instead of a signal pointer,
|
* instead of a signal pointer,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: pform_dump.cc,v 1.5 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: pform_dump.cc,v 1.6 1998/11/25 02:35:54 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -332,9 +332,42 @@ void pform_dump(ostream&out, Module*mod)
|
||||||
out << "endmodule" << endl;
|
out << "endmodule" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PUdp::dump(ostream&out) const
|
||||||
|
{
|
||||||
|
out << "primitive " << name_ << "(" << ports[0];
|
||||||
|
for (unsigned idx = 1 ; idx < ports.size() ; idx += 1)
|
||||||
|
out << ", " << ports[idx];
|
||||||
|
out << ");" << endl;
|
||||||
|
|
||||||
|
if (sequential)
|
||||||
|
out << " reg " << ports[0] << ";" << endl;
|
||||||
|
|
||||||
|
out << " table" << endl;
|
||||||
|
for (unsigned idx = 0 ; idx < tinput.size() ; idx += 1) {
|
||||||
|
out << " ";
|
||||||
|
for (unsigned chr = 0 ; chr < tinput[idx].length() ; chr += 1)
|
||||||
|
out << " " << tinput[idx][chr];
|
||||||
|
|
||||||
|
if (sequential)
|
||||||
|
out << " : " << tcurrent[idx];
|
||||||
|
|
||||||
|
out << " : " << toutput[idx] << " ;" << endl;
|
||||||
|
}
|
||||||
|
out << " endtable" << endl;
|
||||||
|
|
||||||
|
if (sequential)
|
||||||
|
out << " initial " << ports[0] << " = 1'b" << initial
|
||||||
|
<< ";" << endl;
|
||||||
|
|
||||||
|
out << "endprimitive" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: pform_dump.cc,v $
|
* $Log: pform_dump.cc,v $
|
||||||
|
* Revision 1.6 1998/11/25 02:35:54 steve
|
||||||
|
* Parse UDP primitives all the way to pform.
|
||||||
|
*
|
||||||
* Revision 1.5 1998/11/23 00:20:23 steve
|
* Revision 1.5 1998/11/23 00:20:23 steve
|
||||||
* NetAssign handles lvalues as pin links
|
* NetAssign handles lvalues as pin links
|
||||||
* instead of a signal pointer,
|
* instead of a signal pointer,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue