Get the structure for ivl_statement_t worked out.

This commit is contained in:
steve 2000-09-18 01:24:32 +00:00
parent 89d7176734
commit effc84c46d
7 changed files with 533 additions and 136 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.66 2000/09/17 21:26:15 steve Exp $"
#ident "$Id: Makefile.in,v 1.67 2000/09/18 01:24:32 steve Exp $"
#
#
SHELL = /bin/sh
@ -69,7 +69,7 @@ distclean: clean
rm -f config.status config.cache config.log
rm -f Makefile
TT = t-dll.o t-null.o t-verilog.o t-vvm.o t-xnf.o
TT = t-dll.o t-dll-api.o t-dll-proc.o t-null.o t-verilog.o t-vvm.o t-xnf.o
FF = nodangle.o synth.o syn-rules.o xnfio.o
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: ivl_target.h,v 1.6 2000/08/27 15:51:50 steve Exp $"
#ident "$Id: ivl_target.h,v 1.7 2000/09/18 01:24:32 steve Exp $"
#endif
#ifdef __cplusplus
@ -68,6 +68,7 @@ typedef struct ivl_net_signal_s*ivl_net_signal_t;
typedef struct ivl_nexus_s *ivl_nexus_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_statement_s*ivl_statement_t;
/* This function returns the string value of the named flag. The key
@ -112,6 +113,29 @@ extern const char* ivl_get_nexus_name(ivl_nexus_t net);
extern unsigned ivl_get_signal_pins(ivl_net_signal_t net);
/*
* These functions get information about a process. A process is
* an initial or always block within the original Verilog source, that
* is translated into a type and a single statement. (The statement
* may be a compound statement.)
*
* The ivl_get_process_type function gets the type of the process,
* an "inital" or "always" statement.
*
* The ivl_get_process_stmt functin gets the statement that forms the
* process. See the statement related functions for how to manipulate
* statements.
*/
typedef enum ivl_process_type {
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1
} ivl_process_type_t;
extern ivl_process_type_t ivl_get_process_type(ivl_process_t net);
extern ivl_statement_t ivl_get_process_stmt(ivl_process_t net);
/* TARGET MODULE ENTRY POINTS
*
* The module entry points generally take a cookie and possibly a name
@ -191,8 +215,10 @@ typedef int (*net_signal_f)(const char*name, ivl_net_signal_t net);
block in the design. In principle, the target creates a thread for
each process in the Verilog original.
XXXX I have not yet decided if it it up to the target to scan the
process statements, or if I will do that myself. Hmm... */
This function is called with the entire thread generated. The
process and statement access methods can be used to randomly
(read-only) access all the code of the thread. Also, the module may
hold on to the process, the core will not delete it. */
typedef int (*process_f)(ivl_process_t net);
@ -210,6 +236,9 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.7 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
* Revision 1.6 2000/08/27 15:51:50 steve
* t-dll iterates signals, and passes them to the
* target module.

87
t-dll-api.cc Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.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) && !defined(macintosh)
#ident "$Id: t-dll-api.cc,v 1.1 2000/09/18 01:24:32 steve Exp $"
#endif
# include "t-dll.h"
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_get_flag(ivl_design_t des, const char*key)
{
return ((const Design*)des)->get_flag(key).c_str();
}
extern "C" const char*ivl_get_root_name(ivl_design_t des)
{
return ((const Design*)des)->find_root_scope()->name().c_str();
}
extern "C" ivl_logic_t ivl_get_logic_type(ivl_net_logic_t net)
{
switch (net->dev_->type()) {
case NetLogic::AND:
return IVL_AND;
case NetLogic::OR:
return IVL_OR;
}
assert(0);
return IVL_AND;
}
extern "C" unsigned ivl_get_logic_pins(ivl_net_logic_t net)
{
return net->dev_->pin_count();
}
extern "C" ivl_nexus_t ivl_get_logic_pin(ivl_net_logic_t net, unsigned pin)
{
return (ivl_nexus_t) (net->dev_->pin(pin).nexus());
}
extern "C" const char* ivl_get_nexus_name(ivl_nexus_t net)
{
const Nexus*nex = (const Nexus*)net;
return nex->name();
}
extern "C" ivl_process_type_t ivl_get_process_type(ivl_process_t net)
{
return net->type_;
}
extern "C" ivl_statement_t ivl_get_process_stmt(ivl_process_t net)
{
return net->stmt_;
}
extern "C" unsigned ivl_get_signal_pins(ivl_net_signal_t net)
{
const NetNet*sig = (const NetNet*)net;
return sig->pin_count();
}
/*
* $Log: t-dll-api.cc,v $
* Revision 1.1 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
*/

