Add the part concatenation node (.concat).

Add a vvp_event_anyedge class to handle the special
 case of .event statements of edge type. This also
 frees the posedge/negedge types to handle all 4 inputs.

 Implement table functor recv_vec4 method to receive
 and process vectors.
This commit is contained in:
steve 2004-12-29 23:45:13 +00:00
parent 7166598ed0
commit 1674d692b7
10 changed files with 289 additions and 72 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.62 2004/12/11 02:31:29 steve Exp $"
#ident "$Id: Makefile.in,v 1.63 2004/12/29 23:45:13 steve Exp $"
#
#
SHELL = /bin/sh
@ -81,7 +81,7 @@ vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_tasks.o vpi_time.o \
vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
vpip_to_dec.o vpip_format.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o \
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o concat.o \
functor.o fvectors.o npmos.o part.o resolv.o stop.o symbols.o ufunc.o \
codes.o \
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.49 2004/12/18 18:52:44 steve Exp $
* $Id: README.txt,v 1.50 2004/12/29 23:45:13 steve Exp $
*/
VVP SIMULATION ENGINE
@ -450,6 +450,26 @@ bit number, and a width. Normally, those bits are constant values.
The input is typically a .reg or .net, but can be any vector node in
the netlist.
PART CONCATENATION STATEMENTS:
The opposite of the part select statement is the part concatenation
statement. The .concat statment is a functor node that takes at input
vector values and produces a single vector output that is the
concatenation of all the inputs.
<label> .concat [W X Y Z], <symbols_list> ;
The "[" and "]" tokens surround a set of 4 numbers that are the
expected widths of all the inputs. These widths are needed to figure
the positions of the input vectors in the generated output, and are
listed in order LSB to MSB. The inputs themselves are also listed LSB
to MSB, with the LSB vector input coming through port-0 of the real
functor.
The initial output value is (W+X+Y+Z) bits of 'bx. As input values are
propagated, the bits are placed in the correct place in the output
vector value, and a new output value is propagated.
FORCE STATEMENTS (old method - remove me):
A force statement creates functors that represent a Verilog force

View File

