#ifndef __vvm_gates_H #define __vvm_gates_H /* * Copyright (c) 1998-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 */ #ifdef HAVE_CVS_IDENT #ident "$Id: vvm_gates.h,v 1.73 2002/08/12 01:35:07 steve Exp $" #endif # include "vvm.h" # include "vvm_signal.h" # include extern vpip_bit_t compute_nand(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t compute_and(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t compute_nor(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t compute_or(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t compute_xor(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t compute_xnor(const vpip_bit_t*inp, unsigned count); extern vpip_bit_t reduce_strength(vpip_bit_t); extern void compute_mux(vpip_bit_t*out, unsigned wid, const vpip_bit_t*sel, unsigned swid, const vpip_bit_t*dat, unsigned size); /* * A vvm gate is constructed with an input width and an output * function. The input width represents all the input signals that go * into generating a single output value. The output value is passed * to the output function, which may fan the result however makes * sense. The output is scheduled as an event. */ class vvm_out_event : public vvm_event { public: typedef void (*action_t)(vpip_bit_t); // XXXX Remove me! vvm_out_event(vpip_bit_t v, vvm_nexus::drive_t*o); ~vvm_out_event(); void event_function(); private: vvm_nexus::drive_t*output_; const vpip_bit_t val_; }; class vvm_1bit_out : public vvm_nexus::drive_t { public: vvm_1bit_out(unsigned delay); ~vvm_1bit_out(); void output(vpip_bit_t); void drive0(vpip_bit_t); void drive1(vpip_bit_t); void driveZ(vpip_bit_t); private: unsigned delay_; vpip_bit_t drive0_; vpip_bit_t drive1_; vpip_bit_t driveX_; vpip_bit_t driveZ_; }; /* * This class implements the LPM_ADD_SUB device type. The width of * the device is a constructor parameter. The device handles addition and * subtraction, selectable by the Add_Sub input. When configured as a * subtractor, the device works by adding the 2s complement of * DataB. */ class vvm_add_sub : public vvm_nexus::recvr_t { public: explicit vvm_add_sub(unsigned width); ~vvm_add_sub(); vvm_nexus::drive_t* config_rout(unsigned idx); vvm_nexus::drive_t* config_cout(); unsigned key_DataA(unsigned idx) const; unsigned key_DataB(unsigned idx) const; void init_DataA(unsigned idx, vpip_bit_t val); void init_DataB(unsigned idx, vpip_bit_t val); void init_Add_Sub(unsigned, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); unsigned width_; vpip_bit_t*ibits_; vpip_bit_t c_; // this is the inverse of the Add_Sub port. It is 0 for add, // and 1 for subtract. vpip_bit_t ndir_; vvm_nexus::drive_t*ro_; vvm_nexus::drive_t co_; void compute_(); private: // not implemented vvm_add_sub(const vvm_add_sub&); vvm_add_sub& operator= (const vvm_add_sub&); }; /* * These are implementations of reduction AND. the vvm_and class is * the parameterized form, that takes the width of the gate input as a * parameter. The vvm_andN classes are versions that have specific * widths. The latter should be preferred over the generic form. */ class vvm_and : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_and(unsigned wid, unsigned long d); ~vvm_and(); void init_I(unsigned idx, vpip_bit_t val); void start(); void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; class vvm_and2 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_and2(unsigned long d); ~vvm_and2(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t input_[2]; }; /* * This class implements LPM_CLSHIFT devices with specified data width * and selector input width. The direction bit is a single bit input. */ class vvm_clshift : public vvm_nexus::recvr_t { public: vvm_clshift(unsigned wid, unsigned dwid); ~vvm_clshift(); void init_Data(unsigned idx, vpip_bit_t val); void init_Distance(unsigned idx, vpip_bit_t val); void init_Direction(unsigned, vpip_bit_t val); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_Data(unsigned idx) const; unsigned key_Distance(unsigned idx) const; unsigned key_Direction(unsigned) const; private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_, wdist_; vpip_bit_t dir_; int dist_val_; vpip_bit_t*ibits_; vvm_nexus::drive_t*out_; void calculate_dist_(); void compute_(); }; /* * This class implements structural comparators, specifically the * LPM_COMPARE device type. */ class vvm_compare : public vvm_nexus::recvr_t { public: explicit vvm_compare(unsigned w); ~vvm_compare(); void init_DataA(unsigned idx, vpip_bit_t val); void init_DataB(unsigned idx, vpip_bit_t val); unsigned key_DataA(unsigned idx) const; unsigned key_DataB(unsigned idx) const; vvm_nexus::drive_t* config_ALB_out(); vvm_nexus::drive_t* config_ALEB_out(); vvm_nexus::drive_t* config_AGB_out(); vvm_nexus::drive_t* config_AGEB_out(); private: void take_value(unsigned key, vpip_bit_t val); unsigned width_; vpip_bit_t*ibits_; vpip_bit_t gt_; vpip_bit_t lt_; vvm_nexus::drive_t out_lt_; vvm_nexus::drive_t out_le_; vvm_nexus::drive_t out_gt_; vvm_nexus::drive_t out_ge_; void compute_(); private: // not implemented vvm_compare(const vvm_compare&); vvm_compare& operator= (const vvm_compare&); }; /* * This class simulates the LPM flip-flop device. The vvm_ff class * supports arbitrary width devices. For each output Q, there is a * unique input D. The CLK input is common for all the bit lanes. */ class vvm_ff : public vvm_nexus::recvr_t { public: explicit vvm_ff(unsigned wid); ~vvm_ff(); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_Data(unsigned idx) const; unsigned key_Clock() const; void init_Data(unsigned idx, vpip_bit_t val); void init_Clock(unsigned, vpip_bit_t val); private: void take_value(unsigned key, vpip_bit_t val); unsigned width_; vpip_bit_t*bits_; vpip_bit_t clk_; vvm_nexus::drive_t* out_; void latch_(); private: // not implemeneted vvm_ff(const vvm_ff&); vvm_ff& operator= (const vvm_ff&); }; /* * This class supports the handling of the procedural force * assignment. It is a device on the netlist that receives a bit value * and forces it onto the target vvm_nexus. That target is enabled by * the execution of the force statement in behavioral code. */ class vvm_force : public vvm_nexus::recvr_t { public: explicit vvm_force(unsigned w); ~vvm_force(); void init_I(unsigned key, vpip_bit_t val); // These methods turn on a force or continuous assign. They // cause the vvm_force object to attach itself to the tgt // object and deliver new values there. void force(unsigned key, vvm_nexus*tgt); void assign(unsigned key, vvm_nexus*tgt); // These methods are called by the attached nexus to detach // the vvm_force object. void release(unsigned key); void deassign(unsigned key); private: void take_value(unsigned key, vpip_bit_t val); bool force_flag_; unsigned width_; vpip_bit_t*bits_; vvm_nexus**target_; private: // not implemented vvm_force(const vvm_force&); vvm_force& operator= (const vvm_force&); }; /* * This class behaves like a combinational divider. There isn't really * such a practical device, but this is useful for simulating code * that includes a / operator in structural contexts. */ class vvm_idiv : public vvm_nexus::recvr_t { public: explicit vvm_idiv(unsigned rwid, unsigned awid, unsigned bwid); ~vvm_idiv(); void init_DataA(unsigned idx, vpip_bit_t val); void init_DataB(unsigned idx, vpip_bit_t val); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_DataA(unsigned idx) const; unsigned key_DataB(unsigned idx) const; private: void take_value(unsigned key, vpip_bit_t val); unsigned rwid_; unsigned awid_; unsigned bwid_; vpip_bit_t*bits_; vvm_nexus::drive_t*out_; }; /* * This class behaves like a combinational modulo operator. There isn't really * such a practical device, but this is useful for simulating code * that includes a / operator in structural contexts. */ class vvm_imod : public vvm_nexus::recvr_t { public: explicit vvm_imod(unsigned rwid, unsigned awid, unsigned bwid); ~vvm_imod(); void init_DataA(unsigned idx, vpip_bit_t val); void init_DataB(unsigned idx, vpip_bit_t val); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_DataA(unsigned idx) const; unsigned key_DataB(unsigned idx) const; private: void take_value(unsigned key, vpip_bit_t val); unsigned rwid_; unsigned awid_; unsigned bwid_; vpip_bit_t*bits_; vvm_nexus::drive_t*out_; }; /* * This class behaves like a combinational multiplier. The device * behaves like the LPM_MULT device. */ class vvm_mult : public vvm_nexus::recvr_t { public: explicit vvm_mult(unsigned rwid, unsigned awid, unsigned bwid, unsigned swid); ~vvm_mult(); void init_DataA(unsigned idx, vpip_bit_t val); void init_DataB(unsigned idx, vpip_bit_t val); void init_Sum(unsigned idx, vpip_bit_t val); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_DataA(unsigned idx) const; unsigned key_DataB(unsigned idx) const; unsigned key_Sum(unsigned idx) const; private: void take_value(unsigned key, vpip_bit_t val); unsigned rwid_; unsigned awid_; unsigned bwid_; unsigned swid_; vpip_bit_t*bits_; vvm_nexus::drive_t*out_; }; /* * This class supports mux devices. The width is the width of the data * (or bus) path, SIZE is the number of alternative inputs and SELWID * is the size (in bits) of the selector input. The device passes to * the output the bits of the input selected by the selector. */ class vvm_mux : public vvm_nexus::recvr_t { public: explicit vvm_mux(unsigned width, unsigned size, unsigned selwid); ~vvm_mux(); void init_Sel(unsigned idx, vpip_bit_t val); void init_Data(unsigned idx, vpip_bit_t val); vvm_nexus::drive_t* config_rout(unsigned idx); unsigned key_Sel(unsigned idx) const; unsigned key_Data(unsigned wi, unsigned si) const; private: void take_value(unsigned key, vpip_bit_t val); unsigned width_, size_, selwid_; vpip_bit_t*bits_; vvm_nexus::drive_t*out_; void evaluate_(); private: // not implemented vvm_mux(const vvm_mux&); vvm_mux& operator= (vvm_mux&); }; class vvm_or : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_or(unsigned wid, unsigned long d); ~vvm_or(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; class vvm_nor : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_nor(unsigned wid, unsigned long d); ~vvm_nor(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; class vvm_nor2 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_nor2(unsigned long d); ~vvm_nor2(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t input_[2]; }; /* * This object implements a LPM_RAM_DQ device, except for the actual * contents of the memory, which are stored in a vvm_memory_t * object. Note that there may be many vvm_ram_dq items referencing * the same memory. * * XXXX Only asynchronous reads are supported. * XXXX Only *synchronous* writes with WE are supported. */ template class vvm_ram_dq : protected vvm_ram_callback, public vvm_nexus::recvr_t { public: vvm_ram_dq(vvm_memory_t*mem) : mem_(mem) { mem->set_callback(this); for (unsigned idx = 0 ; idx < AWIDTH+WIDTH+2 ; idx += 1) ibits_[idx] = StX; } void init_Address(unsigned idx, vpip_bit_t val) { ibits_[idx] = val; } void init_Data(unsigned idx, vpip_bit_t val) { ibits_[AWIDTH+idx] = val; } void init_WE(unsigned, vpip_bit_t val) { ibits_[AWIDTH+WIDTH] = val; } void init_InClock(unsigned, vpip_bit_t val) { ibits_[AWIDTH+WIDTH+1] = val; } unsigned key_Address(unsigned idx) const { return idx; } unsigned key_Data(unsigned idx) const { return AWIDTH+idx; } unsigned key_WE() const { return AWIDTH+WIDTH + 0; } unsigned key_InClock() const { return AWIDTH+WIDTH + 1; } vvm_nexus::drive_t* config_rout(unsigned idx) { return out_+idx; } void take_value(unsigned key, vpip_bit_t val) { if (ibits_[key] == val) return; if (key == key_InClock()) { vpip_bit_t tmp = ibits_[key]; ibits_[key] = val; if (B_IS1(ibits_[key_WE()])) return; if (posedge(tmp, val)) mem_->set_word(addr_val_, ibits_+AWIDTH); return; } else { ibits_[key] = val; if (key < AWIDTH) { compute_(); send_out_(); } } } void handle_write(unsigned idx) { if (idx == addr_val_) send_out_(); } private: vvm_memory_t*mem_; vpip_bit_t ibits_[AWIDTH+WIDTH+2]; vvm_nexus::drive_t out_[WIDTH]; unsigned long addr_val_; void compute_() { unsigned bit; unsigned mask; addr_val_ = 0; for (bit = 0, mask = 1 ; bit < AWIDTH ; bit += 1, mask <<= 1) if (B_IS1(ibits_[bit])) addr_val_ |= mask; } void send_out_() { vpip_bit_t ov_bits[WIDTH]; vvm_bitset_t ov(ov_bits, WIDTH); mem_->get_word(addr_val_, ov); for (unsigned bit = 0 ; bit < WIDTH ; bit += 1) { vvm_out_event*ev = new vvm_out_event(ov[bit], out_+bit); ev->schedule(); } } }; class vvm_buf : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_buf(unsigned long d); ~vvm_buf(); void init_I(unsigned, vpip_bit_t); void start() { } private: void take_value(unsigned, vpip_bit_t val); }; class vvm_bufif0 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_bufif0(unsigned long d); ~vvm_bufif0(); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_bufif1 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_bufif1(unsigned long d); ~vvm_bufif1(); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_notif0 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_notif0(unsigned long d); ~vvm_notif0(); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_notif1 : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_notif1(unsigned long d); ~vvm_notif1(); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_nand : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_nand(unsigned wid, unsigned long d); ~vvm_nand(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; /* * Simple inverter buffer. */ class vvm_not : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_not(unsigned long d); ~vvm_not(); void init_I(unsigned, vpip_bit_t); void start(); private: void take_value(unsigned key, vpip_bit_t val); }; class vvm_nmos : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_nmos(unsigned long d); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_rnmos : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_rnmos(unsigned long d); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_pmos : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_pmos(unsigned long d); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_rpmos : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_rpmos(unsigned long d); void init_I(unsigned, vpip_bit_t); void start() { } private: vpip_bit_t input_[2]; void take_value(unsigned key, vpip_bit_t val); }; class vvm_xnor : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_xnor(unsigned wid, unsigned long d); ~vvm_xnor(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; class vvm_xor : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_xor(unsigned wid, unsigned long d); ~vvm_xor(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); private: unsigned width_; vpip_bit_t*input_; }; /* * This gate has only 3 pins, the output at pin 0 and two inputs. The * output is 1 or 0 if the two inputs are exactly equal or not. */ class vvm_eeq : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_eeq(unsigned long d); ~vvm_eeq(); void init_I(unsigned idx, vpip_bit_t val); void start(); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t compute_() const; vpip_bit_t input_[2]; }; /* * This class allows programmers to define combinational primitives at * truth tables. The device has a single bit output, and any fixed * width. * * The truth table is specified as a string of characters organized as * a table. Every width+1 characters represents one row, including the * set of inputs and the output that they generated. There can be any * number of rows in the table, which is terminated by a nul byte. The * table is passed to the constructor as a constant string. * * This is a simple example of a truth table for an inverter. The * width is 1, so there are two characters in each row. The last * character in each row is the output if all the other characters in * the row match the input. As you can see, this table inverts its * input and outputs 'x' if the input is unknown. * * const char*invert_table = * "01" * "10" * "xx"; * * The valid input characters are '0', '1' and 'x'. The valid output * characters are '0', '1', 'x' and 'z'. (The last is not supported by * Verilog primitives, so ivl will never generate it.) */ class vvm_udp_comb : public vvm_1bit_out, public vvm_nexus::recvr_t { public: explicit vvm_udp_comb(unsigned w, const char*t); ~vvm_udp_comb(); void init_I(unsigned idx, vpip_bit_t val); void start(); protected: void take_value(unsigned key, vpip_bit_t val); char*ibits_; char obit_; unsigned width_; const char*table_; }; class vvm_udp_sequ1 : public vvm_udp_comb { public: explicit vvm_udp_sequ1(unsigned w, const char*t) : vvm_udp_comb(w+1, t) {}; void init_I(unsigned idx, vpip_bit_t val); private: void take_value(unsigned key, vpip_bit_t val); }; /* * The bufz is a trivial device that simply passes its input to its * output. Unlike a buf devince, this does not change Vz values to Vx, * it instead passes the Vz unaltered. * * This device is useful for isolating nets. */ class vvm_bufz : public vvm_nexus::recvr_t, public vvm_1bit_out { public: explicit vvm_bufz(unsigned delay =0); ~vvm_bufz(); void init_I(unsigned idx, vpip_bit_t val); private: void take_value(unsigned, vpip_bit_t val); }; /* * The pullup is a trivial device that drives a logic 1 onto its output. */ class vvm_pullup : public vvm_nexus::recvr_t, public vvm_1bit_out { public: explicit vvm_pullup(unsigned delay =0); ~vvm_pullup(); void start(); private: void take_value(unsigned, vpip_bit_t val); }; /* * The pulldown is a trivial device that drives a logic 0 onto its output. */ class vvm_pulldown : public vvm_nexus::recvr_t, public vvm_1bit_out { public: explicit vvm_pulldown(unsigned delay =0); ~vvm_pulldown(); void start(); private: void take_value(unsigned, vpip_bit_t val); }; /* * Threads use the vvm_sync to wait for something to happen. This * class cooperates with the various event source classes that receive * events and trigger the associated vvm_sync object. * * CHAINING * A thread can only wait on one vvm_sync object. To get the effect of * waiting on many vvm_sync objects, vvm_sync objects can be * chained. That is, a vvm_sync object can be configured to receive * triggers from other vvm_sync objects. That is the job of the * chain_sync() method. */ class vvm_sync { public: vvm_sync(); void wait(vvm_thread*); void wakeup(); // Receive triggers from the specified source. void chain_sync(vvm_sync*src); private: vvm_thread*hold_; vvm_sync**tgt_; unsigned ntgt_; private: // not implemented vvm_sync(const vvm_sync&); vvm_sync& operator= (const vvm_sync&); }; class vvm_anyedge : public vvm_nexus::recvr_t { public: explicit vvm_anyedge(vvm_sync*tgt, unsigned n); ~vvm_anyedge(); void init_P(unsigned idx, vpip_bit_t val); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t*val_; unsigned nval_; vvm_sync*sync_; private: // not implemented vvm_anyedge(const vvm_anyedge&); vvm_anyedge& operator= (const vvm_anyedge&); }; class vvm_negedge : public vvm_nexus::recvr_t { public: explicit vvm_negedge(vvm_sync*tgt); ~vvm_negedge(); void init_P(int idx, vpip_bit_t val); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t val_; vvm_sync*sync_; private: // not implemented vvm_negedge(const vvm_negedge&); vvm_negedge& operator= (const vvm_negedge&); }; class vvm_posedge : public vvm_nexus::recvr_t { public: explicit vvm_posedge(vvm_sync*tgt); ~vvm_posedge(); void init_P(int idx, vpip_bit_t val); private: void take_value(unsigned key, vpip_bit_t val); vpip_bit_t val_; vvm_sync*sync_; private: // not implemented vvm_posedge(const vvm_posedge&); vvm_posedge& operator= (const vvm_posedge&); }; /* * $Log: vvm_gates.h,v $ * Revision 1.73 2002/08/12 01:35:07 steve * conditional ident string using autoconfig. * * Revision 1.72 2001/10/14 03:50:53 steve * vvm support for pullup/down gates (PR#288) * * Revision 1.71 2001/04/22 23:09:46 steve * More UDP consolidation from Stephan Boettcher. * * Revision 1.70 2001/01/16 03:57:46 steve * Get rid of gate templates. * * Revision 1.69 2000/12/15 20:05:16 steve * Fix memory access in vvm. (PR#70) * * Revision 1.68 2000/12/10 06:42:00 steve * Support delays on continuous assignment from idents. (PR#40) * * Revision 1.67 2000/11/11 01:52:09 steve * change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1 * change set to correct behavior of bufif0 and bufif1 * (Tim Leight) * * Also includes fix for PR#27 * * Revision 1.66 2000/11/04 06:36:24 steve * Apply sequential UDP rework from Stephan Boettcher (PR#39) * * Revision 1.65 2000/09/17 21:26:16 steve * Add support for modulus (Eric Aardoom) * * Revision 1.64 2000/05/11 23:37:28 steve * Add support for procedural continuous assignment. * * Revision 1.63 2000/05/11 01:37:33 steve * Calculate the X output value from drive0 and drive1 * * Revision 1.62 2000/05/09 21:16:35 steve * Give strengths to logic and bufz devices. * * Revision 1.61 2000/05/08 05:27:32 steve * Restore vvm_bufz to working condition. * * Revision 1.60 2000/04/23 21:15:07 steve * Emit code for the bufif devices. * * Revision 1.59 2000/04/23 03:45:25 steve * Add support for the procedural release statement. * * Revision 1.58 2000/04/22 04:20:20 steve * Add support for force assignment. * * Revision 1.57 2000/04/15 02:25:32 steve * Support chained events. * * Revision 1.56 2000/04/10 05:26:07 steve * All events now use the NetEvent class. * * Revision 1.55 2000/04/08 05:49:59 steve * Fix memory object compile problems. * * Revision 1.54 2000/04/01 21:40:23 steve * Add support for integer division. * * Revision 1.53 2000/03/29 04:37:11 steve * New and improved combinational primitives. * * Revision 1.52 2000/03/26 16:28:31 steve * vvm_bitset_t is no longer a template. * * Revision 1.51 2000/03/25 02:43:57 steve * Remove all remain vvm_bitset_t return values, * and disallow vvm_bitset_t copying. * * Revision 1.50 2000/03/24 03:47:01 steve * Update vvm_ram_dq to nexus style. * * Revision 1.49 2000/03/22 04:26:41 steve * Replace the vpip_bit_t with a typedef and * define values for all the different bit * values, including strengths. */ #endif