diff --git a/Makefile.in b/Makefile.in index 2beb72a0f..79b384dd0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ diff --git a/ivl_target.h b/ivl_target.h index a01e7abd4..72c92ae2d 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -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. diff --git a/t-dll-api.cc b/t-dll-api.cc new file mode 100644 index 000000000..129215e15 --- /dev/null +++ b/t-dll-api.cc @@ -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. + * + */ + diff --git a/t-dll-proc.cc b/t-dll-proc.cc new file mode 100644 index 000000000..56ef56490 --- /dev/null +++ b/t-dll-proc.cc @@ -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 + + +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. + * + */ + diff --git a/t-dll.cc b/t-dll.cc index 3bc67ea2b..dcff8a7d5 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -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 -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. diff --git a/t-dll.h b/t-dll.h new file mode 100644 index 000000000..6784ce2d4 --- /dev/null +++ b/t-dll.h @@ -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 diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 6d7e983ac..376713277 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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.