232
t-dll-proc.cc Normal file
View File

@ -0,0 +1,232 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.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.will need a Picture Elements Binary Software
* License.
*
* 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) && !defined(macintosh)
#ident "$Id: t-dll-proc.cc,v 1.1 2000/09/18 01:24:32 steve Exp $"
#endif
# include "target.h"
# include "ivl_target.h"
# include "compiler.h"
# include "t-dll.h"
# include <malloc.h>
bool dll_target::process(const NetProcTop*net)
{
ivl_process_t obj = (struct ivl_process_s*)
calloc(1, sizeof(struct ivl_process_s));
switch (net->type()) {
case NetProcTop::KINITIAL:
obj->type_ = IVL_PR_INITIAL;
break;
case NetProcTop::KALWAYS:
obj->type_ = IVL_PR_ALWAYS;
break;
default:
assert(0);
}
/* This little bit causes the process to be completely
generated so that it can be passed to the DLL. The
stmt_cur_ member us used to hold a pointer to the current
statement in progress, and the emit_proc() method fills in
that object.
We know a few things about the current statement: we are
not in the middle of one, and when we are done, we have our
statement back. The asserts check these conditions. */
assert(stmt_cur_ == 0);
stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
assert(stmt_cur_);
net->statement()->emit_proc(this);
assert(stmt_cur_);
obj->stmt_ = stmt_cur_;
stmt_cur_ = 0;
if (process_) {
int rc = (process_)(obj);
return rc == 0;
} else {
cerr << dll_path_ << ": internal error: target DLL lacks "
<< "target_process function." << endl;
return false;
}
return false;
}
/*XXXX
* Currently, this doesn't do anything really, so stub it out.
*/
void dll_target::proc_assign(const NetAssign*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN;
}
bool dll_target::proc_block(const NetBlock*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
/* First, count the statements in the block. */
unsigned count = 0;
for (const NetProc*cur = net->proc_first()
; cur ; cur = net->proc_next(cur))
count += 1;
/* If the block has no statements, then turn it into a no-op */
if (count == 0) {
stmt_cur_->type_ = IVL_ST_NOOP;
return true;
}
/* If there is exactly one statement, there is no need for the
block wrapper, generate the contained statement instead. */
if (count == 1) {
return net->proc_first()->emit_proc(this);
}
/* Handle the general case. The block has some statements in
it, so fill in the block fields of the existing statement,
and generate the contents for the statement array. */
stmt_cur_->type_ = IVL_ST_BLOCK;
stmt_cur_->u_.block_.nstmt_ = count;
stmt_cur_->u_.block_.stmt_ = (struct ivl_statement_s*)
calloc(count, sizeof(struct ivl_statement_s));
struct ivl_statement_s*save_cur_ = stmt_cur_;
unsigned idx = 0;
bool flag = true;
for (const NetProc*cur = net->proc_first()
; cur ; cur = net->proc_next(cur), idx += 1) {
assert(idx < count);
stmt_cur_ = save_cur_->u_.block_.stmt_ + idx;
bool rc = cur->emit_proc(this);
flag = flag && rc;
}
assert(idx == count);
stmt_cur_ = save_cur_;
return flag;
}
void dll_target::proc_condit(const NetCondit*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_CONDIT;
stmt_cur_->u_.condit_.stmt_ = (struct ivl_statement_s*)
calloc(2, sizeof(struct ivl_statement_s));
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = save_cur_->u_.condit_.stmt_+0;
net->emit_recurse_if(this);
stmt_cur_ = save_cur_->u_.condit_.stmt_+1;
net->emit_recurse_else(this);
stmt_cur_ = save_cur_;
}
bool dll_target::proc_delay(const NetPDelay*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
ivl_statement_t tmp = (struct ivl_statement_s*)
calloc(1, sizeof(struct ivl_statement_s));
if (const NetExpr*expr = net->expr()) {
stmt_cur_->type_ = IVL_ST_DELAYX;
stmt_cur_->u_.delayx_.stmt_ = tmp;
} else {
stmt_cur_->type_ = IVL_ST_DELAY;
stmt_cur_->u_.delay_.stmt_ = tmp;
stmt_cur_->u_.delay_.delay_ = net->delay();
}
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = tmp;
bool flag = net->emit_proc_recurse(this);
stmt_cur_ = save_cur_;
return flag;
}
bool dll_target::proc_wait(const NetEvWait*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_WAIT;
stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*)
calloc(1, sizeof(struct ivl_statement_s));
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = stmt_cur_->u_.wait_.stmt_;
bool flag = net->emit_recurse(this);
return flag;
}
void dll_target::proc_while(const NetWhile*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_WHILE;
stmt_cur_->u_.while_.stmt_ = (struct ivl_statement_s*)
calloc(1, sizeof(struct ivl_statement_s));
/* XXXX Nothing about the expression? */
/* Now generate the statement of the while loop. We know it is
a single statement, and we know that the
emit_proc_recurse() will call emit_proc() for it. */
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = save_cur_->u_.while_.stmt_;
net->emit_proc_recurse(this);
stmt_cur_ = save_cur_;
}
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.1 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
*/

