From 0edb5a7547bc089533d3da23cb6dd7f015067507 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 23 Sep 2006 04:57:19 +0000 Subject: [PATCH] Basic support for specify timing. --- Makefile.in | 4 +- Module.h | 8 ++- PSpec.h | 48 ++++++++++++++++++ design_dump.cc | 30 ++++++++++- elaborate.cc | 118 +++++++++++++++++++++++++++++++++++++++++++- ivl_target.h | 37 +++++++++++++- netlist.cc | 113 +++++++++++++++++++++++++++++++++++++++++- netlist.h | 55 ++++++++++++++++++++- parse.y | 45 ++++++++++++----- pform.cc | 51 +++++++++++++++++-- pform.h | 14 ++++-- pform_dump.cc | 40 ++++++++++++++- t-dll-api.cc | 27 +++++++++- t-dll.cc | 27 +++++++++- t-dll.h | 13 ++++- tgt-stub/stub.c | 29 ++++++++++- tgt-vvp/vvp_scope.c | 85 +++++++++++++++++++++++++++++-- vvp/README.txt | 10 +++- vvp/compile.cc | 44 ++++++++++++++++- vvp/compile.h | 12 ++++- vvp/delay.cc | 86 +++++++++++++++++++++++++++++++- vvp/delay.h | 58 +++++++++++++++++++++- vvp/lexor.lex | 6 ++- vvp/parse.y | 35 ++++++++++++- vvp/parse_misc.cc | 12 ++++- vvp/parse_misc.h | 6 ++- 26 files changed, 966 insertions(+), 47 deletions(-) create mode 100644 PSpec.h diff --git a/Makefile.in b/Makefile.in index 525e85095..d32413af3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.177 2006/09/20 22:31:45 steve Exp $" +#ident "$Id: Makefile.in,v 1.178 2006/09/23 04:57:19 steve Exp $" # # SHELL = /bin/sh @@ -111,7 +111,7 @@ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o symbol_search.o sync.o sys_funcs.o \ verinum.o verireal.o target.o targets.o \ Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ -PExpr.o PGate.o PGenerate.o \ +PExpr.o PGate.o PGenerate.o PSpec.o \ PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \ $(FF) $(TT) diff --git a/Module.h b/Module.h index 7c217b7dc..4a8077523 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Module.h,v 1.40 2006/04/10 00:37:42 steve Exp $" +#ident "$Id: Module.h,v 1.41 2006/09/23 04:57:19 steve Exp $" #endif # include @@ -35,6 +35,7 @@ class PExpr; class PEIdent; class PGate; class PGenerate; +class PSpecPath; class PTask; class PFunction; class PWire; @@ -122,6 +123,8 @@ class Module : public LineInfo { the module definition. These are used at elaboration time. */ list generate_schemes; + list specify_paths; + perm_string mod_name() const { return name_; } void add_gate(PGate*gate); @@ -173,6 +176,9 @@ class Module : public LineInfo { /* * $Log: Module.h,v $ + * Revision 1.41 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.40 2006/04/10 00:37:42 steve * Add support for generate loops w/ wires and gates. * diff --git a/PSpec.h b/PSpec.h new file mode 100644 index 000000000..7f1f9d089 --- /dev/null +++ b/PSpec.h @@ -0,0 +1,48 @@ +#ifndef __PSpec_H +#define __PSpec_H +/* + * Copyright (c) 2006 Stephen Williams + * + * 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 + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: PSpec.h,v 1.1 2006/09/23 04:57:19 steve Exp $" +#endif + +# include "LineInfo.h" +# include "StringHeap.h" +# include + +class PSpecPath : public LineInfo { + + public: + PSpecPath(unsigned src_cnt, unsigned dst_cnt); + ~PSpecPath(); + + void elaborate(class Design*des, class NetScope*scope) const; + + void dump(std::ostream&out, unsigned ind) const; + + public: + // Ordered set of source nodes of a path + std::vector src; + // Ordered set of destination nodes of a path + std::vector dst; + + std::vectordelays; +}; + +#endif diff --git a/design_dump.cc b/design_dump.cc index 6bf89046f..c8caf2c85 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.167 2006/07/31 03:50:17 steve Exp $" +#ident "$Id: design_dump.cc,v 1.168 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -90,6 +90,25 @@ ostream& operator << (ostream&o, ivl_variable_type_t val) return o; } +void NetDelaySrc::dump(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "specify delay src " + << "(" << transition_delays_[IVL_PE_01] + << "," << transition_delays_[IVL_PE_10] + << "," << transition_delays_[IVL_PE_0z] + << "/" << transition_delays_[IVL_PE_z1] + << "," << transition_delays_[IVL_PE_1z] + << "," << transition_delays_[IVL_PE_z0] + << "/" << transition_delays_[IVL_PE_0x] + << "," << transition_delays_[IVL_PE_x1] + << "," << transition_delays_[IVL_PE_1x] + << "/" << transition_delays_[IVL_PE_x0] + << "," << transition_delays_[IVL_PE_xz] + << "," << transition_delays_[IVL_PE_zx] + << "): " << endl; + dump_node_pins(o, ind+4); +} + /* Dump a net. This can be a wire or register. */ void NetNet::dump_net(ostream&o, unsigned ind) const { @@ -139,6 +158,12 @@ void NetNet::dump_net(ostream&o, unsigned ind) const o << setw(ind+4) << "" << "[" << idx << "]: " << nex << " " << nex->name() << endl; } + + for (unsigned idx = 0 ; idx < delay_paths_.size() ; idx += 1) { + const NetDelaySrc*cur = delay_paths_[idx]; + cur->dump(o, ind+4); + } + dump_obj_attr(o, ind+4); } @@ -1183,6 +1208,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.168 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.167 2006/07/31 03:50:17 steve * Add support for power in constant expressions. * diff --git a/elaborate.cc b/elaborate.cc index 7d561b8e1..94515dcb3 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2006 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.342 2006/09/22 22:14:27 steve Exp $" +#ident "$Id: elaborate.cc,v 1.343 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -35,6 +35,7 @@ # include "pform.h" # include "PEvent.h" # include "PGenerate.h" +# include "PSpec.h" # include "netlist.h" # include "netmisc.h" # include "util.h" @@ -2872,6 +2873,108 @@ NetProc* PWhile::elaborate(Design*des, NetScope*scope) const return loop; } +void PSpecPath::elaborate(Design*des, NetScope*scope) const +{ + uint64_t delay_value[12]; + unsigned ndelays = 0; + + ndelays = delays.size(); + if (ndelays > 12) + ndelays = 12; + + /* Elaborate the delay values themselves. */ + for (unsigned idx = 0 ; idx < ndelays ; idx += 1) { + PExpr*exp = delays[idx]; + NetExpr*cur = elab_and_eval(des, scope, exp, 0); + + if (NetEConst*cur_con = dynamic_cast (cur)) { + delay_value[idx] = cur_con->value().as_ulong(); + } else { + cerr << cur->get_line() << ": error: Path delay value " + << "must be constant." << endl; + delay_value[idx] = 0; + des->errors += 1; + } + delete cur; + } + + switch (ndelays) { + case 1: + case 2: + case 3: + case 6: + case 12: + break; + default: + cerr << get_line() << ": error: Incorrect delay configuration." + << endl; + ndelays = 1; + des->errors += 1; + break; + } + + /* Create all the various paths from the path specifier. */ + typedef std::vector::const_iterator str_vector_iter; + for (str_vector_iter cur = dst.begin() + ; cur != dst.end() ; cur ++) { + + if (debug_elaborate) { + cerr << get_line() << ": debug: Path to " << (*cur) << endl; + } + + NetNet*dst_sig = scope->find_signal(*cur); + if (dst_sig == 0) { + cerr << get_line() << ": error: No such wire " + << *cur << " in this module." << endl; + des->errors += 1; + continue; + } + + NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(), + src.size()); + path->set_line(*this); + + switch (ndelays) { + case 12: + path->set_delays(delay_value[0], delay_value[1], + delay_value[2], delay_value[3], + delay_value[4], delay_value[5], + delay_value[6], delay_value[7], + delay_value[8], delay_value[9], + delay_value[10], delay_value[11]); + break; + case 6: + path->set_delays(delay_value[0], delay_value[1], + delay_value[2], delay_value[3], + delay_value[4], delay_value[5]); + break; + case 3: + path->set_delays(delay_value[0], delay_value[1], + delay_value[2]); + break; + case 2: + path->set_delays(delay_value[0], delay_value[1]); + break; + case 1: + path->set_delays(delay_value[0]); + break; + } + + unsigned idx = 0; + for (str_vector_iter cur_src = src.begin() + ; cur_src != src.end() ; cur_src ++) { + NetNet*src_sig = scope->find_signal(*cur_src); + assert(src_sig); + + connect(src_sig->pin(0), path->pin(idx)); + idx += 1; + } + + dst_sig->add_delay_path(path); + } + +} + /* * When a module is instantiated, it creates the scope then uses this * method to elaborate the contents of the module. @@ -3003,6 +3106,14 @@ bool Module::elaborate(Design*des, NetScope*scope) const } + // Elaborate the specify paths of the module. + + for (list::const_iterator sp = specify_paths.begin() + ; sp != specify_paths.end() ; sp ++) { + + (*sp)->elaborate(des, scope); + } + return result_flag; } @@ -3144,6 +3255,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.343 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.342 2006/09/22 22:14:27 steve * Proper error message when logic array pi count is bad. * diff --git a/ivl_target.h b/ivl_target.h index 3fd0318e3..55ba728c3 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.170 2006/08/08 05:11:37 steve Exp $" +#ident "$Id: ivl_target.h,v 1.171 2006/09/23 04:57:19 steve Exp $" #endif # include @@ -137,6 +137,7 @@ _BEGIN_DECL * scope. These names are unique within a scope, but not necessarily * throughout the design. */ +typedef struct ivl_delaypath_s*ivl_delaypath_t; typedef struct ivl_design_s *ivl_design_t; typedef struct ivl_event_s *ivl_event_t; typedef struct ivl_expr_s *ivl_expr_t; @@ -255,6 +256,16 @@ typedef enum ivl_lpm_type_e { IVL_LPM_UFUNC = 14 } ivl_lpm_type_t; +/* The path edge type is the edge type used to select a specific + delay. */ +typedef enum ivl_path_edge_e { + IVL_PE_01 = 0, IVL_PE_10, IVL_PE_0z, + IVL_PE_z1, IVL_PE_1z, IVL_PE_z0, + IVL_PE_0x, IVL_PE_x1, IVL_PE_1x, + IVL_PE_x0, IVL_PE_xz, IVL_PE_zx, + IVL_PE_COUNT +} ivl_path_edge_t; + /* Processes are initial or always blocks with a statement. This is the type of the ivl_process_t object. */ typedef enum ivl_process_type_e { @@ -361,6 +372,19 @@ struct ivl_attribute_s { }; typedef const struct ivl_attribute_s*ivl_attribute_t; +/* DELAYPATH + * Delaypath objects represent delay paths called out by a specify + * block in the verilog source file. The destination signal references + * the path object, which in turn points to the source for the path. + * + * ivl_path_source + * This returns the nexus that is the source end of the delay + * path. Transitions on the source are the start of the delay time + * for this path. + */ +extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj); +extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt); + /* DESIGN * When handed a design (ivl_design_t) there are a few things that you @@ -1450,6 +1474,12 @@ extern int ivl_scope_time_units(ivl_scope_t net); * etc. All the signals connected to a nexus should have the same * data type * + * ivl_signal_npath + * ivl_signal_path + * This function returns the delay path object for the signal. The + * delay path has this signal as the output, the source is attached + * to the delay path itself. + * * ivl_signal_name (DEPRECATED) * This function returns the fully scoped hierarchical name for the * signal. The name refers to the entire vector that is the signal. @@ -1481,6 +1511,8 @@ extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net); extern int ivl_signal_signed(ivl_signal_t net); extern int ivl_signal_integer(ivl_signal_t net); extern int ivl_signal_local(ivl_signal_t net); +extern unsigned ivl_signal_npath(ivl_signal_t net); +extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx); extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net); extern ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net); extern const char* ivl_signal_name(ivl_signal_t net); @@ -1720,6 +1752,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.171 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.170 2006/08/08 05:11:37 steve * Handle 64bit delay constants. * diff --git a/netlist.cc b/netlist.cc index 33e1862c4..73fff0753 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.248 2005/09/14 02:53:14 steve Exp $" +#ident "$Id: netlist.cc,v 1.249 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -237,6 +237,99 @@ NetBus::~NetBus() { } +NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins) +: NetObj(s, n, npins) +{ + for (unsigned idx = 0 ; idx < npins ; idx += 1) { + pin(idx).set_name(perm_string::literal("I"), idx); + pin(idx).set_dir(Link::INPUT); + } +} + +NetDelaySrc::~NetDelaySrc() +{ +} + +void NetDelaySrc::set_delays(uint64_t del) +{ + for (unsigned idx = 0 ; idx < 12 ; idx += 1) + transition_delays_[idx] = del; +} + +void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall) +{ + transition_delays_[IVL_PE_01] = trise; + transition_delays_[IVL_PE_10] = tfall; + transition_delays_[IVL_PE_0z] = trise; + transition_delays_[IVL_PE_z1] = trise; + transition_delays_[IVL_PE_1z] = tfall; + transition_delays_[IVL_PE_z0] = tfall; + transition_delays_[IVL_PE_0x] = trise; + transition_delays_[IVL_PE_x1] = trise; + transition_delays_[IVL_PE_1x] = tfall; + transition_delays_[IVL_PE_x0] = tfall; + transition_delays_[IVL_PE_xz] = max(trise,tfall); + transition_delays_[IVL_PE_zx] = min(trise,tfall); +} + +void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall, uint64_t tz) +{ + transition_delays_[IVL_PE_01] = trise; + transition_delays_[IVL_PE_10] = tfall; + transition_delays_[IVL_PE_0z] = tz; + transition_delays_[IVL_PE_z1] = trise; + transition_delays_[IVL_PE_1z] = tz; + transition_delays_[IVL_PE_z0] = tfall; + transition_delays_[IVL_PE_0x] = min(trise,tz); + transition_delays_[IVL_PE_x1] = trise; + transition_delays_[IVL_PE_1x] = min(tfall,tz); + transition_delays_[IVL_PE_x0] = tfall; + transition_delays_[IVL_PE_xz] = tz; + transition_delays_[IVL_PE_zx] = min(trise,tfall); +} + +void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z, + uint64_t tz1, uint64_t t1z, uint64_t tz0) +{ + transition_delays_[IVL_PE_01] = t01; + transition_delays_[IVL_PE_10] = t10; + transition_delays_[IVL_PE_0z] = t0z; + transition_delays_[IVL_PE_z1] = tz1; + transition_delays_[IVL_PE_1z] = t1z; + transition_delays_[IVL_PE_z0] = tz0; + transition_delays_[IVL_PE_0x] = min(t01,t0z); + transition_delays_[IVL_PE_x1] = max(t01,tz1); + transition_delays_[IVL_PE_1x] = min(t10,t1z); + transition_delays_[IVL_PE_x0] = max(t10,tz0); + transition_delays_[IVL_PE_xz] = max(t1z,t0z); + transition_delays_[IVL_PE_zx] = min(tz1,tz0); +} + +void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z, + uint64_t tz1, uint64_t t1z, uint64_t tz0, + uint64_t t0x, uint64_t tx1, uint64_t t1x, + uint64_t tx0, uint64_t txz, uint64_t tzx) +{ + transition_delays_[IVL_PE_01] = t01; + transition_delays_[IVL_PE_10] = t10; + transition_delays_[IVL_PE_0z] = t0z; + transition_delays_[IVL_PE_z1] = tz1; + transition_delays_[IVL_PE_1z] = t1z; + transition_delays_[IVL_PE_z0] = tz0; + transition_delays_[IVL_PE_0x] = t0x; + transition_delays_[IVL_PE_x1] = tx1; + transition_delays_[IVL_PE_1x] = t1x; + transition_delays_[IVL_PE_x0] = tx0; + transition_delays_[IVL_PE_xz] = txz; + transition_delays_[IVL_PE_zx] = tzx; +} + +uint64_t NetDelaySrc::get_delay(unsigned idx) const +{ + assert(idx < 12); + return transition_delays_[idx]; +} + NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) : NetObj(s, n, 1), sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), @@ -477,6 +570,21 @@ unsigned NetNet::get_refs() const return lref_count_ + eref_count_; } +void NetNet::add_delay_path(NetDelaySrc*path) +{ + delay_paths_.push_back(path); +} + +unsigned NetNet::delay_paths(void)const +{ + return delay_paths_.size(); +} + +const NetDelaySrc* NetNet::delay_path(unsigned idx) const +{ + assert(idx < delay_paths_.size()); + return delay_paths_[idx]; +} NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid, NetPartSelect::dir_t dir) @@ -2228,6 +2336,9 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.249 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.248 2005/09/14 02:53:14 steve * Support bool expressions and compares handle them optimally. * diff --git a/netlist.h b/netlist.h index 09bb9518e..e8551d02a 100644 --- a/netlist.h +++ b/netlist.h @@ -1,7 +1,7 @@ #ifndef __netlist_H #define __netlist_H /* - * Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2006 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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.360 2006/08/08 05:11:37 steve Exp $" +#ident "$Id: netlist.h,v 1.361 2006/09/23 04:57:19 steve Exp $" #endif /* @@ -31,6 +31,7 @@ # include # include # include +# include # include # include "ivl_target.h" # include "verinum.h" @@ -369,6 +370,46 @@ class NetNode : public NetObj { Design*design_; }; +/* + * A NetDelaySrc is an input-only device that calculates a path delay + * based on the time that the inputs change. This class is used by the + * NetNet class, and NetDelaySrc objects cannot exist outside of its + * association with NetNet objects. + */ +class NetDelaySrc : public NetObj { + + public: + explicit NetDelaySrc(NetScope*s, perm_string n, unsigned npins); + ~NetDelaySrc(); + + // These functions set the delays from the values in the + // source. These set_delays functions implement the various + // rules wrt collections of transitions. + + // One transition specified. + void set_delays(uint64_t del); + // Two transitions: rise and fall + void set_delays(uint64_t rise, uint64_t fall); + // Three transitions + void set_delays(uint64_t rise, uint64_t fall, uint64_t tz); + void set_delays(uint64_t t01, uint64_t t10, uint64_t t0z, + uint64_t tz1, uint64_t t1z, uint64_t tz0); + void set_delays(uint64_t t01, uint64_t t10, uint64_t t0z, + uint64_t tz1, uint64_t t1z, uint64_t tz0, + uint64_t t0x, uint64_t tx1, uint64_t t1x, + uint64_t tx0, uint64_t txz, uint64_t tzx); + + uint64_t get_delay(unsigned pe) const; + + void dump(ostream&, unsigned ind) const; + + private: + uint64_t transition_delays_[12]; + + private: // Not implemented + NetDelaySrc(const NetDelaySrc&); + NetDelaySrc& operator= (const NetDelaySrc&); +}; /* * NetNet is a special kind of NetObj that doesn't really do anything, @@ -463,6 +504,11 @@ class NetNet : public NetObj { unsigned get_refs() const; + /* Manage path delays */ + void add_delay_path(class NetDelaySrc*path); + unsigned delay_paths(void) const; + const class NetDelaySrc*delay_path(unsigned idx) const; + virtual void dump_net(ostream&, unsigned) const; private: @@ -482,6 +528,8 @@ class NetNet : public NetObj { bool local_flag_; unsigned eref_count_; unsigned lref_count_; + + vector delay_paths_; }; /* @@ -3510,6 +3558,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.361 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.360 2006/08/08 05:11:37 steve * Handle 64bit delay constants. * diff --git a/parse.y b/parse.y index ba81dca6b..2049adfac 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.219 2006/08/08 05:11:37 steve Exp $" +#ident "$Id: parse.y,v 1.220 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -30,6 +30,8 @@ # include "Statement.h" # include +class PSpecPath; + extern void lex_start_table(); extern void lex_end_table(); @@ -141,6 +143,8 @@ static list* list_from_identifier(list*tmp, char*id) verinum* number; verireal* realtime; + + PSpecPath* specpath; }; %token IDENTIFIER SYSTEM_IDENTIFIER STRING @@ -215,7 +219,7 @@ static list* list_from_identifier(list*tmp, char*id) %type expression expr_primary %type lpvalue %type delay_value delay_value_simple -%type delay1 delay3 delay3_opt +%type delay1 delay3 delay3_opt delay_value_list %type expression_list %type assign assign_list %type indexed_identifier @@ -237,6 +241,8 @@ static list* list_from_identifier(list*tmp, char*id) %type spec_polarity %type specify_path_identifiers +%type specify_simple_path specify_simple_path_decl + %token K_TAND %right '?' ':' %left K_LOR @@ -550,6 +556,19 @@ delay3_opt | { $$ = 0; } ; +delay_value_list + : delay_value + { svector*tmp = new svector(1); + (*tmp)[0] = $1; + $$ = tmp; + } + | delay_value_list ',' delay_value + { svector*tmp = new svector(*$1, $3); + delete $1; + $$ = tmp; + } + ; + delay_value : expression { PExpr*tmp = $1; @@ -2444,7 +2463,7 @@ register_variable_list specify_item : K_specparam specparam_list ';' | specify_simple_path_decl ';' - { + { pform_module_specify_path($1); } | specify_edge_path_decl ';' { @@ -2494,18 +2513,14 @@ specify_item } ; -specify_delay_value_list - : delay_value { } - | specify_delay_value_list ',' delay_value { } - ; - specify_item_list : specify_item | specify_item_list specify_item ; specify_edge_path_decl - : specify_edge_path '=' '(' specify_delay_value_list ')' + : specify_edge_path '=' '(' delay_value_list ')' + { delete $4; } | specify_edge_path '=' delay_value_simple ; @@ -2527,21 +2542,27 @@ polarity_operator ; specify_simple_path_decl - : specify_simple_path '=' '(' specify_delay_value_list ')' + : specify_simple_path '=' '(' delay_value_list ')' + { $$ = pform_assign_path_delay($1, $4); } | specify_simple_path '=' delay_value_simple + { svector*tmp = new svector(1); + (*tmp)[0] = $3; + $$ = pform_assign_path_delay($1, tmp); + } | specify_simple_path '=' '(' error ')' { yyerror(@2, "Syntax error in delay value list."); yyerrok; + $$ = 0; } ; specify_simple_path : '(' specify_path_identifiers spec_polarity K_EG specify_path_identifiers ')' - { pform_make_specify_path($2, $3, false, $5); } + { $$ = pform_make_specify_path(@1, $2, $3, false, $5); } | '(' specify_path_identifiers spec_polarity K_SG specify_path_identifiers ')' - { pform_make_specify_path($2, $3, true, $5); } + { $$ = pform_make_specify_path(@1, $2, $3, true, $5); } | '(' error ')' { yyerror(@2, "Invalid simple path"); yyerrok; diff --git a/pform.cc b/pform.cc index df7fdff64..b7b3d9434 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.136 2006/08/08 05:11:37 steve Exp $" +#ident "$Id: pform.cc,v 1.137 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -29,6 +29,7 @@ # include "PEvent.h" # include "PUdp.h" # include "PGenerate.h" +# include "PSpec.h" # include # include # include @@ -1535,13 +1536,52 @@ void pform_set_defparam(const hname_t&name, PExpr*expr) } /* - * XXXX Not implemented yet. + * Specify paths. */ -extern void pform_make_specify_path(list*src, char pol, - bool full_flag, list*dst) +extern PSpecPath* pform_make_specify_path(const struct vlltype&li, + list*src, char pol, + bool full_flag, list*dst) { + PSpecPath*path = new PSpecPath(src->size(), dst->size()); + path->set_file(li.text); + path->set_lineno(li.first_line); + + unsigned idx; + list::const_iterator cur; + + idx = 0; + for (idx = 0, cur = src->begin() ; cur != src->end() ; idx++, cur++) { + path->src[idx] = *cur; + } + assert(idx == path->src.size()); delete src; + + for (idx = 0, cur = dst->begin() ; cur != dst->end() ; idx++, cur++) { + path->dst[idx] = *cur; + } + assert(idx == path->dst.size()); delete dst; + + return path; +} + +extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector*del) +{ + assert(path->delays.size() == 0); + + path->delays.resize(del->count()); + for (unsigned idx = 0 ; idx < path->delays.size() ; idx += 1) + path->delays[idx] = (*del)[idx]; + + delete del; + + return path; +} + + +extern void pform_module_specify_path(PSpecPath*obj) +{ + pform_cur_module->specify_paths.push_back(obj); } void pform_set_port_type(const struct vlltype&li, @@ -1707,6 +1747,9 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.137 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.136 2006/08/08 05:11:37 steve * Handle 64bit delay constants. * diff --git a/pform.h b/pform.h index de10c243b..2125e4317 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.86 2006/04/10 00:37:42 steve Exp $" +#ident "$Id: pform.h,v 1.87 2006/09/23 04:57:19 steve Exp $" #endif # include "netlist.h" @@ -57,6 +57,7 @@ */ class PGate; class PExpr; +class PSpecPath; struct vlltype; /* @@ -260,8 +261,12 @@ extern void pform_set_defparam(const hname_t&name, PExpr*expr); * Functions related to specify blocks. */ extern void pform_set_specparam(perm_string name, PExpr*expr); -extern void pform_make_specify_path(list*src, char pol, - bool full_flag, list*dst); + +extern PSpecPath*pform_make_specify_path(const struct vlltype&li, + list*src, char pol, + bool full_flag, list*dst); +extern PSpecPath*pform_assign_path_delay(PSpecPath*obj, svector*delays); +extern void pform_module_specify_path(PSpecPath*obj); /* * pform_make_behavior creates processes that are declared with always @@ -323,6 +328,9 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.87 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.86 2006/04/10 00:37:42 steve * Add support for generate loops w/ wires and gates. * diff --git a/pform_dump.cc b/pform_dump.cc index 0d5c98d95..b26d3b835 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.93 2006/04/28 04:19:31 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.94 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -31,6 +31,7 @@ # include "pform.h" # include "PEvent.h" # include "PGenerate.h" +# include "PSpec.h" # include # include # include @@ -739,6 +740,33 @@ void PProcess::dump(ostream&out, unsigned ind) const statement_->dump(out, ind+2); } +void PSpecPath::dump(std::ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "specify path ("; + + for (unsigned idx = 0 ; idx < src.size() ; idx += 1) { + if (idx > 0) out << ", "; + assert(src[idx]); + out << src[idx]; + } + + out << " => "; + + for (unsigned idx = 0 ; idx < dst.size() ; idx += 1) { + if (idx > 0) out << ", "; + assert(dst[idx]); + out << dst[idx]; + } + + out << ") = ("; + for (unsigned idx = 0 ; idx < delays.size() ; idx += 1) { + if (idx > 0) out << ", "; + assert(delays[idx]); + out << *delays[idx]; + } + out << ");" << endl; +} + void PGenerate::dump(ostream&out) const { out << " generate(" << id_number << ")"; @@ -920,6 +948,13 @@ void Module::dump(ostream&out) const (*behav)->dump(out, 4); } + for (list::const_iterator spec = specify_paths.begin() + ; spec != specify_paths.end() + ; spec ++ ) { + + (*spec)->dump(out, 4); + } + out << "endmodule" << endl; } @@ -972,6 +1007,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.94 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.93 2006/04/28 04:19:31 steve * Dump indexes of ident expressions * diff --git a/t-dll-api.cc b/t-dll-api.cc index d1f1356d2..04d7bb21c 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-api.cc,v 1.136 2006/09/20 22:31:23 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.137 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -1283,6 +1283,17 @@ extern "C" ivl_scope_t ivl_parameter_scope(ivl_parameter_t net) return net->scope; } +extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t edg) +{ + assert(obj); + return obj->delay[edg]; +} + +extern ivl_nexus_t ivl_path_source(ivl_delaypath_t net) +{ + return net->src; +} + extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net) { return net->type_; @@ -1606,6 +1617,17 @@ extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net) return net->data_type; } +extern "C" unsigned ivl_signal_npath(ivl_signal_t net) +{ + return net->npath; +} + +extern "C" ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx) +{ + assert(idx < net->npath); + return net->path + idx; +} + extern "C" ivl_signal_type_t ivl_signal_type(ivl_signal_t net) { return net->type_; @@ -1954,6 +1976,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.137 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.136 2006/09/20 22:31:23 steve * Remove dead code. * diff --git a/t-dll.cc b/t-dll.cc index 71d7215b2..874e25e30 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.cc,v 1.157 2006/06/18 04:15:50 steve Exp $" +#ident "$Id: t-dll.cc,v 1.158 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" @@ -2174,6 +2174,28 @@ void dll_target::signal(const NetNet*net) break; } + /* Collect the delay paths for this signal. */ + obj->npath = net->delay_paths(); + if (obj->npath > 0) { + obj->path = new struct ivl_delaypath_s[obj->npath]; + + for (unsigned idx = 0 ; idx < obj->npath ; idx += 1) { + const NetDelaySrc*src = net->delay_path(idx); + // For now, only handle single-source paths. + assert(src->pin_count() == 1); + const Nexus*nex = src->pin(0).nexus(); + assert(nex->t_cookie()); + obj->path[idx].src = (ivl_nexus_t) nex->t_cookie(); + + for (unsigned pe = 0 ; pe < 12 ; pe += 1) { + obj->path[idx].delay[pe] = src->get_delay(pe); + } + } + + } else { + obj->path = 0; + } + obj->data_type = net->data_type(); obj->nattr = net->attr_cnt(); obj->attr = fill_in_attributes(net); @@ -2207,6 +2229,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.158 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.157 2006/06/18 04:15:50 steve * Add support for system functions in continuous assignments. * diff --git a/t-dll.h b/t-dll.h index 60f69911f..7ac53e387 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.h,v 1.132 2006/08/08 05:11:37 steve Exp $" +#ident "$Id: t-dll.h,v 1.133 2006/09/23 04:57:19 steve Exp $" #endif # include "target.h" @@ -177,6 +177,11 @@ struct dll_target : public target_t, public expr_scan_t { * These are various private declarations used by the t-dll target. */ +struct ivl_delaypath_s { + ivl_nexus_t src; + uint64_t delay[12]; +}; + struct ivl_event_s { perm_string name; ivl_scope_t scope; @@ -585,6 +590,9 @@ struct ivl_signal_s { ivl_nexus_t pin_; + ivl_delaypath_s*path; + unsigned npath; + struct ivl_attribute_s*attr; unsigned nattr; }; @@ -671,6 +679,9 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.133 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.132 2006/08/08 05:11:37 steve * Handle 64bit delay constants. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 2350aa7b6..7e2e26b0e 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,12 +17,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: stub.c,v 1.140 2006/07/30 02:51:36 steve Exp $" +#ident "$Id: stub.c,v 1.141 2006/09/23 04:57:19 steve Exp $" #endif # include "config.h" # include "priv.h" # include +# include # include FILE*out; @@ -1331,6 +1332,29 @@ static void show_signal(ivl_signal_t net) } } + for (idx = 0 ; idx < ivl_signal_npath(net) ; idx += 1) { + ivl_delaypath_t path = ivl_signal_path(net,idx); + ivl_nexus_t nex = ivl_path_source(path); + + fprintf(out, " path %s", ivl_nexus_name(nex)); + fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64 + " %" PRIu64 ",%" PRIu64 ",%" PRIu64 + " %" PRIu64 ",%" PRIu64 ",%" PRIu64 + " %" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n", + ivl_path_delay(path, IVL_PE_01), + ivl_path_delay(path, IVL_PE_10), + ivl_path_delay(path, IVL_PE_0z), + ivl_path_delay(path, IVL_PE_z1), + ivl_path_delay(path, IVL_PE_1z), + ivl_path_delay(path, IVL_PE_z0), + ivl_path_delay(path, IVL_PE_0x), + ivl_path_delay(path, IVL_PE_x1), + ivl_path_delay(path, IVL_PE_1x), + ivl_path_delay(path, IVL_PE_x0), + ivl_path_delay(path, IVL_PE_xz), + ivl_path_delay(path, IVL_PE_zx)); + } + for (idx = 0 ; idx < ivl_signal_attr_cnt(net) ; idx += 1) { ivl_attribute_t atr = ivl_signal_attr_val(net, idx); @@ -1647,6 +1671,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.141 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.140 2006/07/30 02:51:36 steve * Fix/implement signed right shift. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 807db0a37..728fb674c 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,16 +17,17 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_scope.c,v 1.146 2006/07/30 02:51:36 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.147 2006/09/23 04:57:19 steve Exp $" #endif # include "vvp_priv.h" -# include #ifdef HAVE_MALLOC_H # include #endif # include # include +# include +# include struct vvp_nexus_data { /* draw_net_input uses this */ @@ -376,6 +377,28 @@ static int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr) return 1; } +/* + * Given a nexus, look for a signal that has module delay + * paths. Return that signal. (There should be no more then 1.) If we + * don't find any, then return nil. + */ +static ivl_signal_t find_modpath(ivl_nexus_t nex) +{ + unsigned idx; + for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { + ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx); + ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); + if (sig == 0) + continue; + if (ivl_signal_npath(sig) == 0) + continue; + + return sig; + } + + return 0; +} + static void draw_C4_to_string(char*result, size_t nresult, ivl_net_const_t cptr) { @@ -894,6 +917,39 @@ static void draw_reg_in_scope(ivl_signal_t sig) vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb); } +static void draw_modpath(const char*label, const char*driver, + ivl_signal_t path_sig) +{ + unsigned idx; + fprintf(vvp_out, "%s .modpath %s", label, driver); + + for (idx = 0 ; idx < ivl_signal_npath(path_sig); idx += 1) { + ivl_delaypath_t path = ivl_signal_path(path_sig, idx); + ivl_nexus_t src = ivl_path_source(path); + const char*src_driver = draw_net_input(src); + fprintf(vvp_out, ",\n %s", src_driver); + fprintf(vvp_out, + " (%"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64")", + ivl_path_delay(path, IVL_PE_01), + ivl_path_delay(path, IVL_PE_10), + ivl_path_delay(path, IVL_PE_0z), + ivl_path_delay(path, IVL_PE_z1), + ivl_path_delay(path, IVL_PE_1z), + ivl_path_delay(path, IVL_PE_z0), + ivl_path_delay(path, IVL_PE_0x), + ivl_path_delay(path, IVL_PE_x1), + ivl_path_delay(path, IVL_PE_1x), + ivl_path_delay(path, IVL_PE_x0), + ivl_path_delay(path, IVL_PE_xz), + ivl_path_delay(path, IVL_PE_zx)); + } + + fprintf(vvp_out, ";\n"); +} + /* * This function draws a net. This is a bit more complicated as we * have to find an appropriate functor to connect to the input. @@ -904,6 +960,8 @@ static void draw_net_in_scope(ivl_signal_t sig) int lsb = ivl_signal_lsb(sig); typedef const char*const_charp; const char* arg; + const char* driver; + char modpath_label[64]; const char*datatype_flag = ivl_signal_signed(sig)? "/s" : ""; @@ -916,7 +974,8 @@ static void draw_net_in_scope(ivl_signal_t sig) /* Connect the pin of the signal to something. */ { ivl_nexus_t nex = ivl_signal_nex(sig); - arg = draw_net_input(nex); + driver = draw_net_input(nex); + arg = driver; nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex); assert(nex_data); @@ -930,6 +989,18 @@ static void draw_net_in_scope(ivl_signal_t sig) break; } + /* If there are module delay paths, then we are going to need + a modpath node between the drivers and the net. the + path_sig is the signal that carries the paths. There should + be 0 or one of these. */ + + ivl_signal_t path_sig = find_modpath(ivl_signal_nex(sig)); + if (path_sig) { + snprintf(modpath_label, sizeof modpath_label, + "V_%p/m", path_sig); + arg = modpath_label; + } + if (nex_data->net == 0) { const char*vec8 = ""; if (nex_data->drivers_count > 1) @@ -945,6 +1016,11 @@ static void draw_net_in_scope(ivl_signal_t sig) nex_data->drivers_count, nex_data->flags&VVP_NEXUS_DATA_STR?", strength-aware":""); nex_data->net = sig; + + if (path_sig) { + draw_modpath(modpath_label, driver, path_sig); + } + } else { /* Detect that this is an alias of nex_data->net. Create a different kind of node that refers to the alias @@ -2251,6 +2327,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.147 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.146 2006/07/30 02:51:36 steve * Fix/implement signed right shift. * diff --git a/vvp/README.txt b/vvp/README.txt index 94a6a9326..fe84dcfeb 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,7 +1,7 @@ /* * Copyright (c) 2001 Stephen Williams (steve@icarus.com) * - * $Id: README.txt,v 1.77 2006/03/18 22:51:10 steve Exp $ + * $Id: README.txt,v 1.78 2006/09/23 04:57:19 steve Exp $ */ VVP SIMULATION ENGINE @@ -342,6 +342,14 @@ delay, and takes a single input. The second form takes 4 net inputs, with the first being the value to delay, and the remaining to be the delay values to use. +MODULE PATH DELAY STATEMENTS: + +A module path delay takes data from its input, then a list of module +path delays. The for each possible delay set is a trigger that +activates the delay. + + .modpath , [ () ] ; + MEMORY STATEMENTS: Memories are arrays of words, each word a vvp_vector4_t vector of the diff --git a/vvp/compile.cc b/vvp/compile.cc index fec45c245..2d78f260f 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: compile.cc,v 1.223 2006/08/09 05:19:08 steve Exp $" +#ident "$Id: compile.cc,v 1.224 2006/09/23 04:57:19 steve Exp $" #endif # include "arith.h" @@ -1048,6 +1048,45 @@ void compile_extend_signed(char*label, long wid, struct symb_s arg) input_connect(ptr, 0, arg.text); } +vvp_fun_modpath* compile_modpath(char*label, struct symb_s src) +{ + vvp_net_t*net = new vvp_net_t; + vvp_fun_modpath*obj = new vvp_fun_modpath(net); + net->fun = obj; + + input_connect(net, 0, src.text); + + define_functor_symbol(label, net); + free(label); + + return obj; +} + +void compile_modpath_src(vvp_fun_modpath*dst, + struct symb_s src, + struct numbv_s vals) +{ + vvp_time64_t use_delay = 0; + + assert(vals.cnt == 12); + + // FIXME: For now, only support single uniform time value. + use_delay = vals.nvec[0]; + for (unsigned idx = 1 ; idx < vals.cnt ; idx += 1) { + assert(use_delay == vals.nvec[idx]); + } + + numbv_clear(&vals); + + vvp_net_t*net = new vvp_net_t; + vvp_fun_modpath_src*obj = new vvp_fun_modpath_src(use_delay); + net->fun = obj; + + input_connect(net, 0, src.text); + + dst->add_modpath_src(obj); +} + /* * A .shift/l statement creates an array of functors for the * width. The 0 input is the data vector to be shifted and the 1 input @@ -1497,6 +1536,9 @@ void compile_param_string(char*label, char*name, char*value) /* * $Log: compile.cc,v $ + * Revision 1.224 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.223 2006/08/09 05:19:08 steve * Add support for real valued modulus. * diff --git a/vvp/compile.h b/vvp/compile.h index bd70b6c9d..f72fbcff9 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: compile.h,v 1.82 2006/07/30 02:51:36 steve Exp $" +#ident "$Id: compile.h,v 1.83 2006/09/23 04:57:19 steve Exp $" #endif # include @@ -160,6 +160,13 @@ extern void compile_dff(char*label, struct symb_s arg_c, struct symb_s arg_e, struct symb_s arg_a); + +class vvp_fun_modpath; +extern vvp_fun_modpath* compile_modpath(char*label, struct symb_s src); +extern void compile_modpath_src(vvp_fun_modpath*dst, + struct symb_s input, + struct numbv_s d); + extern void compile_reduce_and(char*label, struct symb_s arg); extern void compile_reduce_or(char*label, struct symb_s arg); extern void compile_reduce_xor(char*label, struct symb_s arg); @@ -345,6 +352,9 @@ extern void compile_alias_real(char*label, char*name, /* * $Log: compile.h,v $ + * Revision 1.83 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.82 2006/07/30 02:51:36 steve * Fix/implement signed right shift. * diff --git a/vvp/delay.cc b/vvp/delay.cc index b70bfe78a..b4e573460 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: delay.cc,v 1.13 2006/07/08 21:48:00 steve Exp $" +#ident "$Id: delay.cc,v 1.14 2006/09/23 04:57:19 steve Exp $" #endif #include "delay.h" @@ -276,9 +276,93 @@ void vvp_fun_delay::run_run_real_() vvp_send_real(net_->out, cur_real_); } +vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net) +: net_(net), src_list_(0) +{ +} + +vvp_fun_modpath::~vvp_fun_modpath() +{ + // Delete the source probes. + while (src_list_) { + vvp_fun_modpath_src*tmp = src_list_; + src_list_ = tmp->next_; + delete tmp; + } +} + +void vvp_fun_modpath::add_modpath_src(vvp_fun_modpath_src*that) +{ + assert(that->next_ == 0); + that->next_ = src_list_; + src_list_ = that; +} + +void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) +{ + /* Only the first port is used. */ + if (port.port() > 0) + return; + + if (cur_vec4_.eeq(bit)) + return; + + /* Select a time delay source that applies. */ + vvp_fun_modpath_src*src = 0; + vvp_time64_t out_at = 0; + for (vvp_fun_modpath_src*cur = src_list_ ; cur ; cur=cur->next_) { + if (src == 0) { + src = cur; + } else if (cur->wake_time_ > src->wake_time_) { + src = cur; + } else { + continue; /* Skip this entry. */ + } + + out_at = src->wake_time_ + src->delay_; + } + + /* Given the scheduled output time, create an output event. */ + vvp_time64_t use_delay = 0; + vvp_time64_t now = schedule_simtime(); + if (out_at <= now) + use_delay = 0; + else + use_delay = out_at - now; + + cur_vec4_ = bit; + schedule_generic(this, use_delay, false); +} + +void vvp_fun_modpath::run_run() +{ + vvp_send_vec4(net_->out, cur_vec4_); +} + +vvp_fun_modpath_src::vvp_fun_modpath_src(vvp_time64_t del) +{ + delay_ = del; + next_ = 0; + wake_time_ = 0; +} + +vvp_fun_modpath_src::~vvp_fun_modpath_src() +{ +} + +void vvp_fun_modpath_src::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) +{ + if (port.port() != 0) + return; + + wake_time_ = schedule_simtime(); +} /* * $Log: delay.cc,v $ + * Revision 1.14 2006/09/23 04:57:19 steve + * Basic support for specify timing. + * * Revision 1.13 2006/07/08 21:48:00 steve * Delay object supports real valued delays. * diff --git a/vvp/delay.h b/vvp/delay.h index 1ccb7d07f..448004daf 100644 --- a/vvp/delay.h +++ b/vvp/delay.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: delay.h,v 1.10 2006/01/02 05:32:07 steve Exp $" +#ident "$Id: delay.h,v 1.11 2006/09/23 04:57:20 steve Exp $" #endif /* @@ -96,8 +96,64 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s { double cur_real_; }; +class vvp_fun_modpath; +class vvp_fun_modpath_src; + +class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s { + + public: + vvp_fun_modpath(vvp_net_t*net); + ~vvp_fun_modpath(); + + void add_modpath_src(vvp_fun_modpath_src*that); + + void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit); + + private: + virtual void run_run(); + + private: + vvp_net_t*net_; + + vvp_vector4_t cur_vec4_; + + vvp_fun_modpath_src*src_list_; + + private: // not implemented + vvp_fun_modpath(const vvp_fun_modpath&); + vvp_fun_modpath& operator= (const vvp_fun_modpath&); +}; + +class vvp_fun_modpath_src : public vvp_net_fun_t { + + friend class vvp_fun_modpath; + + public: + vvp_fun_modpath_src(vvp_time64_t d); + private: + ~vvp_fun_modpath_src(); + + public: + void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit); + + private: + // FIXME: Needs to be a 12-value array + vvp_time64_t delay_; + // Used by vvp_fun_modpath to keep a list of modpath_src objects. + vvp_fun_modpath_src*next_; + + vvp_time64_t wake_time_; + + private: + vvp_fun_modpath_src(const vvp_fun_modpath_src&); + vvp_fun_modpath_src& operator = (const vvp_fun_modpath_src&); +}; + /* * $Log: delay.h,v $ + * Revision 1.11 2006/09/23 04:57:20 steve + * Basic support for specify timing. + * * Revision 1.10 2006/01/02 05:32:07 steve * Require explicit delay node from source. * diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 17b1fc021..59b63f0b2 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: lexor.lex,v 1.62 2006/07/30 02:51:36 steve Exp $" +#ident "$Id: lexor.lex,v 1.63 2006/09/23 04:57:20 steve Exp $" #endif # include "parse_misc.h" @@ -111,6 +111,7 @@ ".event/or" { return K_EVENT_OR; } ".extend/s" { return K_EXTEND_S; } ".functor" { return K_FUNCTOR; } +".modpath" { return K_MODPATH; } ".net" { return K_NET; } ".net8" { return K_NET8; } ".net8/s" { return K_NET8_S; } @@ -210,6 +211,9 @@ int yywrap() /* * $Log: lexor.lex,v $ + * Revision 1.63 2006/09/23 04:57:20 steve + * Basic support for specify timing. + * * Revision 1.62 2006/07/30 02:51:36 steve * Fix/implement signed right shift. * diff --git a/vvp/parse.y b/vvp/parse.y index e7c9a0110..7b51c9ea5 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.84 2006/07/30 02:51:36 steve Exp $" +#ident "$Id: parse.y,v 1.85 2006/09/23 04:57:20 steve Exp $" #endif # include "parse_misc.h" @@ -34,6 +34,15 @@ */ extern FILE*yyin; +/* + * Local variables. + */ + +/* + * When parsing a modpath list, this is the processed destination that + * the source items will attach themselves to. + */ +static vvp_fun_modpath*modpath_dst = 0; %} %union { @@ -62,7 +71,7 @@ extern FILE*yyin; %token K_CMP_EEQ K_CMP_EQ K_CMP_NEE K_CMP_NE %token K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S %token K_CONCAT K_DELAY K_DFF -%token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_NET K_NET_S K_NET_R +%token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R %token K_NET8 K_NET8_S %token K_PARAM_STR K_PARAM_L K_PART K_PART_PV %token K_PART_V K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR @@ -297,6 +306,11 @@ statement compile_delay($1, obj.cnt, obj.vect); } + | T_LABEL K_MODPATH symbol ',' + { modpath_dst = compile_modpath($1, $3); } + modpath_src_list ';' + { modpath_dst = 0; } + /* DFF nodes have an output and take exactly 4 inputs. */ | T_LABEL K_DFF symbol ',' symbol ',' symbol ',' symbol ';' @@ -695,6 +709,20 @@ symbol_opt } ; + /* This rule is invoked within the rule for a modpath statement. The + beginning of that run has already created the modpath dst object + and saved it in the modpath_dst variable. The modpath_src rule, + then simply needs to attach the items it creates. */ +modpath_src_list + : modpath_src + | modpath_src_list ',' modpath_src + ; + +modpath_src + : symbol '(' numbers ')' + { compile_modpath_src(modpath_dst, $1, $3); } + ; + udp_table : T_STRING { $$ = compile_udp_table(0x0, $1); } @@ -750,6 +778,9 @@ int compile_design(const char*path) /* * $Log: parse.y,v $ + * Revision 1.85 2006/09/23 04:57:20 steve + * Basic support for specify timing. + * * Revision 1.84 2006/07/30 02:51:36 steve * Fix/implement signed right shift. * diff --git a/vvp/parse_misc.cc b/vvp/parse_misc.cc index e29992d62..08d68fe36 100644 --- a/vvp/parse_misc.cc +++ b/vvp/parse_misc.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse_misc.cc,v 1.8 2002/08/12 01:35:08 steve Exp $" +#ident "$Id: parse_misc.cc,v 1.9 2006/09/23 04:57:20 steve Exp $" #endif # include "parse_misc.h" @@ -63,6 +63,13 @@ void numbv_add(struct numbv_s*obj, long item) obj->cnt += 1; } +void numbv_clear(struct numbv_s*obj) +{ + free(obj->nvec); + obj->nvec = 0; + obj->cnt = 0; +} + void argv_init(struct argv_s*obj) { obj->argc = 0; @@ -98,6 +105,9 @@ void argv_sym_lookup(struct argv_s*obj) /* * $Log: parse_misc.cc,v $ + * Revision 1.9 2006/09/23 04:57:20 steve + * Basic support for specify timing. + * * Revision 1.8 2002/08/12 01:35:08 steve * conditional ident string using autoconfig. * diff --git a/vvp/parse_misc.h b/vvp/parse_misc.h index d2843c8f5..441e42ab3 100644 --- a/vvp/parse_misc.h +++ b/vvp/parse_misc.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse_misc.h,v 1.7 2002/08/12 01:35:08 steve Exp $" +#ident "$Id: parse_misc.h,v 1.8 2006/09/23 04:57:20 steve Exp $" #endif @@ -63,6 +63,7 @@ struct numbv_s { extern void numbv_init(struct numbv_s*obj); extern void numbv_add(struct numbv_s*obj, long item); +extern void numbv_clear(struct numbv_s*obj); struct argv_s { unsigned argc; @@ -77,6 +78,9 @@ extern void argv_sym_lookup(struct argv_s*obj); /* * $Log: parse_misc.h,v $ + * Revision 1.8 2006/09/23 04:57:20 steve + * Basic support for specify timing. + * * Revision 1.7 2002/08/12 01:35:08 steve * conditional ident string using autoconfig. *