@ -1,7 +1,7 @@
#ifndef __compile_H
#define __compile_H
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2004 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: compile.h,v 1.57 2004/12/11 02:31:29 steve Exp $"
#ident "$Id: compile.h,v 1.58 2004/12/29 23:45:13 steve Exp $"
#endif
# include <stdio.h>
@ -83,11 +83,21 @@ extern void compile_functor(char*label, char*type,
/*
* This is called by the parser to make a resolver. This is a special
* kind of functor; a strength aware functor.
* kind of functor; a strength aware functor. It has up to 4 inputs
* that are blended to make a resolved output. The type string selects
* a resolution algorithm.
*/
extern void compile_resolver(char*label, char*type,
unsigned argc, struct symb_s*argv);
extern void compile_concat(char*label, unsigned w0, unsigned w1,
unsigned w2, unsigned w3,
unsigned argc, struct symb_s*argv);
/*
* This is called by the parser to create a part select node.
* See the PART SELECT STATEMENT section in the README.txt
*/
extern void compile_part_select(char*label, char*src,
unsigned base, unsigned wid);
@ -272,6 +282,16 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.58 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.57 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
@ -282,44 +302,5 @@ extern void compile_net(char*label, char*name,
*
* Revision 1.55 2004/06/30 02:15:57 steve
* Add signed LPM divide.
*
* Revision 1.54 2004/06/16 16:33:26 steve
* Add structural equality compare nodes.
*
* Revision 1.53 2003/09/04 20:26:31 steve
* Add $push flag for threads.
*
* Revision 1.52 2003/05/29 02:21:45 steve
* Implement acc_fetch_defname and its infrastructure in vvp.
*
* Revision 1.51 2003/04/11 05:15:39 steve
* Add signed versions of .cmp/gt/ge
*
* Revision 1.50 2003/03/10 23:37:07 steve
* Direct support for string parameters.
*
* Revision 1.49 2003/02/09 23:33:26 steve
* Spelling fixes.
*
* Revision 1.48 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.47 2003/01/25 23:48:06 steve
* Add thread word array, and add the instructions,
* %add/wr, %cmp/wr, %load/wr, %mul/wr and %set/wr.
*
* Revision 1.46 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.45 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.44 2002/07/15 00:21:42 steve
* Fix initialization of symbol table string heap.
*/
#endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.cc,v 1.16 2004/12/18 18:52:44 steve Exp $"
#ident "$Id: event.cc,v 1.17 2004/12/29 23:45:13 steve Exp $"
#endif
# include "event.h"
@ -64,13 +64,16 @@ const vvp_fun_edge::edge_t vvp_edge_negedge
| VVP_EDGE(BIT4_Z,BIT4_0)
;
const vvp_fun_edge::edge_t vvp_edge_anyedge = 0x7bde;
const vvp_fun_edge::edge_t vvp_edge_none = 0;
vvp_fun_edge::vvp_fun_edge(edge_t e)
: edge_(e)
{
threads = 0;
bits_[0] = BIT4_X;
bits_[1] = BIT4_X;
bits_[2] = BIT4_X;
bits_[3] = BIT4_X;
}
vvp_fun_edge::~vvp_fun_edge()
@ -80,10 +83,10 @@ vvp_fun_edge::~vvp_fun_edge()
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
{
/* See what kind of edge this represents. */
edge_t mask = VVP_EDGE(bits_.value(0), bit.value(0));
edge_t mask = VVP_EDGE(bits_[port.port()], bit.value(0));
/* Save the current input for the next time around. */
bits_ = bit;
bits_[port.port()] = bit.value(0);
if ((edge_ == vvp_edge_none) || (edge_ & mask)) {
run_waiting_threads_();
@ -93,6 +96,40 @@ void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
}
}
vvp_fun_anyedge::vvp_fun_anyedge()
{
}
vvp_fun_anyedge::~vvp_fun_anyedge()
{
}
void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
{
unsigned pdx = port.port();
bool flag = false;
if (bits_[pdx].size() != bit.size()) {
flag = true;
} else {
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
if (bits_[pdx].value(idx) != bit.value(idx)) {
flag = true;
break;
}
}
}
if (flag) {
bits_[pdx] = bit;
run_waiting_threads_();
vvp_net_t*net = port.ptr();
vvp_send_vec4(net->out, bit);
}
}
vvp_named_event::vvp_named_event(struct __vpiHandle*h)
{
handle_ = h;
@ -120,21 +157,29 @@ void vvp_named_event::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv)
{
vvp_fun_edge::edge_t edge = vvp_edge_none;
vvp_net_fun_t*fun = 0;
if (type) {
if (strcmp(type,"posedge") == 0)
edge = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0)
edge = vvp_edge_negedge;
else if (strcmp(type,"edge") == 0)
edge = vvp_edge_anyedge;
if (type && (strcmp(type,"edge") == 0) ) {
assert(argc <= 4);
free(type);
}
fun = new vvp_fun_anyedge;
vvp_fun_edge*fun = new vvp_fun_edge(edge);
} else {
vvp_fun_edge::edge_t edge = vvp_edge_none;
if (type) {
if (strcmp(type,"posedge") == 0)
edge = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0)
edge = vvp_edge_negedge;
assert(argc <= 4);
free(type);
}
fun = new vvp_fun_edge(edge);
}
vvp_net_t* ptr = new vvp_net_t;
ptr->fun = fun;
@ -167,6 +212,16 @@ void compile_named_event(char*label, char*name)
/*
* $Log: event.cc,v $
* Revision 1.17 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.16 2004/12/18 18:52:44 steve
* Rework named events and event/or.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.h,v 1.7 2004/12/18 18:52:44 steve Exp $"
#ident "$Id: event.h,v 1.8 2004/12/29 23:45:13 steve Exp $"
#endif
# include "vvp_net.h"
@ -57,15 +57,32 @@ class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
vvp_vector4_t bits_;
vvp_bit4_t bits_[4];
edge_t edge_;
};
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
extern const vvp_fun_edge::edge_t vvp_edge_anyedge;
extern const vvp_fun_edge::edge_t vvp_edge_none;
/*
* The vvp_fun_anyedge functor checks to see if any value in an input
* vector changes. Unlike the vvp_fun_edge, which watches for the LSB
* of its inputs to change in a particular direction, the anyedge
* functor looks at the entire input vector for any change.
*/
class vvp_fun_anyedge : public vvp_net_fun_t, public waitable_hooks_s {
public:
explicit vvp_fun_anyedge();
virtual ~vvp_fun_anyedge();
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
vvp_vector4_t bits_[4];
};
/*
* A named event is simpler then a vvp_fun_edge in that it triggers on
* any input at all to port-0. The idea here is that behavioral code
@ -86,6 +103,16 @@ class vvp_named_event : public vvp_net_fun_t, public waitable_hooks_s {
/*
* $Log: event.h,v $
* Revision 1.8 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.7 2004/12/18 18:52:44 steve
* Rework named events and event/or.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.44 2004/12/11 02:31:29 steve Exp $"
#ident "$Id: lexor.lex,v 1.45 2004/12/29 23:45:13 steve Exp $"
#endif
# include "parse_misc.h"
@ -95,6 +95,7 @@
".cmp/ge.s" { return K_CMP_GE_S; }
".cmp/gt" { return K_CMP_GT; }
".cmp/gt.s" { return K_CMP_GT_S; }
".concat" { return K_CONCAT; }
".event" { return K_EVENT; }
".event/or" { return K_EVENT_OR; }
".functor" { return K_FUNCTOR; }
@ -183,6 +184,16 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.45 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.44 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.cc,v 1.14 2004/12/11 02:31:29 steve Exp $"
#ident "$Id: logic.cc,v 1.15 2004/12/29 23:45:13 steve Exp $"
#endif
# include "logic.h"
@ -48,6 +48,53 @@ table_functor_s::~table_functor_s()
{
}
/*
* WARNING: This function assumes that the table generator encodes the
* values 0/1/x/z the same as the vvp_bit4_t enumeration values.
*/
void table_functor_s::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t val)
{
input_[ptr.port()] = val;
vvp_vector4_t result (val.size());
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
unsigned lookup = 0;
for (unsigned pdx = 4 ; pdx > 0 ; pdx -= 1) {
lookup <<= 2;
if (idx < input_[pdx-1].size())
lookup |= input_[pdx-1].value(idx);
}
unsigned off = lookup / 4;
unsigned shift = lookup % 4 * 2;
unsigned bit_val = table[off] >> shift;
bit_val &= 3;
result.set_bit(idx, (vvp_bit4_t)bit_val);
}
vvp_send_vec4(ptr.ptr()->out, result);
}
vvp_fun_buf::vvp_fun_buf()
{
count_functors_table += 1;
}
vvp_fun_buf::~vvp_fun_buf()
{
}
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
if (ptr.port() != 0)
return;
vvp_send_vec4(ptr.ptr()->out, bit);
}
/*
* The parser calls this function to create a logic functor. I allocate a
* functor, and map the name to the vvp_ipoint_t address for the
@ -58,7 +105,7 @@ void compile_functor(char*label, char*type,
vvp_delay_t delay, unsigned ostr0, unsigned ostr1,
unsigned argc, struct symb_s*argv)
{
table_functor_s* obj = 0;
vvp_net_fun_t* obj = 0;
if (strcmp(type, "OR") == 0) {
obj = new table_functor_s(ft_OR);
@ -67,7 +114,7 @@ void compile_functor(char*label, char*type,
obj = new table_functor_s(ft_AND);
} else if (strcmp(type, "BUF") == 0) {
obj = new table_functor_s(ft_BUF);
obj = new vvp_fun_buf();
#if 0
} else if (strcmp(type, "BUFIF0") == 0) {
obj = new vvp_bufif_s(true,false, ostr0, ostr1);
@ -132,6 +179,7 @@ void compile_functor(char*label, char*type,
assert(argc <= 4);
vvp_net_t*net = new vvp_net_t;
net->fun = obj;
define_functor_symbol(label, net);
free(label);
@ -143,6 +191,16 @@ void compile_functor(char*label, char*type,
/*
* $Log: logic.cc,v $
* Revision 1.15 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.14 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.h,v 1.8 2004/12/11 02:31:29 steve Exp $"
#ident "$Id: logic.h,v 1.9 2004/12/29 23:45:13 steve Exp $"
#endif
# include "vvp_net.h"
@ -38,8 +38,28 @@ class table_functor_s: public vvp_net_fun_t {
explicit table_functor_s(truth_t t);
virtual ~table_functor_s();
void recv_vec4(vvp_net_ptr_t p, vvp_vector4_t bit);
private:
truth_t table;
vvp_vector4_t input_[4];
};
/*
* The buffer functor is a very primitive functor that takes the input
* from port-0 (and only port-0) and retransmits it as a vvp_vector4_t.
* This is intended to model the Verilog buf(Q,D) statement. This
* device should be useful for removing strength from vectors.
*/
class vvp_fun_buf: public vvp_net_fun_t {
public:
explicit vvp_fun_buf();
virtual ~vvp_fun_buf();
void recv_vec4(vvp_net_ptr_t p, vvp_vector4_t bit);
private:
};
// table functor types
@ -66,6 +86,16 @@ extern const unsigned char ft_var[];
/*
* $Log: logic.h,v $
* Revision 1.9 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.8 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -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.61 2004/12/11 02:31:30 steve Exp $"
#ident "$Id: parse.y,v 1.62 2004/12/29 23:45:13 steve Exp $"
#endif
# include "parse_misc.h"
@ -60,6 +60,7 @@ extern FILE*yyin;
%token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
%token K_ARITH_SUB K_ARITH_SUM
%token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
%token K_CONCAT
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM K_PART
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
%token K_UDP K_UDP_C K_UDP_S
@ -187,6 +188,10 @@ statement
| T_LABEL K_PART T_SYMBOL ',' T_NUMBER ',' T_NUMBER ';'
{ compile_part_select($1, $3, $5, $7); }
| T_LABEL K_CONCAT '[' T_NUMBER T_NUMBER T_NUMBER T_NUMBER ']' ','
symbols ';'
{ compile_concat($1, $4, $5, $6, $7, $10.cnt, $10.vect); }
/* Force statements are very much like functors. They are
compiled to functors of a different mode. */
@ -637,6 +642,16 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.62 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.61 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: vvp_net.h,v 1.2 2004/12/15 17:16:08 steve Exp $"
#ident "$Id: vvp_net.h,v 1.3 2004/12/29 23:45:13 steve Exp $"
# include <assert.h>
@ -295,14 +295,24 @@ class vvp_net_fun_t {
* concatenation of the inputs. The inputs (4) may be scalers or other
* vectors. Scalers are turned into vectors of size==1 before
* concatenating.
*
* The expected widths of the input vectors must be given up front so
* that the positions in the output vector (and also the size of the
* output vector) can be worked out. The input vectors must match the
* expected width.
*/
class vvp_fun_concat : public vvp_net_fun_t {
public:
vvp_fun_concat();
vvp_fun_concat(unsigned w0, unsigned w1,
unsigned w2, unsigned w3);
~vvp_fun_concat();
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
unsigned wid_[4];
vvp_vector4_t val_;
};
/* vvp_fun_drive
@ -428,6 +438,16 @@ class vvp_fun_signal : public vvp_net_fun_t {
/*
* $Log: vvp_net.h,v $
* Revision 1.3 2004/12/29 23:45:13 steve
* Add the part concatenation node (.concat).
*
* Add a vvp_event_anyedge class to handle the special
* case of .event statements of edge type. This also
* frees the posedge/negedge types to handle all 4 inputs.
*
* Implement table functor recv_vec4 method to receive
* and process vectors.
*
* Revision 1.2 2004/12/15 17:16:08 steve
* Add basic force/release capabilities.
*