140
t-dll.cc
View File

@ -17,72 +17,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.cc,v 1.6 2000/08/27 15:51:51 steve Exp $"
#ident "$Id: t-dll.cc,v 1.7 2000/09/18 01:24:32 steve Exp $"
#endif
# include "target.h"
# include "ivl_target.h"
# include "compiler.h"
# include "t-dll.h"
# include <dlfcn.h>
struct ivl_design_s {
const Design*des_;
};
struct ivl_net_const_s {
const NetConst*con_;
};
struct ivl_net_logic_s {
const NetLogic*dev_;
};
struct ivl_process_s {
const NetProcTop*top_;
};
/*
* The DLL target type loads a named object file to handle the process
* of scanning the netlist. When it is time to start the design, I
* locate and link in the desired DLL, then start calling methods. The
* DLL will call me back to get information out of the netlist in
* particular.
*/
struct dll_target : public target_t {
bool start_design(const Design*);
void end_design(const Design*);
bool bufz(const NetBUFZ*);
void event(const NetEvent*);
void logic(const NetLogic*);
bool net_const(const NetConst*);
void net_probe(const NetEvProbe*);
bool process(const NetProcTop*);
void scope(const NetScope*);
void signal(const NetNet*);
void*dll_;
string dll_path_;
struct ivl_design_s ivl_des;
start_design_f start_design_;
end_design_f end_design_;
net_bufz_f net_bufz_;
net_const_f net_const_;
net_event_f net_event_;
net_logic_f net_logic_;
net_probe_f net_probe_;
net_signal_f net_signal_;
process_f process_;
scope_f scope_;
} dll_target_obj;
static struct dll_target dll_target_obj;
bool dll_target::start_design(const Design*des)
{
@ -93,7 +35,9 @@ bool dll_target::start_design(const Design*des)
return false;
}
ivl_des.des_ = des;
stmt_cur_ = 0;
des_ = (ivl_design_t)des;
start_design_ = (start_design_f)dlsym(dll_, "target_start_design");
end_design_ = (end_design_f) dlsym(dll_, "target_end_design");
@ -107,13 +51,13 @@ bool dll_target::start_design(const Design*des)
process_ = (process_f) dlsym(dll_, LU "target_process" TU);
scope_ = (scope_f) dlsym(dll_, LU "target_scope" TU);
(start_design_)(&ivl_des);
(start_design_)(des_);
return true;
}
void dll_target::end_design(const Design*)
{
(end_design_)(&ivl_des);
(end_design_)(des_);
dlclose(dll_);
}
@ -195,25 +139,6 @@ void dll_target::net_probe(const NetEvProbe*net)
return;
}
bool dll_target::process(const NetProcTop*net)
{
struct ivl_process_s obj;
obj.top_ = net;
if (process_) {
int rc = (process_)(&obj);
return rc == 0;
} else {
cerr << dll_path_ << ": internal error: target DLL lacks "
<< "target_process function." << endl;
return false;
}
return false;
}
void dll_target::scope(const NetScope*net)
{
if (scope_)
@ -236,54 +161,11 @@ void dll_target::signal(const NetNet*net)
extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_get_flag(ivl_design_t des, const char*key)
{
return des->des_->get_flag(key).c_str();
}
extern "C" const char*ivl_get_root_name(ivl_design_t des)
{
return des->des_->find_root_scope()->name().c_str();
}
extern "C" ivl_logic_t ivl_get_logic_type(ivl_net_logic_t net)
{
switch (net->dev_->type()) {
case NetLogic::AND:
return IVL_AND;
case NetLogic::OR:
return IVL_OR;
}
assert(0);
return IVL_AND;
}
extern "C" unsigned ivl_get_logic_pins(ivl_net_logic_t net)
{
return net->dev_->pin_count();
}
extern "C" ivl_nexus_t ivl_get_logic_pin(ivl_net_logic_t net, unsigned pin)
{
return (ivl_nexus_t) (net->dev_->pin(pin).nexus());
}
extern "C" const char* ivl_get_nexus_name(ivl_nexus_t net)
{
const Nexus*nex = (const Nexus*)net;
return nex->name();
}
extern "C" unsigned ivl_get_signal_pins(ivl_net_signal_t net)
{
const NetNet*sig = (const NetNet*)net;
return sig->pin_count();
}
/*
* $Log: t-dll.cc,v $
* Revision 1.7 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
* Revision 1.6 2000/08/27 15:51:51 steve
* t-dll iterates signals, and passes them to the
* target module.

155
t-dll.h Normal file
View File

@ -0,0 +1,155 @@
#ifndef __t_dll_H
#define __t_dll_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.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) && !defined(macintosh)
#ident "$Id: t-dll.h,v 1.1 2000/09/18 01:24:32 steve Exp $"
#endif
# include "target.h"
# include "ivl_target.h"
/*
* The DLL target type loads a named object file to handle the process
* of scanning the netlist. When it is time to start the design, I
* locate and link in the desired DLL, then start calling methods. The
* DLL will call me back to get information out of the netlist in
* particular.
*/
struct dll_target : public target_t {
bool start_design(const Design*);
void end_design(const Design*);
bool bufz(const NetBUFZ*);
void event(const NetEvent*);
void logic(const NetLogic*);
bool net_const(const NetConst*);
void net_probe(const NetEvProbe*);
bool process(const NetProcTop*);
void scope(const NetScope*);
void signal(const NetNet*);
void*dll_;
string dll_path_;
ivl_design_t des_;
start_design_f start_design_;
end_design_f end_design_;
net_bufz_f net_bufz_;
net_const_f net_const_;
net_event_f net_event_;
net_logic_f net_logic_;
net_probe_f net_probe_;
net_signal_f net_signal_;
process_f process_;
scope_f scope_;
/* These methods and members are used for forming the
statements of a thread. */
struct ivl_statement_s*stmt_cur_;
void proc_assign(const NetAssign*);
bool proc_block(const NetBlock*);
void proc_condit(const NetCondit*);
bool proc_delay(const NetPDelay*);
bool proc_wait(const NetEvWait*);
void proc_while(const NetWhile*);
};
/*
* These are various private declarations used by the t-dll target.
*/
struct ivl_net_const_s {
const NetConst*con_;
};
struct ivl_net_logic_s {
const NetLogic*dev_;
};
struct ivl_process_s {
ivl_process_type_t type_;
ivl_statement_t stmt_;
};
/*
* The ivl_statement_t represents any statement. The type of statement
* is defined by the ivl_statement_type_t enumeration. Given the type,
* certain information about the statement may be available.
*/
typedef enum ivl_statement_type_e {
IVL_ST_NONE = 0,
IVL_ST_NOOP = 1,
IVL_ST_ASSIGN,
IVL_ST_BLOCK,
IVL_ST_CONDIT,
IVL_ST_DELAY,
IVL_ST_DELAYX,
IVL_ST_WAIT,
IVL_ST_WHILE
} ivl_statement_type_t;
struct ivl_statement_s {
enum ivl_statement_type_e type_;
union {
struct { /* IVL_ST_BLOCK */
struct ivl_statement_s*stmt_;
unsigned nstmt_;
} block_;
struct { /* IVL_ST_CONDIT */
struct ivl_statement_s*stmt_;
} condit_;
struct { /* IVL_ST_DELAY */
unsigned long delay_;
ivl_statement_t stmt_;
} delay_;
struct { /* IVL_ST_DELAYX */
int expr_; /* XXXX */
ivl_statement_t stmt_;
} delayx_;
struct { /* IVL_ST_WAIT */
int cond_; /* XXXX */
ivl_statement_t stmt_;
} wait_;
struct { /* IVL_ST_WHILE */
int cond_; /* XXXX */
ivl_statement_t stmt_;
} while_;
} u_;
};
/*
* $Log: t-dll.h,v $
* Revision 1.1 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
*/
#endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: stub.c,v 1.6 2000/08/27 15:51:51 steve Exp $"
#ident "$Id: stub.c,v 1.7 2000/09/18 01:24:32 steve Exp $"
#endif
/*
@ -115,12 +115,24 @@ int target_net_signal(const char*name, ivl_net_signal_t net)
int target_process(ivl_process_t net)
{
fprintf(out, "STUB: process\n");
switch (ivl_get_process_type(net)) {
case IVL_PR_INITIAL:
fprintf(out, " initial\n");
break;
case IVL_PR_ALWAYS:
fprintf(out, " always\n");
break;
}
fprintf(out, " STUB: process\n");
return 0;
}
/*
* $Log: stub.c,v $
* Revision 1.7 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
* Revision 1.6 2000/08/27 15:51:51 steve
* t-dll iterates signals, and passes them to the
* target module.