Match parsed IOPATH to cell and modpath to be annotated.
This commit is contained in:
parent
c5950e3aa6
commit
73e60f4b81
|
|
@ -26,6 +26,7 @@
|
||||||
# include "sdf_parse.h"
|
# include "sdf_parse.h"
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
|
# include <assert.h>
|
||||||
|
|
||||||
static void process_quoted_string(void);
|
static void process_quoted_string(void);
|
||||||
static int lookup_keyword(const char*text);
|
static int lookup_keyword(const char*text);
|
||||||
|
|
@ -104,9 +105,15 @@ static int lookup_keyword(const char*text)
|
||||||
return IDENTIFIER;
|
return IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a string witout the leading and trailing quotes.
|
||||||
|
*/
|
||||||
static void process_quoted_string(void)
|
static void process_quoted_string(void)
|
||||||
{
|
{
|
||||||
yylval.string_val = strdup(yytext);
|
yylval.string_val = strdup(yytext+1);
|
||||||
|
char*endp = yylval.string_val+strlen(yylval.string_val);
|
||||||
|
assert(endp[-1] == '"');
|
||||||
|
endp[-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int sdfparse(void);
|
extern int sdfparse(void);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,12 @@ extern int sdflex(void);
|
||||||
static void yyerror(const char*msg);
|
static void yyerror(const char*msg);
|
||||||
# include "vpi_user.h"
|
# include "vpi_user.h"
|
||||||
# include "sdf_parse_priv.h"
|
# include "sdf_parse_priv.h"
|
||||||
|
# include "sdf_priv.h"
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
||||||
|
/* This is the hierarchy separator to use. */
|
||||||
|
static char use_hchar = '.';
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
|
@ -41,6 +46,11 @@ static void yyerror(const char*msg);
|
||||||
%token <real_val> REAL_NUMBER
|
%token <real_val> REAL_NUMBER
|
||||||
%token <int_val> INTEGER
|
%token <int_val> INTEGER
|
||||||
|
|
||||||
|
%type <string_val> celltype
|
||||||
|
%type <string_val> cell_instance
|
||||||
|
%type <string_val> hierarchical_identifier
|
||||||
|
%type <string_val> port port_instance port_spec
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
source_file
|
source_file
|
||||||
|
|
@ -68,8 +78,7 @@ sdf_header_item
|
||||||
|
|
||||||
sdfversion
|
sdfversion
|
||||||
: '(' K_SDFVERSION QSTRING ')'
|
: '(' K_SDFVERSION QSTRING ')'
|
||||||
{ vpi_printf("SDFVERSION: %s\n", $3);
|
{ free($3);
|
||||||
free($3);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -106,8 +115,8 @@ program_version : '(' K_VERSION QSTRING ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
hierarchy_divider
|
hierarchy_divider
|
||||||
: '(' K_DIVIDER '.' ')' { vpi_printf("SDF Use . for hierarchy\n"); }
|
: '(' K_DIVIDER '.' ')' { use_hchar = '.'; }
|
||||||
| '(' K_DIVIDER '/' ')' { vpi_printf("SDF Use / for hierarchy\n"); }
|
| '(' K_DIVIDER '/' ')' { use_hchar = '/'; }
|
||||||
;
|
;
|
||||||
|
|
||||||
voltage
|
voltage
|
||||||
|
|
@ -139,22 +148,27 @@ cell_list
|
||||||
;
|
;
|
||||||
|
|
||||||
cell
|
cell
|
||||||
: '(' K_CELL celltype cell_instance timing_spec_list ')'
|
: '(' K_CELL celltype cell_instance
|
||||||
|
{ sdf_select_instance($3, $4); /* find the instance in the design */}
|
||||||
|
timing_spec_list
|
||||||
|
')'
|
||||||
|
{ free($3);
|
||||||
|
free($4); }
|
||||||
| '(' K_CELL error ')'
|
| '(' K_CELL error ')'
|
||||||
{ vpi_printf("%s:%d: Syntax error in CELL\n",
|
{ vpi_printf("%s:%d: Syntax error in CELL\n",
|
||||||
sdf_parse_path, @2.first_line); }
|
sdf_parse_path, @2.first_line); }
|
||||||
;
|
;
|
||||||
|
|
||||||
celltype
|
celltype
|
||||||
: '(' K_CELLTYPE QSTRING ')'
|
: '(' K_CELLTYPE QSTRING ')'
|
||||||
{ vpi_printf("%s:%d: SDF CELL TYPE: %s\n", sdf_parse_path, @1.first_line, $3);
|
{ $$ = $3; }
|
||||||
free($3);
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
cell_instance
|
cell_instance
|
||||||
: '(' K_INSTANCE hierarchical_identifier ')'
|
: '(' K_INSTANCE hierarchical_identifier ')'
|
||||||
|
{ $$ = $3; }
|
||||||
| '(' K_INSTANCE '*' ')'
|
| '(' K_INSTANCE '*' ')'
|
||||||
|
{ $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
timing_spec_list
|
timing_spec_list
|
||||||
|
|
@ -189,9 +203,13 @@ del_def_list
|
||||||
|
|
||||||
del_def
|
del_def
|
||||||
: '(' K_IOPATH port_spec port_instance delval_list ')'
|
: '(' K_IOPATH port_spec port_instance delval_list ')'
|
||||||
|
{ sdf_iopath_delays($3, $4);
|
||||||
|
free($3);
|
||||||
|
free($4);
|
||||||
|
}
|
||||||
| '(' K_IOPATH error ')'
|
| '(' K_IOPATH error ')'
|
||||||
{ vpi_printf("%s:%d: Invalid/malformed IOPATH\n",
|
{ vpi_printf("%s:%d: Invalid/malformed IOPATH\n",
|
||||||
sdf_parse_path, @2.first_line); }
|
sdf_parse_path, @2.first_line); }
|
||||||
;
|
;
|
||||||
|
|
||||||
port_spec
|
port_spec
|
||||||
|
|
@ -200,12 +218,13 @@ port_spec
|
||||||
;
|
;
|
||||||
|
|
||||||
port_instance
|
port_instance
|
||||||
: port
|
: port { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
port
|
port
|
||||||
: hierarchical_identifier
|
: hierarchical_identifier
|
||||||
| hierarchical_identifier '[' INTEGER ']'
|
{ $$ = $1; }
|
||||||
|
/* | hierarchical_identifier '[' INTEGER ']' */
|
||||||
;
|
;
|
||||||
|
|
||||||
delval_list
|
delval_list
|
||||||
|
|
@ -226,7 +245,7 @@ rvalue
|
||||||
|
|
||||||
hierarchical_identifier
|
hierarchical_identifier
|
||||||
: IDENTIFIER
|
: IDENTIFIER
|
||||||
{ free($1); }
|
{ $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
rtriple
|
rtriple
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,12 @@
|
||||||
*/
|
*/
|
||||||
extern void sdf_process_file(FILE*fd, const char*path);
|
extern void sdf_process_file(FILE*fd, const char*path);
|
||||||
|
|
||||||
|
|
||||||
|
/* ****
|
||||||
|
* These functions are called by the parser to process the SDF file as
|
||||||
|
* it is parsed.
|
||||||
|
*/
|
||||||
|
extern void sdf_select_instance(const char*celltype, const char*inst);
|
||||||
|
extern void sdf_iopath_delays(const char*src, const char*dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,99 @@
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are static context
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scope of the $sdf_annotate call. Annotation starts here. */
|
||||||
|
static vpiHandle sdf_scope;
|
||||||
|
/* The cell in process. */
|
||||||
|
static vpiHandle sdf_cur_cell;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions are called by the SDF parser during parsing to
|
||||||
|
* handling items discovered in the parse.
|
||||||
|
*/
|
||||||
|
void sdf_select_instance(const char*celltype, const char*cellinst)
|
||||||
|
{
|
||||||
|
vpiHandle idx = vpi_iterate(vpiModule, sdf_scope);
|
||||||
|
assert(idx);
|
||||||
|
|
||||||
|
vpiHandle cur;
|
||||||
|
while ( (cur = vpi_scan(idx)) ) {
|
||||||
|
|
||||||
|
/* If we find the cell in this scope, then save it for
|
||||||
|
future processing. */
|
||||||
|
if ( strcmp(cellinst, vpi_get_str(vpiName,cur)) == 0) {
|
||||||
|
sdf_cur_cell = cur;
|
||||||
|
vpi_free_object(idx);
|
||||||
|
|
||||||
|
/* The scope that matches should be a module. */
|
||||||
|
if (vpi_get(vpiType,sdf_cur_cell) != vpiModule) {
|
||||||
|
vpi_printf("SDF ERROR: Scope %s in %s is not a module.\n",
|
||||||
|
cellinst, vpi_get_str(vpiName,sdf_scope));
|
||||||
|
}
|
||||||
|
/* The matching scope (a module) should have the
|
||||||
|
expected type. */
|
||||||
|
if (strcmp(celltype,vpi_get_str(vpiDefName,sdf_cur_cell)) != 0) {
|
||||||
|
vpi_printf("SDF ERROR: Module %s in %s is not a %s; "
|
||||||
|
"it is an %s\n", cellinst,
|
||||||
|
vpi_get_str(vpiName,sdf_scope), celltype,
|
||||||
|
vpi_get_str(vpiDefName,sdf_cur_cell));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdf_cur_cell = 0;
|
||||||
|
vpi_printf("SDF WARNING: Unable to find %s in current scope\n", cellinst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdf_iopath_delays(const char*src, const char*dst)
|
||||||
|
{
|
||||||
|
assert(sdf_cur_cell);
|
||||||
|
|
||||||
|
vpiHandle idx = vpi_iterate(vpiModPath, sdf_cur_cell);
|
||||||
|
assert(idx);
|
||||||
|
|
||||||
|
/* Search for the modpath that matches the IOPATH by looking
|
||||||
|
for the modpath that uses the same ports as the ports that
|
||||||
|
the parser has found. */
|
||||||
|
vpiHandle path;
|
||||||
|
while ( (path = vpi_scan(idx)) ) {
|
||||||
|
vpiHandle path_in = vpi_handle(vpiModPathIn,path);
|
||||||
|
vpiHandle path_out = vpi_handle(vpiModPathOut,path);
|
||||||
|
|
||||||
|
path_in = vpi_handle(vpiExpr,path_in);
|
||||||
|
path_out = vpi_handle(vpiExpr,path_out);
|
||||||
|
assert(vpi_get(vpiType,path_in) == vpiNet);
|
||||||
|
assert(vpi_get(vpiType,path_out) == vpiNet);
|
||||||
|
|
||||||
|
/* If the src name doesn't match, go on. */
|
||||||
|
if (strcmp(src,vpi_get_str(vpiName,path_in)) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the dst name doesn't match, go on. */
|
||||||
|
if (strcmp(dst,vpi_get_str(vpiName,path_out)) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Ah, this must be a match! */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == 0) {
|
||||||
|
vpi_printf("SDF ERROR: Unable to find ModPath %s -> %s in %s\n",
|
||||||
|
src, dst, vpi_get_str(vpiName,sdf_cur_cell));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No longer need the iterator. */
|
||||||
|
vpi_free_object(idx);
|
||||||
|
|
||||||
|
vpi_printf("XXXX Found the modpath object.\n");
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name)
|
static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -55,6 +148,9 @@ static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name)
|
||||||
FILE*sdf_fd = fopen(path_str, "r");
|
FILE*sdf_fd = fopen(path_str, "r");
|
||||||
assert(sdf_fd);
|
assert(sdf_fd);
|
||||||
|
|
||||||
|
sdf_scope = vpi_handle(vpiScope,sys);
|
||||||
|
sdf_cur_cell = 0;
|
||||||
|
|
||||||
sdf_process_file(sdf_fd, path_str);
|
sdf_process_file(sdf_fd, path_str);
|
||||||
|
|
||||||
fclose(sdf_fd);
|
fclose(sdf_fd);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue