1998-11-10 00:44:10 +01:00
|
|
|
#ifndef __vvm_gates_H
|
|
|
|
|
#define __vvm_gates_H
|
|
|
|
|
/*
|
2000-02-23 03:56:53 +01:00
|
|
|
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
1998-11-10 00:44:10 +01:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2002-08-12 03:34:58 +02:00
|
|
|
#ifdef HAVE_CVS_IDENT
|
|
|
|
|
#ident "$Id: vvm_gates.h,v 1.73 2002/08/12 01:35:07 steve Exp $"
|
1998-11-10 00:44:10 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
# include "vvm.h"
|
2000-03-16 20:03:03 +01:00
|
|
|
# include "vvm_signal.h"
|
1998-11-10 00:44:10 +01:00
|
|
|
# include <assert.h>
|
|
|
|
|
|
1999-11-24 05:38:49 +01:00
|
|
|
extern vpip_bit_t compute_nand(const vpip_bit_t*inp, unsigned count);
|
1999-11-22 01:30:52 +01:00
|
|
|
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);
|
1999-11-24 05:38:49 +01:00
|
|
|
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);
|
1999-11-22 01:30:52 +01:00
|
|
|
|
2000-11-11 02:52:09 +01:00
|
|
|
extern vpip_bit_t reduce_strength(vpip_bit_t);
|
|
|
|
|
|
1999-12-02 05:54:11 +01:00
|
|
|
extern void compute_mux(vpip_bit_t*out, unsigned wid,
|
|
|
|
|
const vpip_bit_t*sel, unsigned swid,
|
|
|
|
|
const vpip_bit_t*dat, unsigned size);
|
|
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
|
|
|
|
|
|
1998-11-10 00:44:10 +01:00
|
|
|
/*
|
|
|
|
|
* 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:
|
2000-03-16 20:03:03 +01:00
|
|
|
typedef void (*action_t)(vpip_bit_t); // XXXX Remove me!
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
vvm_out_event(vpip_bit_t v, vvm_nexus::drive_t*o);
|
1999-11-22 01:30:52 +01:00
|
|
|
~vvm_out_event();
|
|
|
|
|
|
|
|
|
|
void event_function();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-16 20:03:03 +01:00
|
|
|
vvm_nexus::drive_t*output_;
|
1999-10-28 02:47:24 +02:00
|
|
|
const vpip_bit_t val_;
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_1bit_out : public vvm_nexus::drive_t {
|
1999-11-22 01:30:52 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-16 20:03:03 +01:00
|
|
|
vvm_1bit_out(unsigned delay);
|
1999-11-22 01:30:52 +01:00
|
|
|
~vvm_1bit_out();
|
1999-12-12 20:47:54 +01:00
|
|
|
void output(vpip_bit_t);
|
1999-11-22 01:30:52 +01:00
|
|
|
|
2000-05-09 23:16:35 +02:00
|
|
|
void drive0(vpip_bit_t);
|
|
|
|
|
void drive1(vpip_bit_t);
|
|
|
|
|
void driveZ(vpip_bit_t);
|
|
|
|
|
|
1999-11-22 01:30:52 +01:00
|
|
|
private:
|
|
|
|
|
unsigned delay_;
|
2000-05-09 23:16:35 +02:00
|
|
|
|
|
|
|
|
vpip_bit_t drive0_;
|
|
|
|
|
vpip_bit_t drive1_;
|
|
|
|
|
vpip_bit_t driveX_;
|
|
|
|
|
vpip_bit_t driveZ_;
|
1999-11-22 01:30:52 +01:00
|
|
|
};
|
|
|
|
|
|
1999-10-31 05:11:27 +01:00
|
|
|
/*
|
2000-03-17 18:25:53 +01:00
|
|
|
* This class implements the LPM_ADD_SUB device type. The width of
|
|
|
|
|
* the device is a constructor parameter. The device handles addition and
|
1999-10-31 21:08:24 +01:00
|
|
|
* subtraction, selectable by the Add_Sub input. When configured as a
|
|
|
|
|
* subtractor, the device works by adding the 2s complement of
|
|
|
|
|
* DataB.
|
1999-10-31 05:11:27 +01:00
|
|
|
*/
|
2000-03-17 18:25:53 +01:00
|
|
|
class vvm_add_sub : public vvm_nexus::recvr_t {
|
1999-10-31 05:11:27 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 18:25:53 +01:00
|
|
|
explicit vvm_add_sub(unsigned width);
|
|
|
|
|
~vvm_add_sub();
|
1999-10-31 05:11:27 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
vvm_nexus::drive_t* config_rout(unsigned idx);
|
|
|
|
|
vvm_nexus::drive_t* config_cout();
|
1999-10-31 05:11:27 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
unsigned key_DataA(unsigned idx) const;
|
|
|
|
|
unsigned key_DataB(unsigned idx) const;
|
1999-10-31 21:08:24 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
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);
|
1999-12-16 03:42:14 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
void start();
|
1999-10-31 05:11:27 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2000-03-17 18:25:53 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
2000-03-16 20:03:03 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*ibits_;
|
1999-12-16 03:42:14 +01:00
|
|
|
vpip_bit_t c_;
|
1999-10-31 05:11:27 +01:00
|
|
|
|
1999-10-31 21:08:24 +01:00
|
|
|
// this is the inverse of the Add_Sub port. It is 0 for add,
|
|
|
|
|
// and 1 for subtract.
|
|
|
|
|
vpip_bit_t ndir_;
|
|
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
vvm_nexus::drive_t*ro_;
|
2000-03-16 20:03:03 +01:00
|
|
|
vvm_nexus::drive_t co_;
|
1999-10-31 05:11:27 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
void compute_();
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
vvm_add_sub(const vvm_add_sub&);
|
|
|
|
|
vvm_add_sub& operator= (const vvm_add_sub&);
|
1999-10-31 05:11:27 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-17 20:23:59 +01:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_and : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_and(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_and();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-01-01 02:44:56 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1998-12-20 03:05:41 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
2000-03-16 20:03:03 +01:00
|
|
|
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-17 20:23:59 +01:00
|
|
|
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];
|
|
|
|
|
};
|
|
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
/*
|
|
|
|
|
* This class implements LPM_CLSHIFT devices with specified data width
|
|
|
|
|
* and selector input width. The direction bit is a single bit input.
|
|
|
|
|
*/
|
2000-03-16 22:47:27 +01:00
|
|
|
class vvm_clshift : public vvm_nexus::recvr_t {
|
1999-11-14 21:24:28 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 03:22:03 +01:00
|
|
|
vvm_clshift(unsigned wid, unsigned dwid);
|
|
|
|
|
~vvm_clshift();
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
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);
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
vvm_nexus::drive_t* config_rout(unsigned idx);
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
unsigned key_Data(unsigned idx) const;
|
|
|
|
|
unsigned key_Distance(unsigned idx) const;
|
|
|
|
|
unsigned key_Direction(unsigned) const;
|
2000-03-16 22:47:27 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-17 03:22:03 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-11-15 01:42:31 +01:00
|
|
|
|
1999-11-14 21:24:28 +01:00
|
|
|
private:
|
2000-03-17 03:22:03 +01:00
|
|
|
unsigned width_, wdist_;
|
1999-11-14 21:24:28 +01:00
|
|
|
vpip_bit_t dir_;
|
1999-11-15 01:42:31 +01:00
|
|
|
int dist_val_;
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
vpip_bit_t*ibits_;
|
|
|
|
|
vvm_nexus::drive_t*out_;
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
void calculate_dist_();
|
|
|
|
|
void compute_();
|
1999-11-14 21:24:28 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-17 03:22:03 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
/*
|
|
|
|
|
* This class implements structural comparators, specifically the
|
|
|
|
|
* LPM_COMPARE device type.
|
|
|
|
|
*/
|
|
|
|
|
class vvm_compare : public vvm_nexus::recvr_t {
|
1999-11-15 00:43:45 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 18:25:53 +01:00
|
|
|
explicit vvm_compare(unsigned w);
|
|
|
|
|
~vvm_compare();
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
void init_DataA(unsigned idx, vpip_bit_t val);
|
|
|
|
|
void init_DataB(unsigned idx, vpip_bit_t val);
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
unsigned key_DataA(unsigned idx) const;
|
|
|
|
|
unsigned key_DataB(unsigned idx) const;
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
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();
|
1999-11-15 00:43:45 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-17 18:25:53 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
|
|
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*ibits_;
|
1999-11-15 00:43:45 +01:00
|
|
|
|
|
|
|
|
vpip_bit_t gt_;
|
|
|
|
|
vpip_bit_t lt_;
|
|
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
vvm_nexus::drive_t out_lt_;
|
|
|
|
|
vvm_nexus::drive_t out_le_;
|
|
|
|
|
vvm_nexus::drive_t out_gt_;
|
|
|
|
|
vvm_nexus::drive_t out_ge_;
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
void compute_();
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-03-17 18:25:53 +01:00
|
|
|
private: // not implemented
|
|
|
|
|
vvm_compare(const vvm_compare&);
|
|
|
|
|
vvm_compare& operator= (const vvm_compare&);
|
1999-11-15 00:43:45 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-11-01 03:07:40 +01:00
|
|
|
/*
|
2000-03-19 00:22:37 +01:00
|
|
|
* 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.
|
1999-11-01 03:07:40 +01:00
|
|
|
*/
|
2000-03-19 00:22:37 +01:00
|
|
|
class vvm_ff : public vvm_nexus::recvr_t {
|
1999-11-01 03:07:40 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-19 00:22:37 +01:00
|
|
|
explicit vvm_ff(unsigned wid);
|
|
|
|
|
~vvm_ff();
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-03-19 00:22:37 +01:00
|
|
|
vvm_nexus::drive_t* config_rout(unsigned idx);
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-03-19 00:22:37 +01:00
|
|
|
unsigned key_Data(unsigned idx) const;
|
|
|
|
|
unsigned key_Clock() const;
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-03-19 00:22:37 +01:00
|
|
|
void init_Data(unsigned idx, vpip_bit_t val);
|
|
|
|
|
void init_Clock(unsigned, vpip_bit_t val);
|
1999-11-01 03:07:40 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-19 00:22:37 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*bits_;
|
1999-11-01 03:07:40 +01:00
|
|
|
vpip_bit_t clk_;
|
|
|
|
|
|
2000-03-19 00:22:37 +01:00
|
|
|
vvm_nexus::drive_t* out_;
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-03-19 00:22:37 +01:00
|
|
|
void latch_();
|
|
|
|
|
|
|
|
|
|
private: // not implemeneted
|
|
|
|
|
vvm_ff(const vvm_ff&);
|
|
|
|
|
vvm_ff& operator= (const vvm_ff&);
|
1999-11-01 03:07:40 +01:00
|
|
|
};
|
|
|
|
|
|
2000-04-22 06:20:19 +02:00
|
|
|
/*
|
|
|
|
|
* 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);
|
|
|
|
|
|
2000-05-12 01:37:26 +02:00
|
|
|
// 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.
|
2000-04-22 06:20:19 +02:00
|
|
|
void force(unsigned key, vvm_nexus*tgt);
|
2000-05-12 01:37:26 +02:00
|
|
|
void assign(unsigned key, vvm_nexus*tgt);
|
|
|
|
|
|
|
|
|
|
// These methods are called by the attached nexus to detach
|
|
|
|
|
// the vvm_force object.
|
2000-04-23 05:45:24 +02:00
|
|
|
void release(unsigned key);
|
2000-05-12 01:37:26 +02:00
|
|
|
void deassign(unsigned key);
|
2000-04-22 06:20:19 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
|
2000-05-12 01:37:26 +02:00
|
|
|
bool force_flag_;
|
2000-04-22 06:20:19 +02:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*bits_;
|
|
|
|
|
vvm_nexus**target_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
vvm_force(const vvm_force&);
|
|
|
|
|
vvm_force& operator= (const vvm_force&);
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-01 23:40:22 +02:00
|
|
|
/*
|
|
|
|
|
* 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_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-09-17 23:26:15 +02:00
|
|
|
/*
|
|
|
|
|
* 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_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-01-13 04:35:35 +01:00
|
|
|
/*
|
|
|
|
|
* This class behaves like a combinational multiplier. The device
|
|
|
|
|
* behaves like the LPM_MULT device.
|
|
|
|
|
*/
|
2000-03-17 04:05:13 +01:00
|
|
|
class vvm_mult : public vvm_nexus::recvr_t {
|
2000-01-13 04:35:35 +01:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2000-03-17 04:05:13 +01:00
|
|
|
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;
|
2000-01-13 04:35:35 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-17 04:05:13 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
|
2000-01-13 04:35:35 +01:00
|
|
|
unsigned rwid_;
|
|
|
|
|
unsigned awid_;
|
|
|
|
|
unsigned bwid_;
|
|
|
|
|
unsigned swid_;
|
|
|
|
|
vpip_bit_t*bits_;
|
2000-03-17 04:05:13 +01:00
|
|
|
vvm_nexus::drive_t*out_;
|
2000-01-13 04:35:35 +01:00
|
|
|
};
|
|
|
|
|
|
1999-11-13 04:46:52 +01:00
|
|
|
/*
|
|
|
|
|
* 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
|
2000-03-18 02:26:59 +01:00
|
|
|
* is the size (in bits) of the selector input. The device passes to
|
|
|
|
|
* the output the bits of the input selected by the selector.
|
1999-11-13 04:46:52 +01:00
|
|
|
*/
|
2000-03-17 00:13:49 +01:00
|
|
|
class vvm_mux : public vvm_nexus::recvr_t {
|
1999-11-13 04:46:52 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-18 02:26:59 +01:00
|
|
|
explicit vvm_mux(unsigned width, unsigned size, unsigned selwid);
|
|
|
|
|
~vvm_mux();
|
1999-11-13 04:46:52 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
void init_Sel(unsigned idx, vpip_bit_t val);
|
|
|
|
|
void init_Data(unsigned idx, vpip_bit_t val);
|
1999-11-13 04:46:52 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
vvm_nexus::drive_t* config_rout(unsigned idx);
|
2000-03-17 00:13:49 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
unsigned key_Sel(unsigned idx) const;
|
|
|
|
|
unsigned key_Data(unsigned wi, unsigned si) const;
|
2000-03-17 00:13:49 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-18 02:26:59 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-11-13 04:46:52 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
unsigned width_, size_, selwid_;
|
|
|
|
|
vpip_bit_t*bits_;
|
1999-11-13 04:46:52 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
vvm_nexus::drive_t*out_;
|
1999-12-02 05:54:11 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
void evaluate_();
|
1999-11-13 04:46:52 +01:00
|
|
|
|
2000-03-18 02:26:59 +01:00
|
|
|
private: // not implemented
|
|
|
|
|
vvm_mux(const vvm_mux&);
|
|
|
|
|
vvm_mux& operator= (vvm_mux&);
|
1999-11-13 04:46:52 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_or : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1999-06-09 02:58:06 +02:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_or(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_or();
|
1999-06-09 02:58:06 +02:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-06-09 02:58:06 +02:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1999-06-09 02:58:06 +02:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-06-09 02:58:06 +02:00
|
|
|
|
|
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1999-06-09 02:58:06 +02:00
|
|
|
};
|
|
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_nor : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1999-10-09 21:24:36 +02:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_nor(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_nor();
|
1999-10-09 21:24:36 +02:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-10-09 21:24:36 +02:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1999-10-09 21:24:36 +02:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-10-09 21:24:36 +02:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1999-10-09 21:24:36 +02:00
|
|
|
};
|
|
|
|
|
|
2000-03-17 20:23:59 +01:00
|
|
|
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];
|
|
|
|
|
};
|
|
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
1999-11-21 01:13:08 +01:00
|
|
|
template <unsigned WIDTH, unsigned AWIDTH, unsigned SIZE>
|
2000-03-24 04:47:01 +01:00
|
|
|
class vvm_ram_dq : protected vvm_ram_callback, public vvm_nexus::recvr_t {
|
1999-11-21 01:13:08 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-12-15 21:05:16 +01:00
|
|
|
vvm_ram_dq(vvm_memory_t*mem)
|
1999-11-21 01:13:08 +01:00
|
|
|
: mem_(mem)
|
|
|
|
|
{ mem->set_callback(this);
|
2000-03-24 04:47:01 +01:00
|
|
|
for (unsigned idx = 0 ; idx < AWIDTH+WIDTH+2 ; idx += 1)
|
|
|
|
|
ibits_[idx] = StX;
|
1999-11-21 01:13:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void init_Address(unsigned idx, vpip_bit_t val)
|
2000-03-24 04:47:01 +01:00
|
|
|
{ ibits_[idx] = val; }
|
1999-11-21 01:13:08 +01:00
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
void init_Data(unsigned idx, vpip_bit_t val)
|
2000-03-24 04:47:01 +01:00
|
|
|
{ ibits_[AWIDTH+idx] = val; }
|
1999-12-05 03:24:08 +01:00
|
|
|
|
|
|
|
|
void init_WE(unsigned, vpip_bit_t val)
|
2000-03-24 04:47:01 +01:00
|
|
|
{ ibits_[AWIDTH+WIDTH] = val; }
|
1999-12-05 03:24:08 +01:00
|
|
|
|
|
|
|
|
void init_InClock(unsigned, vpip_bit_t val)
|
2000-03-24 04:47:01 +01:00
|
|
|
{ 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_();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-12-05 03:24:08 +01:00
|
|
|
|
1999-11-21 01:13:08 +01:00
|
|
|
|
2000-03-24 04:47:01 +01:00
|
|
|
void handle_write(unsigned idx) { if (idx == addr_val_) send_out_(); }
|
1999-11-21 01:13:08 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-12-15 21:05:16 +01:00
|
|
|
vvm_memory_t*mem_;
|
1999-12-05 03:24:08 +01:00
|
|
|
|
2000-03-24 04:47:01 +01:00
|
|
|
vpip_bit_t ibits_[AWIDTH+WIDTH+2];
|
|
|
|
|
vvm_nexus::drive_t out_[WIDTH];
|
1999-11-21 01:13:08 +01:00
|
|
|
|
|
|
|
|
unsigned long addr_val_;
|
|
|
|
|
|
|
|
|
|
void compute_()
|
|
|
|
|
{ unsigned bit;
|
|
|
|
|
unsigned mask;
|
|
|
|
|
addr_val_ = 0;
|
|
|
|
|
for (bit = 0, mask = 1 ; bit < AWIDTH ; bit += 1, mask <<= 1)
|
2000-03-24 04:47:01 +01:00
|
|
|
if (B_IS1(ibits_[bit])) addr_val_ |= mask;
|
1999-11-21 01:13:08 +01:00
|
|
|
}
|
|
|
|
|
|
1999-12-12 20:47:54 +01:00
|
|
|
void send_out_()
|
2000-04-08 07:49:59 +02:00
|
|
|
{ vpip_bit_t ov_bits[WIDTH];
|
|
|
|
|
vvm_bitset_t ov(ov_bits, WIDTH);
|
2000-03-25 03:43:56 +01:00
|
|
|
mem_->get_word(addr_val_, ov);
|
2000-03-24 04:47:01 +01:00
|
|
|
for (unsigned bit = 0 ; bit < WIDTH ; bit += 1) {
|
|
|
|
|
vvm_out_event*ev = new vvm_out_event(ov[bit], out_+bit);
|
|
|
|
|
ev->schedule();
|
|
|
|
|
}
|
1999-11-21 01:13:08 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
class vvm_buf : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1999-11-21 02:16:51 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 04:36:07 +01:00
|
|
|
explicit vvm_buf(unsigned long d);
|
|
|
|
|
~vvm_buf();
|
1999-11-21 02:16:51 +01:00
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
void init_I(unsigned, vpip_bit_t);
|
1999-12-12 20:47:54 +01:00
|
|
|
void start() { }
|
1999-11-21 02:16:51 +01:00
|
|
|
private:
|
2000-03-17 04:36:07 +01:00
|
|
|
void take_value(unsigned, vpip_bit_t val);
|
1999-11-21 02:16:51 +01:00
|
|
|
};
|
|
|
|
|
|
2000-04-23 23:15:07 +02:00
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
class vvm_bufif1 : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1999-02-15 06:52:50 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 04:36:07 +01:00
|
|
|
explicit vvm_bufif1(unsigned long d);
|
|
|
|
|
~vvm_bufif1();
|
1999-02-15 06:52:50 +01:00
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
void init_I(unsigned, vpip_bit_t);
|
|
|
|
|
void start() { }
|
1999-02-15 06:52:50 +01:00
|
|
|
|
|
|
|
|
private:
|
1999-10-28 02:47:24 +02:00
|
|
|
vpip_bit_t input_[2];
|
2000-03-17 04:36:07 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-02-15 06:52:50 +01:00
|
|
|
};
|
|
|
|
|
|
2000-11-11 02:52:09 +01:00
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_nand : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_nand(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_nand();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-11-14 19:22:12 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1998-12-20 03:05:41 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
2000-03-16 20:03:03 +01:00
|
|
|
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Simple inverter buffer.
|
|
|
|
|
*/
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_not : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-03-17 04:36:07 +01:00
|
|
|
explicit vvm_not(unsigned long d);
|
|
|
|
|
~vvm_not();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
void init_I(unsigned, vpip_bit_t);
|
|
|
|
|
void start();
|
1998-11-10 00:44:10 +01:00
|
|
|
private:
|
2000-03-17 04:36:07 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
2000-11-11 02:52:09 +01:00
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
|
2000-03-17 04:36:07 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_xnor : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_xnor(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_xnor();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-01-31 19:15:55 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1998-12-20 03:05:41 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_xor : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
public:
|
2001-01-16 04:57:46 +01:00
|
|
|
explicit vvm_xor(unsigned wid, unsigned long d);
|
|
|
|
|
~vvm_xor();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-01-01 02:44:56 +01:00
|
|
|
|
2001-01-16 04:57:46 +01:00
|
|
|
void start();
|
1998-12-20 03:05:41 +01:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-01-01 02:44:56 +01:00
|
|
|
|
|
|
|
|
private:
|
2001-01-16 04:57:46 +01:00
|
|
|
unsigned width_;
|
|
|
|
|
vpip_bit_t*input_;
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
1999-10-10 03:59:54 +02:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2000-03-16 20:03:03 +01:00
|
|
|
class vvm_eeq : public vvm_1bit_out, public vvm_nexus::recvr_t {
|
1999-10-10 03:59:54 +02:00
|
|
|
|
|
|
|
|
public:
|
2000-03-16 20:03:03 +01:00
|
|
|
explicit vvm_eeq(unsigned long d);
|
|
|
|
|
~vvm_eeq();
|
1999-10-10 03:59:54 +02:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1999-10-10 03:59:54 +02:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
void start();
|
1999-10-10 03:59:54 +02:00
|
|
|
|
|
|
|
|
private:
|
2000-03-16 20:03:03 +01:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-10-10 03:59:54 +02:00
|
|
|
|
2000-03-16 20:03:03 +01:00
|
|
|
vpip_bit_t compute_() const;
|
1999-10-10 03:59:54 +02:00
|
|
|
|
1999-10-28 02:47:24 +02:00
|
|
|
vpip_bit_t input_[2];
|
1999-10-10 03:59:54 +02:00
|
|
|
};
|
|
|
|
|
|
2000-03-29 06:37:10 +02:00
|
|
|
/*
|
|
|
|
|
* 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();
|
|
|
|
|
|
2000-11-04 07:36:24 +01:00
|
|
|
protected:
|
2000-03-29 06:37:10 +02:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
2000-11-04 07:36:24 +01:00
|
|
|
char*ibits_;
|
|
|
|
|
char obit_;
|
2000-03-29 06:37:10 +02:00
|
|
|
|
|
|
|
|
unsigned width_;
|
|
|
|
|
const char*table_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-11-04 07:36:24 +01:00
|
|
|
class vvm_udp_sequ1 : public vvm_udp_comb
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit vvm_udp_sequ1(unsigned w, const char*t)
|
|
|
|
|
: vvm_udp_comb(w+1, t) {};
|
2001-04-23 01:09:45 +02:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
2000-11-04 07:36:24 +01:00
|
|
|
private:
|
|
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1998-12-18 00:54:58 +01:00
|
|
|
};
|
|
|
|
|
|
2000-03-18 03:26:02 +01:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2000-05-09 23:16:35 +02:00
|
|
|
class vvm_bufz : public vvm_nexus::recvr_t, public vvm_1bit_out {
|
1998-11-10 00:44:10 +01:00
|
|
|
public:
|
2000-12-10 07:41:59 +01:00
|
|
|
explicit vvm_bufz(unsigned delay =0);
|
2000-03-18 03:26:02 +01:00
|
|
|
~vvm_bufz();
|
1998-12-20 03:05:41 +01:00
|
|
|
|
2000-05-08 07:27:32 +02:00
|
|
|
void init_I(unsigned idx, vpip_bit_t val);
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-03-18 03:26:02 +01:00
|
|
|
void take_value(unsigned, vpip_bit_t val);
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
2001-10-14 05:50:53 +02:00
|
|
|
/*
|
|
|
|
|
* 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);
|
|
|
|
|
};
|
|
|
|
|
|
1999-05-01 04:57:52 +02:00
|
|
|
/*
|
|
|
|
|
* Threads use the vvm_sync to wait for something to happen. This
|
2000-04-10 07:26:05 +02:00
|
|
|
* class cooperates with the various event source classes that receive
|
|
|
|
|
* events and trigger the associated vvm_sync object.
|
2000-04-15 04:25:32 +02:00
|
|
|
*
|
|
|
|
|
* 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.
|
1999-05-01 04:57:52 +02:00
|
|
|
*/
|
2000-04-15 04:25:32 +02:00
|
|
|
|
1999-05-01 04:57:52 +02:00
|
|
|
class vvm_sync {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvm_sync();
|
|
|
|
|
|
|
|
|
|
void wait(vvm_thread*);
|
1999-12-12 20:47:54 +01:00
|
|
|
void wakeup();
|
1999-05-01 04:57:52 +02:00
|
|
|
|
2000-04-15 04:25:32 +02:00
|
|
|
// Receive triggers from the specified source.
|
|
|
|
|
void chain_sync(vvm_sync*src);
|
|
|
|
|
|
1999-05-01 04:57:52 +02:00
|
|
|
private:
|
|
|
|
|
vvm_thread*hold_;
|
|
|
|
|
|
2000-04-15 04:25:32 +02:00
|
|
|
vvm_sync**tgt_;
|
|
|
|
|
unsigned ntgt_;
|
|
|
|
|
|
1999-05-01 04:57:52 +02:00
|
|
|
private: // not implemented
|
|
|
|
|
vvm_sync(const vvm_sync&);
|
|
|
|
|
vvm_sync& operator= (const vvm_sync&);
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
class vvm_anyedge : public vvm_nexus::recvr_t {
|
|
|
|
|
|
1998-11-10 00:44:10 +01:00
|
|
|
public:
|
2000-04-10 07:26:05 +02:00
|
|
|
explicit vvm_anyedge(vvm_sync*tgt, unsigned n);
|
|
|
|
|
~vvm_anyedge();
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
void init_P(unsigned idx, vpip_bit_t val);
|
1998-11-10 00:44:10 +01:00
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
private:
|
|
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
1999-05-01 22:43:55 +02:00
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
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);
|
2000-03-16 20:03:03 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-04-10 07:26:05 +02:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
vpip_bit_t val_;
|
2000-03-16 20:03:03 +01:00
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
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);
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-04-10 07:26:05 +02:00
|
|
|
void take_value(unsigned key, vpip_bit_t val);
|
|
|
|
|
vpip_bit_t val_;
|
|
|
|
|
|
|
|
|
|
vvm_sync*sync_;
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
private: // not implemented
|
2000-04-10 07:26:05 +02:00
|
|
|
vvm_posedge(const vvm_posedge&);
|
|
|
|
|
vvm_posedge& operator= (const vvm_posedge&);
|
1998-11-10 00:44:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* $Log: vvm_gates.h,v $
|
2002-08-12 03:34:58 +02:00
|
|
|
* Revision 1.73 2002/08/12 01:35:07 steve
|
|
|
|
|
* conditional ident string using autoconfig.
|
|
|
|
|
*
|
2001-10-14 05:50:53 +02:00
|
|
|
* Revision 1.72 2001/10/14 03:50:53 steve
|
|
|
|
|
* vvm support for pullup/down gates (PR#288)
|
|
|
|
|
*
|
2001-04-23 01:09:45 +02:00
|
|
|
* Revision 1.71 2001/04/22 23:09:46 steve
|
|
|
|
|
* More UDP consolidation from Stephan Boettcher.
|
|
|
|
|
*
|
2001-01-16 04:57:46 +01:00
|
|
|
* Revision 1.70 2001/01/16 03:57:46 steve
|
|
|
|
|
* Get rid of gate templates.
|
|
|
|
|
*
|
2000-12-15 21:05:16 +01:00
|
|
|
* Revision 1.69 2000/12/15 20:05:16 steve
|
|
|
|
|
* Fix memory access in vvm. (PR#70)
|
|
|
|
|
*
|
2000-12-10 07:41:59 +01:00
|
|
|
* Revision 1.68 2000/12/10 06:42:00 steve
|
|
|
|
|
* Support delays on continuous assignment from idents. (PR#40)
|
|
|
|
|
*
|
2000-11-11 02:52:09 +01:00
|
|
|
* 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
|
|
|
|
|
*
|
2000-11-04 07:36:24 +01:00
|
|
|
* Revision 1.66 2000/11/04 06:36:24 steve
|
|
|
|
|
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
|
|
|
|
|
*
|
2000-09-17 23:26:15 +02:00
|
|
|
* Revision 1.65 2000/09/17 21:26:16 steve
|
|
|
|
|
* Add support for modulus (Eric Aardoom)
|
|
|
|
|
*
|
2000-05-12 01:37:26 +02:00
|
|
|
* Revision 1.64 2000/05/11 23:37:28 steve
|
|
|
|
|
* Add support for procedural continuous assignment.
|
|
|
|
|
*
|
2000-05-11 03:37:33 +02:00
|
|
|
* Revision 1.63 2000/05/11 01:37:33 steve
|
|
|
|
|
* Calculate the X output value from drive0 and drive1
|
|
|
|
|
*
|
2000-05-09 23:16:35 +02:00
|
|
|
* Revision 1.62 2000/05/09 21:16:35 steve
|
|
|
|
|
* Give strengths to logic and bufz devices.
|
|
|
|
|
*
|
2000-05-08 07:27:32 +02:00
|
|
|
* Revision 1.61 2000/05/08 05:27:32 steve
|
|
|
|
|
* Restore vvm_bufz to working condition.
|
|
|
|
|
*
|
2000-04-23 23:15:07 +02:00
|
|
|
* Revision 1.60 2000/04/23 21:15:07 steve
|
|
|
|
|
* Emit code for the bufif devices.
|
|
|
|
|
*
|
2000-04-23 05:45:24 +02:00
|
|
|
* Revision 1.59 2000/04/23 03:45:25 steve
|
|
|
|
|
* Add support for the procedural release statement.
|
|
|
|
|
*
|
2000-04-22 06:20:19 +02:00
|
|
|
* Revision 1.58 2000/04/22 04:20:20 steve
|
|
|
|
|
* Add support for force assignment.
|
|
|
|
|
*
|
2000-04-15 04:25:32 +02:00
|
|
|
* Revision 1.57 2000/04/15 02:25:32 steve
|
|
|
|
|
* Support chained events.
|
|
|
|
|
*
|
2000-04-10 07:26:05 +02:00
|
|
|
* Revision 1.56 2000/04/10 05:26:07 steve
|
|
|
|
|
* All events now use the NetEvent class.
|
|
|
|
|
*
|
2000-04-08 07:49:59 +02:00
|
|
|
* Revision 1.55 2000/04/08 05:49:59 steve
|
|
|
|
|
* Fix memory object compile problems.
|
|
|
|
|
*
|
2000-04-01 23:40:22 +02:00
|
|
|
* Revision 1.54 2000/04/01 21:40:23 steve
|
|
|
|
|
* Add support for integer division.
|
|
|
|
|
*
|
2000-03-29 06:37:10 +02:00
|
|
|
* Revision 1.53 2000/03/29 04:37:11 steve
|
|
|
|
|
* New and improved combinational primitives.
|
|
|
|
|
*
|
2000-03-26 18:28:31 +02:00
|
|
|
* Revision 1.52 2000/03/26 16:28:31 steve
|
|
|
|
|
* vvm_bitset_t is no longer a template.
|
|
|
|
|
*
|
2000-03-25 03:43:56 +01:00
|
|
|
* Revision 1.51 2000/03/25 02:43:57 steve
|
|
|
|
|
* Remove all remain vvm_bitset_t return values,
|
|
|
|
|
* and disallow vvm_bitset_t copying.
|
|
|
|
|
*
|
2000-03-24 04:47:01 +01:00
|
|
|
* Revision 1.50 2000/03/24 03:47:01 steve
|
|
|
|
|
* Update vvm_ram_dq to nexus style.
|
|
|
|
|
*
|
2000-03-22 05:26:40 +01:00
|
|
|
* 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.
|
1998-11-10 00:44:10 +01:00
|
|
|
*/
|
|
|
|
|
#endif
|