Add fork and join instructions.
This commit is contained in:
parent
f6eb581aff
commit
386958f9a0
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* $Id: README.txt,v 1.10 2001/03/29 03:46:36 steve Exp $
|
* $Id: README.txt,v 1.11 2001/03/30 04:55:22 steve Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VVP SIMULATION ENGINE
|
VVP SIMULATION ENGINE
|
||||||
|
|
@ -29,7 +29,7 @@ semicolon that terminates a statement. Like so:
|
||||||
The semicolon is required, whether the comment is there or not.
|
The semicolon is required, whether the comment is there or not.
|
||||||
|
|
||||||
Statements may span multiple lines, as long as there is no text (other
|
Statements may span multiple lines, as long as there is no text (other
|
||||||
then the first character of a label) in the first column of hte
|
then the first character of a label) in the first column of the
|
||||||
continuation line.
|
continuation line.
|
||||||
|
|
||||||
HEADER SYNTAX
|
HEADER SYNTAX
|
||||||
|
|
@ -54,7 +54,7 @@ Labels and symbols consist of the characters:
|
||||||
a-z
|
a-z
|
||||||
A-Z
|
A-Z
|
||||||
0-9
|
0-9
|
||||||
.$_
|
.$_<>
|
||||||
|
|
||||||
Labels and symbols may not start with a digit or a '.', so that they
|
Labels and symbols may not start with a digit or a '.', so that they
|
||||||
are easily distinguished from keywords and numbers. A Label is a
|
are easily distinguished from keywords and numbers. A Label is a
|
||||||
|
|
@ -229,6 +229,25 @@ This statement creates a thread with a starting address at the
|
||||||
instruction given by <symbol>.
|
instruction given by <symbol>.
|
||||||
|
|
||||||
|
|
||||||
|
THREADS IN GENERAL:
|
||||||
|
|
||||||
|
Thread statements create the initial threads of a design. These
|
||||||
|
include the ``initial'' and ``always'' statements of the original
|
||||||
|
Verilog, and possibly some other synthetic threads for various
|
||||||
|
purposes. It is also possible to create transient threads from
|
||||||
|
behavioral code. These are needed to support such constructs as
|
||||||
|
fork/join, named blocks and task activation.
|
||||||
|
|
||||||
|
A transient thread is created with a %fork instruction. When a
|
||||||
|
transient thread is created this way, the operand to the %fork gives
|
||||||
|
the starting address, and the new thread is said to be a child of the
|
||||||
|
forking thread. The children of a thread are pushed onto a stack of
|
||||||
|
children.
|
||||||
|
|
||||||
|
A transient thread is reaped with a %join instruction. %join waits for
|
||||||
|
the top thread in the stack of children to complete, then
|
||||||
|
continues. It is an error to %join when there are no children.
|
||||||
|
|
||||||
TRUTH TABLES
|
TRUTH TABLES
|
||||||
|
|
||||||
The logic that a functor represents is expressed as a truth table. The
|
The logic that a functor represents is expressed as a truth table. The
|
||||||
|
|
@ -425,6 +444,17 @@ becomes:
|
||||||
a .var "a", 0, 0;
|
a .var "a", 0, 0;
|
||||||
|
|
||||||
|
|
||||||
|
* named events
|
||||||
|
|
||||||
|
Events in general are implemented as functors, but named events in
|
||||||
|
partinular have no inputs and only the event output. The way to
|
||||||
|
generate code for these is like so:
|
||||||
|
|
||||||
|
a .event "name";
|
||||||
|
|
||||||
|
This creates a functor and makes it into a mode-2 functor. Then the
|
||||||
|
trigger statement, "-> a", cause a ``%set a, 0;'' statement be
|
||||||
|
generated. This is sufficient to trigger the event.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
|
|
|
||||||
|
|
@ -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: codes.h,v 1.7 2001/03/26 04:00:39 steve Exp $"
|
#ident "$Id: codes.h,v 1.8 2001/03/30 04:55:22 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,10 +39,12 @@ extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
|
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_END(vthread_t thr, vvp_code_t code);
|
extern bool of_END(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_FORK(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_INV(vthread_t thr, vvp_code_t code);
|
extern bool of_INV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_MOV(vthread_t thr, vvp_code_t code);
|
extern bool of_MOV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -93,6 +95,9 @@ extern void codespace_dump(FILE*fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: codes.h,v $
|
* $Log: codes.h,v $
|
||||||
|
* Revision 1.8 2001/03/30 04:55:22 steve
|
||||||
|
* Add fork and join instructions.
|
||||||
|
*
|
||||||
* Revision 1.7 2001/03/26 04:00:39 steve
|
* Revision 1.7 2001/03/26 04:00:39 steve
|
||||||
* Add the .event statement and the %wait instruction.
|
* Add the .event statement and the %wait instruction.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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.18 2001/03/29 03:46:36 steve Exp $"
|
#ident "$Id: compile.cc,v 1.19 2001/03/30 04:55:22 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "compile.h"
|
# include "compile.h"
|
||||||
|
|
@ -69,10 +69,12 @@ const static struct opcode_table_s opcode_table[] = {
|
||||||
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
|
{ "%fork", of_FORK, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
|
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||||
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
|
|
@ -685,6 +687,9 @@ void compile_dump(FILE*fd)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: compile.cc,v $
|
* $Log: compile.cc,v $
|
||||||
|
* Revision 1.19 2001/03/30 04:55:22 steve
|
||||||
|
* Add fork and join instructions.
|
||||||
|
*
|
||||||
* Revision 1.18 2001/03/29 03:46:36 steve
|
* Revision 1.18 2001/03/29 03:46:36 steve
|
||||||
* Support named events as mode 2 functors.
|
* Support named events as mode 2 functors.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
:vpi_module "system";
|
||||||
|
|
||||||
|
; 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
|
||||||
|
|
||||||
|
; This sample demonstrates the behavior of %fork and %join.
|
||||||
|
|
||||||
|
S_main .scope "main";
|
||||||
|
|
||||||
|
child %vpi_call "$display", "I'm a child";
|
||||||
|
%end;
|
||||||
|
|
||||||
|
parent %fork child;
|
||||||
|
%vpi_call "$display", "I'm a parent";
|
||||||
|
%join;
|
||||||
|
%vpi_call "$display", "reaped";
|
||||||
|
%end;
|
||||||
|
|
||||||
|
.thread parent;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* $Id: opcodes.txt,v 1.6 2001/03/26 04:00:39 steve Exp $
|
* $Id: opcodes.txt,v 1.7 2001/03/30 04:55:22 steve Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,7 +9,9 @@
|
||||||
EXECUTABLE INSTRUCTION OPCODES
|
EXECUTABLE INSTRUCTION OPCODES
|
||||||
|
|
||||||
Instruction opcodes all start with a % character and have 0 or more
|
Instruction opcodes all start with a % character and have 0 or more
|
||||||
operands. In no case are there more then 3 operands.
|
operands. In no case are there more then 3 operands. This chapter
|
||||||
|
describes the specific behavior of each opcode, in hopefully enough
|
||||||
|
detail that its complete effect can be predicted.
|
||||||
|
|
||||||
|
|
||||||
* %assign <var-label>, <delay>, <bit>
|
* %assign <var-label>, <delay>, <bit>
|
||||||
|
|
@ -68,9 +70,29 @@ future to reschedule, and is >= 0. If the %delay is zero, then the
|
||||||
thread yields the processor for another thread, but will be resumed in
|
thread yields the processor for another thread, but will be resumed in
|
||||||
the current time step.
|
the current time step.
|
||||||
|
|
||||||
|
* %fork <code-label>
|
||||||
|
|
||||||
|
This instruction is similar to %jmp, except that it creates a new
|
||||||
|
thread to start executing at the specified address. The new thread is
|
||||||
|
created and pushed onto the child stack. It is also marked runnable,
|
||||||
|
but is not necessarily started until the current thread yields.
|
||||||
|
|
||||||
|
The %fork instruction has no effect other then to push a child thread.
|
||||||
|
|
||||||
|
See also %join.
|
||||||
|
|
||||||
|
|
||||||
* %inv <bit>, <wid>
|
* %inv <bit>, <wid>
|
||||||
|
|
||||||
Perform a bitwise invert of the vector starting at <bit>.
|
Perform a bitwise invert of the vector starting at <bit>. The result
|
||||||
|
replaces the input. Invert means the following, independently for each
|
||||||
|
bit:
|
||||||
|
|
||||||
|
0 --> 1
|
||||||
|
1 --> 0
|
||||||
|
x --> x
|
||||||
|
z --> x
|
||||||
|
|
||||||
|
|
||||||
* %jmp <code-label>
|
* %jmp <code-label>
|
||||||
|
|
||||||
|
|
@ -87,6 +109,21 @@ values in the part after the /, the jump is taken. For example:
|
||||||
|
|
||||||
will jump to T_label if bit 8 is x or z.
|
will jump to T_label if bit 8 is x or z.
|
||||||
|
|
||||||
|
* %join
|
||||||
|
|
||||||
|
This is the partner to %fork. This instruction causes the thread to
|
||||||
|
wait for the top thread in the child stack to terminate, then
|
||||||
|
continues. It has no effect in the current thread other then to wait
|
||||||
|
until the top child is cleared.
|
||||||
|
|
||||||
|
It is an error to execute %join if there are no children in the child
|
||||||
|
stack. If a child thread terminates before this instruction is called,
|
||||||
|
it remains in the stack as a zombie until the %join reaps it.
|
||||||
|
|
||||||
|
If a thread terminates (i.e. executes %end) all its children are
|
||||||
|
terminated as well.
|
||||||
|
|
||||||
|
|
||||||
* %load <bit>, <functor-label>
|
* %load <bit>, <functor-label>
|
||||||
|
|
||||||
This instruction loads a value from the given functor output into the
|
This instruction loads a value from the given functor output into the
|
||||||
|
|
|
||||||
|
|
@ -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: vthread.cc,v 1.13 2001/03/29 03:46:36 steve Exp $"
|
#ident "$Id: vthread.cc,v 1.14 2001/03/30 04:55:22 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
|
|
@ -34,6 +34,10 @@ struct vthread_s {
|
||||||
unsigned long pc;
|
unsigned long pc;
|
||||||
unsigned char *bits;
|
unsigned char *bits;
|
||||||
unsigned short nbits;
|
unsigned short nbits;
|
||||||
|
/* This points to the top (youngest) child of the thread. */
|
||||||
|
struct vthread_s*child;
|
||||||
|
/* This is set if the parent is waiting for me to end. */
|
||||||
|
struct vthread_s*reaper;
|
||||||
/* This is used for keeping wait queues. */
|
/* This is used for keeping wait queues. */
|
||||||
struct vthread_s*next;
|
struct vthread_s*next;
|
||||||
};
|
};
|
||||||
|
|
@ -78,6 +82,8 @@ vthread_t v_newthread(unsigned long pc)
|
||||||
thr->pc = pc;
|
thr->pc = pc;
|
||||||
thr->bits = (unsigned char*)malloc(16);
|
thr->bits = (unsigned char*)malloc(16);
|
||||||
thr->nbits = 16*4;
|
thr->nbits = 16*4;
|
||||||
|
thr->child = 0;
|
||||||
|
thr->reaper = 0;
|
||||||
thr->next = 0;
|
thr->next = 0;
|
||||||
|
|
||||||
thr_put_bit(thr, 0, 0);
|
thr_put_bit(thr, 0, 0);
|
||||||
|
|
@ -87,6 +93,13 @@ vthread_t v_newthread(unsigned long pc)
|
||||||
return thr;
|
return thr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vthread_reap(vthread_t thr)
|
||||||
|
{
|
||||||
|
assert(thr->next == 0);
|
||||||
|
assert(thr->child == 0);
|
||||||
|
free(thr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function runs a thread by fetching an instruction,
|
* This function runs a thread by fetching an instruction,
|
||||||
|
|
@ -169,10 +182,21 @@ bool of_DELAY(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
bool of_END(vthread_t thr, vvp_code_t cp)
|
bool of_END(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
//printf("thread %p: %%end\n", thr);
|
if (thr->reaper)
|
||||||
|
schedule_vthread(thr->reaper, 0);
|
||||||
|
thr->reaper = thr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool of_FORK(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
vthread_t child = v_newthread(cp->cptr);
|
||||||
|
child->child = thr->child;
|
||||||
|
thr->child = child;
|
||||||
|
schedule_vthread(child, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool of_INV(vthread_t thr, vvp_code_t cp)
|
bool of_INV(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
assert(cp->bit_idx1 >= 4);
|
assert(cp->bit_idx1 >= 4);
|
||||||
|
|
@ -214,6 +238,19 @@ bool of_JMP0XZ(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
assert(thr->child);
|
||||||
|
if (thr->child->reaper == thr->child) {
|
||||||
|
vthread_reap(thr->child);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(thr->child->reaper == 0);
|
||||||
|
thr->child->reaper = thr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool of_LOAD(vthread_t thr, vvp_code_t cp)
|
bool of_LOAD(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
assert(cp->bit_idx1 >= 4);
|
assert(cp->bit_idx1 >= 4);
|
||||||
|
|
@ -278,6 +315,9 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vthread.cc,v $
|
* $Log: vthread.cc,v $
|
||||||
|
* Revision 1.14 2001/03/30 04:55:22 steve
|
||||||
|
* Add fork and join instructions.
|
||||||
|
*
|
||||||
* Revision 1.13 2001/03/29 03:46:36 steve
|
* Revision 1.13 2001/03/29 03:46:36 steve
|
||||||
* Support named events as mode 2 functors.
|
* Support named events as mode 2 functors.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue