Functor values and propagation.
This commit is contained in:
parent
cb65ee5e00
commit
cbc3be0304
|
|
@ -8,4 +8,5 @@ lexor.cc
|
||||||
parse.cc
|
parse.cc
|
||||||
parse.cc.output
|
parse.cc.output
|
||||||
parse.h
|
parse.h
|
||||||
|
tables.cc
|
||||||
vvp
|
vvp
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
# 59 Temple Place - Suite 330
|
# 59 Temple Place - Suite 330
|
||||||
# Boston, MA 02111-1307, USA
|
# Boston, MA 02111-1307, USA
|
||||||
#
|
#
|
||||||
#ident "$Id: Makefile.in,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
#ident "$Id: Makefile.in,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
|
|
@ -52,7 +52,7 @@ distclean: clean
|
||||||
rm -f config.h Makefile config.cache config.log config.status
|
rm -f config.h Makefile config.cache config.log config.status
|
||||||
|
|
||||||
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
|
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
|
||||||
codes.o vthread.o schedule.o
|
codes.o vthread.o schedule.o tables.o
|
||||||
|
|
||||||
vvp: $O
|
vvp: $O
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o vvp $O
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o vvp $O
|
||||||
|
|
@ -63,6 +63,10 @@ vvp: $O
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||||
mv $*.d dep/$*.d
|
mv $*.d dep/$*.d
|
||||||
|
|
||||||
|
tables.cc: draw_tt.c
|
||||||
|
$(CC) -o draw_tt draw_tt.c
|
||||||
|
./draw_tt > tables.cc
|
||||||
|
rm draw_tt
|
||||||
|
|
||||||
lexor.o: lexor.cc parse.h
|
lexor.o: lexor.cc parse.h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Every statement is terminated by a semicolon. The semicolon is also
|
||||||
the start of a comment line, so you can put comment text after the
|
the start of a comment line, so you can put comment text after the
|
||||||
semicolon that terminates a statement. Like so:
|
semicolon that terminates a statement. Like so:
|
||||||
|
|
||||||
Label .functor and, x, y ; This is a comment.
|
Label .functor and, 0x5a, x, y ; This is a comment.
|
||||||
|
|
||||||
The semicolon is required, whether the comment is there or not.
|
The semicolon is required, whether the comment is there or not.
|
||||||
|
|
||||||
|
|
@ -59,15 +59,20 @@ label is required for functors.
|
||||||
|
|
||||||
The general syntax of a functor is:
|
The general syntax of a functor is:
|
||||||
|
|
||||||
<label> .functor <type> [, symbol_list]
|
<label> .functor <type>, <init> [, symbol_list]
|
||||||
|
|
||||||
The symbol list is 0-4 names of labels of other functors. These
|
The symbol list is 0-4 names of labels of other functors. These
|
||||||
connect inputs of the functor of the statement to the output of other
|
connect inputs of the functor of the statement to the output of other
|
||||||
functors. The type is the label of a .ftype statement elsewhere in the
|
functors. The type is the label of a .ftype statement elsewhere in the
|
||||||
program. The references .ftype describes the behavoir of the functor.
|
program. The references .ftype describes the behavoir of the
|
||||||
|
functor.
|
||||||
|
|
||||||
|
The <init> value is the 8-bit initial value of the 4 input ports. The
|
||||||
|
LSB is port 0, and the MSB port 3.
|
||||||
|
|
||||||
Almost all of the structural aspects of a simulation can be
|
Almost all of the structural aspects of a simulation can be
|
||||||
represented by functors.
|
represented by functors, which perform the very basic task of
|
||||||
|
combining up to four inputs down to one output.
|
||||||
|
|
||||||
VARIABLE STATEMENTS:
|
VARIABLE STATEMENTS:
|
||||||
|
|
||||||
|
|
@ -111,6 +116,43 @@ This statement creates a thread with a starting address at the
|
||||||
instruction given by <symbol>.
|
instruction given by <symbol>.
|
||||||
|
|
||||||
|
|
||||||
|
TRUTH TABLES
|
||||||
|
|
||||||
|
The logic that a functor represents is expressed as a truth table. The
|
||||||
|
functor has four inputs and one output. Each input and output has one
|
||||||
|
of four possible values (0, 1, x and z) so two bits are needed to
|
||||||
|
represent them. So the input of the functor is 8 bits, and the output
|
||||||
|
2 bits. A complete lookup table for generating the 2-bit output from
|
||||||
|
an 8-bit input is 512 bits. That can be packed into 64 bytes. This is
|
||||||
|
small enough that the table should take less space then the code to
|
||||||
|
implement the logic.
|
||||||
|
|
||||||
|
To implement the truth table, we need to assign 2-bit encodings for
|
||||||
|
the 4-value signals. I choose, pseudo-randomly, the following
|
||||||
|
encoding:
|
||||||
|
|
||||||
|
1'b0 : 00
|
||||||
|
1'b1 : 01
|
||||||
|
1'bx : 10
|
||||||
|
1'bz : 11
|
||||||
|
|
||||||
|
The table is an array of 64 bytes, each byte holding 4 2-bit
|
||||||
|
outputs. Construct a 6-bit byte address with inputs 1, 2 and 3 like
|
||||||
|
so:
|
||||||
|
332211
|
||||||
|
|
||||||
|
The input 0 2-bits can then be used to select which of the 4 2-bit
|
||||||
|
pairs in the 8-bit byte are the output:
|
||||||
|
|
||||||
|
MSB -> zzxx1100 <- LSB
|
||||||
|
|
||||||
|
A complete truth table, then is described as 64 8-bit bytes.
|
||||||
|
|
||||||
|
The vvp engine includes truth tables for the primitive gate types, so
|
||||||
|
none needs to be given by the programmer. It is sufficient to name the
|
||||||
|
type to get that truth table.
|
||||||
|
|
||||||
|
|
||||||
EXECUTABLE INSTRUCTIONS
|
EXECUTABLE INSTRUCTIONS
|
||||||
|
|
||||||
Threads run executable code, much like a processor executes machine
|
Threads run executable code, much like a processor executes machine
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: compile.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
#ident "$Id: compile.cc,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "compile.h"
|
# include "compile.h"
|
||||||
|
|
@ -125,7 +125,8 @@ void compile_init(void)
|
||||||
* functor, and map the name to the vvp_ipoint_t address for the
|
* functor, and map the name to the vvp_ipoint_t address for the
|
||||||
* functor. Also resolve the inputs to the functor.
|
* functor. Also resolve the inputs to the functor.
|
||||||
*/
|
*/
|
||||||
void compile_functor(char*label, char*type, unsigned argc, char**argv)
|
void compile_functor(char*label, char*type, unsigned init,
|
||||||
|
unsigned argc, char**argv)
|
||||||
{
|
{
|
||||||
vvp_ipoint_t fdx = functor_allocate();
|
vvp_ipoint_t fdx = functor_allocate();
|
||||||
functor_t obj = functor_index(fdx);
|
functor_t obj = functor_index(fdx);
|
||||||
|
|
@ -163,6 +164,19 @@ void compile_functor(char*label, char*type, unsigned argc, char**argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj->ival = init;
|
||||||
|
obj->oval = 2;
|
||||||
|
|
||||||
|
if (strcmp(type, "OR") == 0) {
|
||||||
|
obj->table = ft_OR;
|
||||||
|
|
||||||
|
} else if (strcmp(type, "AND") == 0) {
|
||||||
|
obj->table = ft_AND;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
yyerror("invalid functor type.");
|
||||||
|
}
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
free(label);
|
free(label);
|
||||||
free(type);
|
free(type);
|
||||||
|
|
@ -298,12 +312,20 @@ void compile_thread(char*start_sym)
|
||||||
void compile_variable(char*label)
|
void compile_variable(char*label)
|
||||||
{
|
{
|
||||||
vvp_ipoint_t fdx = functor_allocate();
|
vvp_ipoint_t fdx = functor_allocate();
|
||||||
functor_t obj = functor_index(fdx);
|
|
||||||
sym_set_value(sym_functors, label, fdx);
|
sym_set_value(sym_functors, label, fdx);
|
||||||
|
|
||||||
|
functor_t obj = functor_index(fdx);
|
||||||
|
obj->table = ft_var;
|
||||||
|
obj->ival = 0x22;
|
||||||
|
obj->oval = 0x02;
|
||||||
|
|
||||||
free(label);
|
free(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When parsing is otherwise complete, this function is called to do
|
||||||
|
* the final stuff. Clean up deferred linking here.
|
||||||
|
*/
|
||||||
void compile_cleanup(void)
|
void compile_cleanup(void)
|
||||||
{
|
{
|
||||||
struct resolv_list_s*tmp_list = resolv_list;
|
struct resolv_list_s*tmp_list = resolv_list;
|
||||||
|
|
@ -313,12 +335,18 @@ void compile_cleanup(void)
|
||||||
struct resolv_list_s*res = tmp_list;
|
struct resolv_list_s*res = tmp_list;
|
||||||
tmp_list = res->next;
|
tmp_list = res->next;
|
||||||
|
|
||||||
|
/* Get the addressed functor object and select the input
|
||||||
|
port that needs resolution. */
|
||||||
functor_t obj = functor_index(res->port);
|
functor_t obj = functor_index(res->port);
|
||||||
unsigned idx = ipoint_port(res->port);
|
unsigned idx = ipoint_port(res->port);
|
||||||
|
|
||||||
|
/* Try again to look up the symbol that was not defined
|
||||||
|
the first time around. */
|
||||||
vvp_ipoint_t tmp = sym_get_value(sym_functors, res->source);
|
vvp_ipoint_t tmp = sym_get_value(sym_functors, res->source);
|
||||||
|
|
||||||
if (tmp != 0) {
|
if (tmp != 0) {
|
||||||
|
/* The symbol is defined, link the functor input
|
||||||
|
to the resolved output. */
|
||||||
functor_t fport = functor_index(tmp);
|
functor_t fport = functor_index(tmp);
|
||||||
obj->port[idx] = fport->out;
|
obj->port[idx] = fport->out;
|
||||||
fport->out = res->port;
|
fport->out = res->port;
|
||||||
|
|
@ -353,6 +381,9 @@ void compile_dump(FILE*fd)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: compile.cc,v $
|
* $Log: compile.cc,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: compile.h,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
#ident "$Id: compile.h,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
@ -47,7 +47,7 @@ extern void compile_cleanup(void);
|
||||||
* of the functor. The compile should match those port parameters up
|
* of the functor. The compile should match those port parameters up
|
||||||
* to existing functors to manage the linking.
|
* to existing functors to manage the linking.
|
||||||
*/
|
*/
|
||||||
extern void compile_functor(char*label, char*type,
|
extern void compile_functor(char*label, char*type, unsigned init,
|
||||||
unsigned argc, char**argv);
|
unsigned argc, char**argv);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -97,6 +97,9 @@ extern void compile_dump(FILE*fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: compile.h,v $
|
* $Log: compile.h,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
|
*
|
||||||
|
* This source code is free software; you can redistribute it
|
||||||
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
#if !defined(WINNT)
|
||||||
|
#ident "$Id: draw_tt.c,v 1.1 2001/03/11 22:42:11 steve Exp $"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
|
||||||
|
static void draw_AND(void)
|
||||||
|
{
|
||||||
|
unsigned i0, i1, i2, i3;
|
||||||
|
|
||||||
|
printf("const unsigned char ft_AND[64] = {");
|
||||||
|
|
||||||
|
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||||
|
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||||
|
printf("\n ");
|
||||||
|
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||||
|
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||||
|
unsigned char byte = 0;
|
||||||
|
|
||||||
|
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||||
|
unsigned val;
|
||||||
|
if ((i0 == 0) || (i1 == 0) ||
|
||||||
|
(i2 == 0) || (i3 == 0))
|
||||||
|
val = 0;
|
||||||
|
else if ((i0 == 1) && (i1 == 1) &&
|
||||||
|
(i2 == 1) && (i3 == 1))
|
||||||
|
val = 1;
|
||||||
|
else
|
||||||
|
val = 2;
|
||||||
|
|
||||||
|
byte |= val << (i0*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("0x%02x, ", byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_OR(void)
|
||||||
|
{
|
||||||
|
unsigned i0, i1, i2, i3;
|
||||||
|
|
||||||
|
printf("const unsigned char ft_OR[64] = {");
|
||||||
|
|
||||||
|
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||||
|
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||||
|
printf("\n ");
|
||||||
|
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||||
|
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||||
|
unsigned char byte = 0;
|
||||||
|
|
||||||
|
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||||
|
unsigned val;
|
||||||
|
if ((i0 == 1) || (i1 == 1) ||
|
||||||
|
(i2 == 1) || (i3 == 1))
|
||||||
|
val = 1;
|
||||||
|
else if ((i0 == 0) && (i1 == 0) &&
|
||||||
|
(i2 == 0) && (i3 == 0))
|
||||||
|
val = 0;
|
||||||
|
else
|
||||||
|
val = 2;
|
||||||
|
|
||||||
|
byte |= val << (i0*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("0x%02x, ", byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
printf("# include \"functor.h\"\n");
|
||||||
|
draw_AND();
|
||||||
|
draw_OR();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Log: draw_tt.c,v $
|
||||||
|
* Revision 1.1 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
@ -17,10 +17,11 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: functor.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
#ident "$Id: functor.cc,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "functor.h"
|
# include "functor.h"
|
||||||
|
# include "schedule.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -68,7 +69,7 @@ void functor_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate normall is just a matter of incrementing the functor_count
|
* Allocate normally is just a matter of incrementing the functor_count
|
||||||
* and returning a pointer to the next unallocated functor. However,
|
* and returning a pointer to the next unallocated functor. However,
|
||||||
* if we overrun a chunk or an index, we need to allocate the needed
|
* if we overrun a chunk or an index, we need to allocate the needed
|
||||||
* bits first.
|
* bits first.
|
||||||
|
|
@ -95,7 +96,11 @@ vvp_ipoint_t functor_allocate(void)
|
||||||
return res * 4;
|
return res * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a vvp_ipoint_t pointer, return a pointer to the detailed
|
||||||
|
* functor structure. This does not use the low 2 bits, which address
|
||||||
|
* a specific port of the functor.
|
||||||
|
*/
|
||||||
functor_t functor_index(vvp_ipoint_t point)
|
functor_t functor_index(vvp_ipoint_t point)
|
||||||
{
|
{
|
||||||
point /= 4;
|
point /= 4;
|
||||||
|
|
@ -112,6 +117,57 @@ functor_t functor_index(vvp_ipoint_t point)
|
||||||
return functor_table[point]->table[index1]->table + index0;
|
return functor_table[point]->table[index1]->table + index0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the addressed bit of the functor, and recalculate the
|
||||||
|
* output. If the output changes any, then generate the necessary
|
||||||
|
* propagation events to pass the output on.
|
||||||
|
*/
|
||||||
|
void functor_set(vvp_ipoint_t ptr, unsigned bit)
|
||||||
|
{
|
||||||
|
functor_t fp = functor_index(ptr);
|
||||||
|
unsigned pp = ipoint_port(ptr);
|
||||||
|
assert(fp);
|
||||||
|
assert(fp->table);
|
||||||
|
|
||||||
|
/* Change the bits of the input. */
|
||||||
|
static const unsigned char mask_table[4] = { 0xfc, 0xf3, 0xcf, 0x3f };
|
||||||
|
unsigned char mask = mask_table[pp];
|
||||||
|
fp->ival = (fp->ival & mask) | (bit << (2*pp));
|
||||||
|
|
||||||
|
/* Locate the new output value in the table. */
|
||||||
|
unsigned char out = fp->table[fp->ival >> 2];
|
||||||
|
out >>= 2 * (fp->ival&0x03);
|
||||||
|
out &= 0x03;
|
||||||
|
|
||||||
|
/* If the output changes, then create a propagation event. */
|
||||||
|
if (out != fp->oval) {
|
||||||
|
fp->oval = out;
|
||||||
|
schedule_functor(ptr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is used by the scheduler to implement the propagation
|
||||||
|
* event. The input is the pointer to the functor who's output is to
|
||||||
|
* be propagated. Pass the output to the inputs of all the connected
|
||||||
|
* functors.
|
||||||
|
*/
|
||||||
|
void functor_propagate(vvp_ipoint_t ptr)
|
||||||
|
{
|
||||||
|
functor_t fp = functor_index(ptr);
|
||||||
|
unsigned char oval = fp->oval;
|
||||||
|
|
||||||
|
printf("functor %lx becomes %u\n", ptr, oval);
|
||||||
|
|
||||||
|
vvp_ipoint_t idx = fp->out;
|
||||||
|
while (idx) {
|
||||||
|
functor_t idxp = functor_index(idx);
|
||||||
|
vvp_ipoint_t next = idxp->port[ipoint_port(idx)];
|
||||||
|
printf(" set %lx to %u\n", idx, oval);
|
||||||
|
functor_set(idx, oval);
|
||||||
|
idx = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void functor_dump(FILE*fd)
|
void functor_dump(FILE*fd)
|
||||||
{
|
{
|
||||||
|
|
@ -123,8 +179,35 @@ void functor_dump(FILE*fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The variable functor is special. This is the truth table for it.
|
||||||
|
*/
|
||||||
|
const unsigned char ft_var[16] = {
|
||||||
|
0xe4, /* 0 0: 11, 10, 01, 00 */
|
||||||
|
0xe4, /* 0 1: 11, 10, 01, 00 */
|
||||||
|
0xe4, /* 0 x: 11, 10, 01, 00 */
|
||||||
|
0xe4, /* 0 z: 11, 10, 01, 00 */
|
||||||
|
0x00, /* 1 0: 00, 00, 00, 00 */
|
||||||
|
0x55, /* 1 1: 01, 01, 01, 01 */
|
||||||
|
0xaa, /* 1 x: 10, 10, 10, 10 */
|
||||||
|
0xff, /* 1 z: 11, 11, 11, 11 */
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4,
|
||||||
|
0xe4
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: functor.cc,v $
|
* $Log: functor.cc,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: functor.h,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
#ident "$Id: functor.h,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "pointers.h"
|
# include "pointers.h"
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
||||||
typedef struct vvp_truth_s*vvp_truth_t;
|
typedef const unsigned char*vvp_truth_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The vvp_ipoint_t is an integral type that is 32bits. The low 2 bits
|
* The vvp_ipoint_t is an integral type that is 32bits. The low 2 bits
|
||||||
|
|
@ -39,6 +39,12 @@ typedef struct vvp_truth_s*vvp_truth_t;
|
||||||
* port, and so on. The last .port[x] contains the null vvp_ipoint_t
|
* port, and so on. The last .port[x] contains the null vvp_ipoint_t
|
||||||
* value zero (0). In this way, an output can fan out as wide as the
|
* value zero (0). In this way, an output can fan out as wide as the
|
||||||
* original design requires.
|
* original design requires.
|
||||||
|
*
|
||||||
|
* Value Encoding
|
||||||
|
* 1'b0 : 00
|
||||||
|
* 1'b1 : 01
|
||||||
|
* 1'bx : 10
|
||||||
|
* 1'bz : 11
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct functor_s {
|
struct functor_s {
|
||||||
|
|
@ -48,6 +54,9 @@ struct functor_s {
|
||||||
vvp_ipoint_t out;
|
vvp_ipoint_t out;
|
||||||
/* These are the input ports. */
|
/* These are the input ports. */
|
||||||
vvp_ipoint_t port[4];
|
vvp_ipoint_t port[4];
|
||||||
|
/* These are the input values. */
|
||||||
|
unsigned char ival;
|
||||||
|
unsigned char oval;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct functor_s *functor_t;
|
typedef struct functor_s *functor_t;
|
||||||
|
|
@ -66,6 +75,20 @@ extern void functor_init(void);
|
||||||
*/
|
*/
|
||||||
extern vvp_ipoint_t functor_allocate(void);
|
extern vvp_ipoint_t functor_allocate(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* functor_set sets the addressed input to the specified value, and
|
||||||
|
* calculates a new output value. If there is any propagation to do,
|
||||||
|
* propagation events are created.
|
||||||
|
*/
|
||||||
|
extern void functor_set(vvp_ipoint_t point, unsigned val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When a propagation event happens, this function is called with the
|
||||||
|
* address of the affected functor. It propagates the output to all
|
||||||
|
* the inputs it is connected to, creating new propagation event on
|
||||||
|
* the way.
|
||||||
|
*/
|
||||||
|
extern void functor_propagate(vvp_ipoint_t ptr);
|
||||||
/*
|
/*
|
||||||
* Given an ipoint_t pointer, return a C pointer to the functor. This
|
* Given an ipoint_t pointer, return a C pointer to the functor. This
|
||||||
* is like a pointer dereference. The point parameter must have been
|
* is like a pointer dereference. The point parameter must have been
|
||||||
|
|
@ -78,8 +101,16 @@ extern functor_t functor_index(vvp_ipoint_t point);
|
||||||
*/
|
*/
|
||||||
extern void functor_dump(FILE*fd);
|
extern void functor_dump(FILE*fd);
|
||||||
|
|
||||||
|
|
||||||
|
extern const unsigned char ft_AND[];
|
||||||
|
extern const unsigned char ft_OR[];
|
||||||
|
extern const unsigned char ft_var[];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: functor.h,v $
|
* $Log: functor.h,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
FUNCTOR DETAILS
|
||||||
|
|
||||||
|
The README.txt describes the .functor statement and how that creates a
|
||||||
|
functor. It also makes passing mention of how the functor is connected
|
||||||
|
up to the netlist. This document describes in detail how a functor is
|
||||||
|
supposed to act. See also the functor.h header file and the functor.cc
|
||||||
|
source file.
|
||||||
|
|
||||||
|
The current values of the inputs are stored in a single 8-bit byte,
|
||||||
|
2-bits per value. This is the ``ival'' member. The input of a functor
|
||||||
|
gets set by propagation events, assign events or %set
|
||||||
|
instructions.
|
||||||
|
|
||||||
|
The output value is stored in two bits of the functor. The current
|
||||||
|
output is used to detect edges when the input changes. Whenever an
|
||||||
|
input is set, a new output is calculated and compared with the current
|
||||||
|
output. If the current output is the same as the new output, then the
|
||||||
|
operation is complete and propagation stops.
|
||||||
|
|
||||||
|
If after a set the output changes, the current output is changed to
|
||||||
|
the new output, and a propagation event is created. This propagation
|
||||||
|
event is given a pointer to the functor that changed, and *not* simply
|
||||||
|
the contents of the out port. The event is scheduled for a delay that
|
||||||
|
is the propagation delay for the functor.
|
||||||
|
|
||||||
|
A propagation event is the only way that the output of a functor is
|
||||||
|
moved to the input of another functor. The propagation event, which is
|
||||||
|
given a pointer to the functor to propagate, looks at the output list
|
||||||
|
and sets the listed inputs to the current value of the output.
|
||||||
10
vvp/parse.y
10
vvp/parse.y
|
|
@ -50,12 +50,12 @@ statement
|
||||||
/* Functor statements define functors. The functor must have a
|
/* Functor statements define functors. The functor must have a
|
||||||
label and a type name, and may have operands. */
|
label and a type name, and may have operands. */
|
||||||
|
|
||||||
: T_LABEL K_FUNCTOR T_SYMBOL ',' symbols ';'
|
: T_LABEL K_FUNCTOR T_SYMBOL ',' T_NUMBER ',' symbols ';'
|
||||||
{ struct textv_s obj = $5;
|
{ struct textv_s obj = $7;
|
||||||
compile_functor($1, $3, obj.cnt, obj.text);
|
compile_functor($1, $3, $5, obj.cnt, obj.text);
|
||||||
}
|
}
|
||||||
| T_LABEL K_FUNCTOR T_SYMBOL ';'
|
| T_LABEL K_FUNCTOR T_SYMBOL',' T_NUMBER ';'
|
||||||
{ compile_functor($1, $3, 0, 0); }
|
{ compile_functor($1, $3, $5, 0, 0); }
|
||||||
|
|
||||||
/* Instructions may have a label, and have zero or more
|
/* Instructions may have a label, and have zero or more
|
||||||
operands. The meaning of and restrictions on the operands depends
|
operands. The meaning of and restrictions on the operands depends
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: schedule.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
|
#ident "$Id: schedule.cc,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
|
# include "functor.h"
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
@ -28,12 +29,19 @@
|
||||||
struct event_s {
|
struct event_s {
|
||||||
unsigned delay;
|
unsigned delay;
|
||||||
|
|
||||||
vthread_t thr;
|
union {
|
||||||
vvp_ipoint_t fun;
|
vthread_t thr;
|
||||||
|
vvp_ipoint_t fun;
|
||||||
|
};
|
||||||
|
unsigned val :2;
|
||||||
|
unsigned type :2;
|
||||||
|
|
||||||
struct event_s*next;
|
struct event_s*next;
|
||||||
struct event_s*last;
|
struct event_s*last;
|
||||||
};
|
};
|
||||||
|
const unsigned TYPE_THREAD = 0;
|
||||||
|
const unsigned TYPE_PROP = 1;
|
||||||
|
const unsigned TYPE_ASSIGN = 2;
|
||||||
|
|
||||||
static struct event_s* list = 0;
|
static struct event_s* list = 0;
|
||||||
|
|
||||||
|
|
@ -91,6 +99,7 @@ void schedule_vthread(vthread_t thr, unsigned delay)
|
||||||
|
|
||||||
cur->delay = delay;
|
cur->delay = delay;
|
||||||
cur->thr = thr;
|
cur->thr = thr;
|
||||||
|
cur->type = TYPE_THREAD;
|
||||||
|
|
||||||
schedule_event_(cur);
|
schedule_event_(cur);
|
||||||
}
|
}
|
||||||
|
|
@ -102,10 +111,25 @@ void schedule_functor(vvp_ipoint_t fun, unsigned delay)
|
||||||
|
|
||||||
cur->delay = delay;
|
cur->delay = delay;
|
||||||
cur->fun = fun;
|
cur->fun = fun;
|
||||||
|
cur->type = TYPE_PROP;
|
||||||
|
|
||||||
schedule_event_(cur);
|
schedule_event_(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void schedule_assign(vvp_ipoint_t fun, unsigned char val, unsigned delay)
|
||||||
|
{
|
||||||
|
struct event_s*cur = (struct event_s*)
|
||||||
|
calloc(1, sizeof(struct event_s));
|
||||||
|
|
||||||
|
cur->delay = delay;
|
||||||
|
cur->fun = fun;
|
||||||
|
cur->val = val;
|
||||||
|
cur->type= TYPE_ASSIGN;
|
||||||
|
|
||||||
|
schedule_event_(cur);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long schedule_time;
|
static unsigned long schedule_time;
|
||||||
|
|
||||||
void schedule_simulate(void)
|
void schedule_simulate(void)
|
||||||
|
|
@ -127,11 +151,19 @@ void schedule_simulate(void)
|
||||||
printf("TIME: %u\n", schedule_time);
|
printf("TIME: %u\n", schedule_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur->thr) {
|
switch (cur->type) {
|
||||||
|
case TYPE_THREAD:
|
||||||
vthread_run(cur->thr);
|
vthread_run(cur->thr);
|
||||||
|
break;
|
||||||
|
|
||||||
} else if (cur->fun) {
|
case TYPE_PROP:
|
||||||
/* XXXX not implemented yet */
|
printf("Propagate %p\n", cur->fun);
|
||||||
|
functor_propagate(cur->fun);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_ASSIGN:
|
||||||
|
functor_set(cur->fun, cur->val);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +173,9 @@ void schedule_simulate(void)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: schedule.cc,v $
|
* $Log: schedule.cc,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:39 steve
|
* Revision 1.1 2001/03/11 00:29:39 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,43 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: schedule.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
|
#ident "$Id: schedule.h,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
# include "pointers.h"
|
# include "pointers.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This causes a thread to be scheduled for execution. The schedule
|
||||||
|
* puts the event into the event queue after any existing events for a
|
||||||
|
* given time step. The delay is a relative time.
|
||||||
|
*/
|
||||||
extern void schedule_vthread(vthread_t thr, unsigned delay);
|
extern void schedule_vthread(vthread_t thr, unsigned delay);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a propagation event. The fun parameter points to the functor
|
||||||
|
* to have its output propagated, and the delay is the delay to
|
||||||
|
* schedule the propagation.
|
||||||
|
*/
|
||||||
extern void schedule_functor(vvp_ipoint_t fun, unsigned delay);
|
extern void schedule_functor(vvp_ipoint_t fun, unsigned delay);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an assignment event. The val passed here will be assigned to
|
||||||
|
* the specified input when the delay times out.
|
||||||
|
*/
|
||||||
|
extern void schedule_assign(vvp_ipoint_t fun, unsigned char val,
|
||||||
|
unsigned delay);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This runs the simulator. It runs until all the functors run out.
|
||||||
|
*/
|
||||||
extern void schedule_simulate(void);
|
extern void schedule_simulate(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: schedule.h,v $
|
* $Log: schedule.h,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:39 steve
|
* Revision 1.1 2001/03/11 00:29:39 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,14 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: vthread.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
|
#ident "$Id: vthread.cc,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
# include "codes.h"
|
# include "codes.h"
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
|
# include "functor.h"
|
||||||
|
# include <assert.h>
|
||||||
|
|
||||||
struct vthread_s {
|
struct vthread_s {
|
||||||
/* This is the program counter. */
|
/* This is the program counter. */
|
||||||
|
|
@ -59,13 +61,23 @@ void vthread_run(vthread_t thr)
|
||||||
|
|
||||||
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
|
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
printf("thread %p: %%assign\n");
|
printf("thread %p: %%assign\n", thr);
|
||||||
|
|
||||||
|
unsigned char bit_val = 3;
|
||||||
|
if ((cp->bit_idx & ~0x3) == 0x0) {
|
||||||
|
bit_val = cp->bit_idx&3;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("XXXX bit_idx out of range?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule_assign(cp->iptr, bit_val, cp->number);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool of_DELAY(vthread_t thr, vvp_code_t cp)
|
bool of_DELAY(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
printf("thread %p: %%delay %u\n", thr, cp->number);
|
printf("thread %p: %%delay %lu\n", thr, cp->number);
|
||||||
schedule_vthread(thr, cp->number);
|
schedule_vthread(thr, cp->number);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -83,12 +95,26 @@ bool of_NOOP(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
bool of_SET(vthread_t thr, vvp_code_t cp)
|
bool of_SET(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
printf("thread %p: %%set\n");
|
printf("thread %p: %%set %lu, %u\n", thr, cp->iptr, cp->bit_idx);
|
||||||
|
|
||||||
|
unsigned char bit_val = 3;
|
||||||
|
if ((cp->bit_idx & ~0x3) == 0x0) {
|
||||||
|
bit_val = cp->bit_idx&3;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("XXXX bit_idx out of range?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
functor_set(cp->iptr, bit_val);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vthread.cc,v $
|
* $Log: vthread.cc,v $
|
||||||
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
|
* Functor values and propagation.
|
||||||
|
*
|
||||||
* Revision 1.1 2001/03/11 00:29:39 steve
|
* Revision 1.1 2001/03/11 00:29:39 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue