Add compiler and the start of vvp support for ->>
This commit is contained in:
parent
753bf516d6
commit
60a77b08d2
15
Statement.cc
15
Statement.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -416,8 +416,8 @@ PReturn::~PReturn()
|
||||||
delete expr_;
|
delete expr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&e)
|
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev)
|
||||||
: package_(pkg), event_(e)
|
: package_(pkg), event_(ev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,6 +425,15 @@ PTrigger::~PTrigger()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNBTrigger::PNBTrigger(const pform_name_t&ev, PExpr*dly)
|
||||||
|
: event_(ev), dly_(dly)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PNBTrigger::~PNBTrigger()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PWhile::PWhile(PExpr*ex, Statement*st)
|
PWhile::PWhile(PExpr*ex, Statement*st)
|
||||||
: cond_(ex), statement_(st)
|
: cond_(ex), statement_(st)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
13
Statement.h
13
Statement.h
|
|
@ -590,6 +590,19 @@ class PTrigger : public Statement {
|
||||||
pform_name_t event_;
|
pform_name_t event_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PNBTrigger : public Statement {
|
||||||
|
public:
|
||||||
|
explicit PNBTrigger(const pform_name_t&ev, PExpr*dly);
|
||||||
|
~PNBTrigger();
|
||||||
|
|
||||||
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||||
|
virtual void dump(ostream&out, unsigned ind) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pform_name_t event_;
|
||||||
|
PExpr*dly_;
|
||||||
|
};
|
||||||
|
|
||||||
class PWhile : public Statement {
|
class PWhile : public Statement {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -1300,6 +1300,13 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
|
||||||
<< "// " << get_fileline() << endl;
|
<< "// " << get_fileline() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEvNBTrig::dump(ostream&o, unsigned ind) const
|
||||||
|
{
|
||||||
|
o << setw(ind) << "" << "->> " ;
|
||||||
|
if (dly_) o << "#" << *dly_ << " ";
|
||||||
|
o << event_->name() << "; " << "// " << get_fileline() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void NetEvWait::dump(ostream&o, unsigned ind) const
|
void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "";
|
o << setw(ind) << "";
|
||||||
|
|
|
||||||
32
elaborate.cc
32
elaborate.cc
|
|
@ -5780,6 +5780,38 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetProc* PNBTrigger::elaborate(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
assert(scope);
|
||||||
|
|
||||||
|
NetNet* sig = 0;
|
||||||
|
const NetExpr*par = 0;
|
||||||
|
NetEvent* eve = 0;
|
||||||
|
|
||||||
|
NetScope*found_in = symbol_search(this, des, scope, event_,
|
||||||
|
sig, par, eve);
|
||||||
|
|
||||||
|
if (found_in == 0) {
|
||||||
|
cerr << get_fileline() << ": error: event <" << event_ << ">"
|
||||||
|
<< " not found." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eve == 0) {
|
||||||
|
cerr << get_fileline() << ": error: <" << event_ << ">"
|
||||||
|
<< " is not a named event." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr*dly = 0;
|
||||||
|
if (dly_) dly = elab_and_eval(des, scope, dly_, -1);
|
||||||
|
NetEvNBTrig*trig = new NetEvNBTrig(eve, dly);
|
||||||
|
trig->set_line(*this);
|
||||||
|
return trig;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The while loop is fairly directly represented in the netlist.
|
* The while loop is fairly directly represented in the netlist.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
7
emit.cc
7
emit.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -389,6 +389,11 @@ bool NetEvTrig::emit_proc(struct target_t*tgt) const
|
||||||
return tgt->proc_trigger(this);
|
return tgt->proc_trigger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetEvNBTrig::emit_proc(struct target_t*tgt) const
|
||||||
|
{
|
||||||
|
return tgt->proc_nb_trigger(this);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetEvWait::emit_proc(struct target_t*tgt) const
|
bool NetEvWait::emit_proc(struct target_t*tgt) const
|
||||||
{
|
{
|
||||||
return tgt->proc_wait(this);
|
return tgt->proc_wait(this);
|
||||||
|
|
|
||||||
|
|
@ -426,6 +426,7 @@ typedef enum ivl_statement_type_e {
|
||||||
IVL_ST_FORK_JOIN_ANY = 28,
|
IVL_ST_FORK_JOIN_ANY = 28,
|
||||||
IVL_ST_FORK_JOIN_NONE = 29,
|
IVL_ST_FORK_JOIN_NONE = 29,
|
||||||
IVL_ST_FREE = 26,
|
IVL_ST_FREE = 26,
|
||||||
|
IVL_ST_NB_TRIGGER = 31,
|
||||||
IVL_ST_RELEASE = 17,
|
IVL_ST_RELEASE = 17,
|
||||||
IVL_ST_REPEAT = 18,
|
IVL_ST_REPEAT = 18,
|
||||||
IVL_ST_STASK = 19,
|
IVL_ST_STASK = 19,
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,7 @@ TU [munpf]
|
||||||
"^~" { return K_NXOR; }
|
"^~" { return K_NXOR; }
|
||||||
"~&" { return K_NAND; }
|
"~&" { return K_NAND; }
|
||||||
"->" { return K_TRIGGER; }
|
"->" { return K_TRIGGER; }
|
||||||
|
"->>" { return K_NB_TRIGGER; }
|
||||||
"+:" { return K_PO_POS; }
|
"+:" { return K_PO_POS; }
|
||||||
"-:" { return K_PO_NEG; }
|
"-:" { return K_PO_NEG; }
|
||||||
"<+" { return K_CONTRIBUTE; }
|
"<+" { return K_CONTRIBUTE; }
|
||||||
|
|
|
||||||
35
net_event.cc
35
net_event.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -264,6 +264,39 @@ const NetEvent* NetEvTrig::event() const
|
||||||
return event_;
|
return event_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEvNBTrig::NetEvNBTrig(NetEvent*ev, NetExpr*dly)
|
||||||
|
: event_(ev), dly_(dly)
|
||||||
|
{
|
||||||
|
enext_ = event_->nb_trig_;
|
||||||
|
event_->nb_trig_ = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetEvNBTrig::~NetEvNBTrig()
|
||||||
|
{
|
||||||
|
if (event_->nb_trig_ == this) {
|
||||||
|
event_->nb_trig_ = enext_;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
NetEvNBTrig*cur = event_->nb_trig_;
|
||||||
|
while (cur->enext_ != this) {
|
||||||
|
assert(cur->enext_);
|
||||||
|
cur = cur->enext_;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->enext_ = this->enext_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetExpr* NetEvNBTrig::delay() const
|
||||||
|
{
|
||||||
|
return dly_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetEvent* NetEvNBTrig::event() const
|
||||||
|
{
|
||||||
|
return event_;
|
||||||
|
}
|
||||||
|
|
||||||
NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
|
NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
|
||||||
edge_t t, unsigned p)
|
edge_t t, unsigned p)
|
||||||
: NetNode(s, n, p), event_(tgt), edge_(t)
|
: NetNode(s, n, p), event_(tgt), edge_(t)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -475,6 +475,11 @@ NexusSet* NetEvTrig::nex_input(bool, bool, bool) const
|
||||||
return new NexusSet;
|
return new NexusSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NexusSet* NetEvNBTrig::nex_input(bool, bool, bool) const
|
||||||
|
{
|
||||||
|
return new NexusSet;
|
||||||
|
}
|
||||||
|
|
||||||
NexusSet* NetEvWait::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
NexusSet* NetEvWait::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
||||||
{
|
{
|
||||||
NexusSet*result = new NexusSet;
|
NexusSet*result = new NexusSet;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2017 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -134,6 +134,10 @@ void NetEvTrig::nex_output(NexusSet&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEvNBTrig::nex_output(NexusSet&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void NetEvWait::nex_output(NexusSet&out)
|
void NetEvWait::nex_output(NexusSet&out)
|
||||||
{
|
{
|
||||||
if (statement_) statement_->nex_output(out);
|
if (statement_) statement_->nex_output(out);
|
||||||
|
|
|
||||||
|
|
@ -3260,6 +3260,13 @@ bool NetEvTrig::check_synth(ivl_process_type_t pr_type,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetEvNBTrig::check_synth(ivl_process_type_t pr_type,
|
||||||
|
const NetScope* /* scope */ ) const
|
||||||
|
{
|
||||||
|
print_synth_warning(this, "A non-blocking event trigger", pr_type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// The delay check above has already marked this as an error.
|
// The delay check above has already marked this as an error.
|
||||||
bool NetEvWait::check_synth(ivl_process_type_t pr_type,
|
bool NetEvWait::check_synth(ivl_process_type_t pr_type,
|
||||||
const NetScope* scope) const
|
const NetScope* scope) const
|
||||||
|
|
|
||||||
35
netlist.h
35
netlist.h
|
|
@ -73,6 +73,7 @@ class NetFuncDef;
|
||||||
class NetRamDq;
|
class NetRamDq;
|
||||||
class NetTaskDef;
|
class NetTaskDef;
|
||||||
class NetEvTrig;
|
class NetEvTrig;
|
||||||
|
class NetEvNBTrig;
|
||||||
class NetEvWait;
|
class NetEvWait;
|
||||||
class PClass;
|
class PClass;
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
|
@ -3346,6 +3347,11 @@ class NetDoWhile : public NetProc {
|
||||||
* turn awakens the waiting threads. Each NetEvTrig object references
|
* turn awakens the waiting threads. Each NetEvTrig object references
|
||||||
* exactly one event object.
|
* exactly one event object.
|
||||||
*
|
*
|
||||||
|
* The NetEvNBTrig class represents non-blocking trigger statements.
|
||||||
|
* Executing this statement causes the referenced event to be triggered
|
||||||
|
* at some time in the future, which in turn awakens the waiting threads.
|
||||||
|
* Each NetEvNBTrig object references exactly one event object.
|
||||||
|
*
|
||||||
* The NetEvProbe class is the structural equivalent of the NetEvTrig,
|
* The NetEvProbe class is the structural equivalent of the NetEvTrig,
|
||||||
* in that it is a node and watches bit values that it receives. It
|
* in that it is a node and watches bit values that it receives. It
|
||||||
* checks for edges then if appropriate triggers the associated
|
* checks for edges then if appropriate triggers the associated
|
||||||
|
|
@ -3358,6 +3364,7 @@ class NetEvent : public LineInfo {
|
||||||
friend class NetScope;
|
friend class NetScope;
|
||||||
friend class NetEvProbe;
|
friend class NetEvProbe;
|
||||||
friend class NetEvTrig;
|
friend class NetEvTrig;
|
||||||
|
friend class NetEvNBTrig;
|
||||||
friend class NetEvWait;
|
friend class NetEvWait;
|
||||||
friend class NetEEvent;
|
friend class NetEEvent;
|
||||||
|
|
||||||
|
|
@ -3416,6 +3423,9 @@ class NetEvent : public LineInfo {
|
||||||
// Use these methods to list the triggers attached to me.
|
// Use these methods to list the triggers attached to me.
|
||||||
NetEvTrig* trig_;
|
NetEvTrig* trig_;
|
||||||
|
|
||||||
|
// Use these methods to list the non-blocking triggers attached to me.
|
||||||
|
NetEvNBTrig* nb_trig_;
|
||||||
|
|
||||||
// Use This member to count references by NetEvWait objects.
|
// Use This member to count references by NetEvWait objects.
|
||||||
unsigned waitref_;
|
unsigned waitref_;
|
||||||
struct wcell_ {
|
struct wcell_ {
|
||||||
|
|
@ -3455,6 +3465,31 @@ class NetEvTrig : public NetProc {
|
||||||
NetEvTrig*enext_;
|
NetEvTrig*enext_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NetEvNBTrig : public NetProc {
|
||||||
|
|
||||||
|
friend class NetEvent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NetEvNBTrig(NetEvent*tgt, NetExpr*dly);
|
||||||
|
~NetEvNBTrig();
|
||||||
|
|
||||||
|
const NetExpr*delay() const;
|
||||||
|
const NetEvent*event() const;
|
||||||
|
|
||||||
|
virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false,
|
||||||
|
bool nested_func = false) const;
|
||||||
|
virtual void nex_output(NexusSet&);
|
||||||
|
virtual bool emit_proc(struct target_t*) const;
|
||||||
|
virtual void dump(ostream&, unsigned ind) const;
|
||||||
|
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetEvent*event_;
|
||||||
|
NetExpr*dly_;
|
||||||
|
// This is used to place me in the NetEvents lists of triggers.
|
||||||
|
NetEvNBTrig*enext_;
|
||||||
|
};
|
||||||
|
|
||||||
class NetEvWait : public NetProc {
|
class NetEvWait : public NetProc {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
29
parse.y
29
parse.y
|
|
@ -478,7 +478,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%token K_CONTRIBUTE
|
%token K_CONTRIBUTE
|
||||||
%token K_PO_POS K_PO_NEG K_POW
|
%token K_PO_POS K_PO_NEG K_POW
|
||||||
%token K_PSTAR K_STARP K_DOTSTAR
|
%token K_PSTAR K_STARP K_DOTSTAR
|
||||||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER K_LEQUIV
|
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER K_NB_TRIGGER K_LEQUIV
|
||||||
%token K_SCOPE_RES
|
%token K_SCOPE_RES
|
||||||
%token K_edge_descriptor
|
%token K_edge_descriptor
|
||||||
|
|
||||||
|
|
@ -692,7 +692,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
|
|
||||||
%token K_TAND
|
%token K_TAND
|
||||||
%nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
%nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||||
%nonassoc K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
%nonassoc K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ K_NB_TRIGGER
|
||||||
%right K_TRIGGER K_LEQUIV
|
%right K_TRIGGER K_LEQUIV
|
||||||
%right '?' ':' K_inside
|
%right '?' ':' K_inside
|
||||||
%left K_LOR
|
%left K_LOR
|
||||||
|
|
@ -6716,16 +6716,37 @@ statement_item /* This is roughly statement_item in the LRM */
|
||||||
}
|
}
|
||||||
| K_TRIGGER hierarchy_identifier ';'
|
| K_TRIGGER hierarchy_identifier ';'
|
||||||
{ PTrigger*tmp = pform_new_trigger(@2, 0, *$2);
|
{ PTrigger*tmp = pform_new_trigger(@2, 0, *$2);
|
||||||
FILE_NAME(tmp, @1);
|
|
||||||
delete $2;
|
delete $2;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_TRIGGER PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
|
| K_TRIGGER PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
|
||||||
{ PTrigger*tmp = pform_new_trigger(@4, $2, *$4);
|
{ PTrigger*tmp = pform_new_trigger(@4, $2, *$4);
|
||||||
FILE_NAME(tmp, @1);
|
|
||||||
delete $4;
|
delete $4;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
/* FIXME: Does this need support for package resolution like above? */
|
||||||
|
| K_NB_TRIGGER hierarchy_identifier ';'
|
||||||
|
{ PNBTrigger*tmp = pform_new_nb_trigger(@2, 0, *$2);
|
||||||
|
delete $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_NB_TRIGGER delay1 hierarchy_identifier ';'
|
||||||
|
{ PNBTrigger*tmp = pform_new_nb_trigger(@3, $2, *$3);
|
||||||
|
delete $3;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_NB_TRIGGER event_control hierarchy_identifier ';'
|
||||||
|
{ PNBTrigger*tmp = pform_new_nb_trigger(@3, 0, *$3);
|
||||||
|
delete $3;
|
||||||
|
$$ = tmp;
|
||||||
|
yywarn(@1, "Sorry: ->> with event control is not currently supported.");
|
||||||
|
}
|
||||||
|
| K_NB_TRIGGER K_repeat '(' expression ')' event_control hierarchy_identifier ';'
|
||||||
|
{ PNBTrigger*tmp = pform_new_nb_trigger(@7, 0, *$7);
|
||||||
|
delete $7;
|
||||||
|
$$ = tmp;
|
||||||
|
yywarn(@1, "Sorry: ->> with repeat event control is not currently supported.");
|
||||||
|
}
|
||||||
|
|
||||||
| procedural_assertion_statement { $$ = $1; }
|
| procedural_assertion_statement { $$ = $1; }
|
||||||
|
|
||||||
|
|
|
||||||
18
pform.cc
18
pform.cc
|
|
@ -752,6 +752,24 @@ PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNBTrigger* pform_new_nb_trigger(const struct vlltype&loc,
|
||||||
|
const list<PExpr*>*dly,
|
||||||
|
const pform_name_t&name)
|
||||||
|
{
|
||||||
|
if (gn_system_verilog())
|
||||||
|
check_potential_imports(loc, name.front().name, false);
|
||||||
|
|
||||||
|
PExpr*tmp_dly = 0;
|
||||||
|
if (dly) {
|
||||||
|
assert(dly->size() == 1);
|
||||||
|
tmp_dly = dly->front();
|
||||||
|
}
|
||||||
|
|
||||||
|
PNBTrigger*tmp = new PNBTrigger(name, tmp_dly);
|
||||||
|
FILE_NAME(tmp, loc);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
PGenerate* pform_parent_generate(void)
|
PGenerate* pform_parent_generate(void)
|
||||||
{
|
{
|
||||||
return pform_cur_generate;
|
return pform_cur_generate;
|
||||||
|
|
|
||||||
3
pform.h
3
pform.h
|
|
@ -250,6 +250,9 @@ extern PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&nam
|
||||||
|
|
||||||
extern PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg,
|
extern PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg,
|
||||||
const pform_name_t&name);
|
const pform_name_t&name);
|
||||||
|
extern PNBTrigger* pform_new_nb_trigger(const struct vlltype&loc,
|
||||||
|
const list<PExpr*>*dly,
|
||||||
|
const pform_name_t&name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enter/exit name scopes. The push_scope function pushes the scope
|
* Enter/exit name scopes. The push_scope function pushes the scope
|
||||||
|
|
|
||||||
|
|
@ -1263,6 +1263,13 @@ void PTrigger::dump(ostream&out, unsigned ind) const
|
||||||
out << setw(ind) << "" << "-> " << event_ << ";" << endl;
|
out << setw(ind) << "" << "-> " << event_ << ";" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PNBTrigger::dump(ostream&out, unsigned ind) const
|
||||||
|
{
|
||||||
|
out << setw(ind) << "" << "->> ";
|
||||||
|
if (dly_) out << "#" << *dly_ << " ";
|
||||||
|
out << event_ << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void PWhile::dump(ostream&out, unsigned ind) const
|
void PWhile::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
out << setw(ind) << "" << "while (" << *cond_ << ")" << endl;
|
out << setw(ind) << "" << "while (" << *cond_ << ")" << endl;
|
||||||
|
|
|
||||||
22
t-dll-api.cc
22
t-dll-api.cc
|
|
@ -2834,6 +2834,9 @@ extern "C" ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net)
|
||||||
case IVL_ST_DELAYX:
|
case IVL_ST_DELAYX:
|
||||||
return net->u_.delayx_.expr;
|
return net->u_.delayx_.expr;
|
||||||
|
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
|
return net->u_.wait_.delay;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2864,12 +2867,15 @@ extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net)
|
||||||
case IVL_ST_ASSIGN_NB:
|
case IVL_ST_ASSIGN_NB:
|
||||||
return net->u_.assign_.nevent;
|
return net->u_.assign_.nevent;
|
||||||
|
|
||||||
case IVL_ST_WAIT:
|
case IVL_ST_NB_TRIGGER:
|
||||||
return net->u_.wait_.nevent;
|
return 1;
|
||||||
|
|
||||||
case IVL_ST_TRIGGER:
|
case IVL_ST_TRIGGER:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case IVL_ST_WAIT:
|
||||||
|
return net->u_.wait_.nevent;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
@ -2887,6 +2893,14 @@ extern "C" ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx)
|
||||||
else
|
else
|
||||||
return net->u_.assign_.events[idx];
|
return net->u_.assign_.events[idx];
|
||||||
|
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
|
assert(idx == 0);
|
||||||
|
return net->u_.wait_.event;
|
||||||
|
|
||||||
|
case IVL_ST_TRIGGER:
|
||||||
|
assert(idx == 0);
|
||||||
|
return net->u_.wait_.event;
|
||||||
|
|
||||||
case IVL_ST_WAIT:
|
case IVL_ST_WAIT:
|
||||||
assert(idx < net->u_.wait_.nevent);
|
assert(idx < net->u_.wait_.nevent);
|
||||||
if (net->u_.wait_.nevent == 1)
|
if (net->u_.wait_.nevent == 1)
|
||||||
|
|
@ -2894,10 +2908,6 @@ extern "C" ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx)
|
||||||
else
|
else
|
||||||
return net->u_.wait_.events[idx];
|
return net->u_.wait_.events[idx];
|
||||||
|
|
||||||
case IVL_ST_TRIGGER:
|
|
||||||
assert(idx == 0);
|
|
||||||
return net->u_.wait_.event;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -825,6 +825,38 @@ bool dll_target::proc_trigger(const NetEvTrig*net)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dll_target::proc_nb_trigger(const NetEvNBTrig*net)
|
||||||
|
{
|
||||||
|
assert(stmt_cur_);
|
||||||
|
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||||
|
FILE_NAME(stmt_cur_, net);
|
||||||
|
|
||||||
|
stmt_cur_->type_ = IVL_ST_NB_TRIGGER;
|
||||||
|
stmt_cur_->u_.wait_.nevent = 1;
|
||||||
|
stmt_cur_->u_.wait_.delay = 0;
|
||||||
|
|
||||||
|
if (const NetExpr*expr = net->delay()) {
|
||||||
|
assert(expr_ == 0);
|
||||||
|
expr->expr_scan(this);
|
||||||
|
stmt_cur_->u_.wait_.delay = expr_;
|
||||||
|
expr_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate the event by name. Save the ivl_event_t in the
|
||||||
|
statement so that the generator can find it easily. */
|
||||||
|
const NetEvent*ev = net->event();
|
||||||
|
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
|
||||||
|
const char*ename = ivl_event_basename(ev_scope->event_[idx]);
|
||||||
|
if (strcmp(ev->name(), ename) == 0) {
|
||||||
|
stmt_cur_->u_.wait_.event = ev_scope->event_[idx];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
t-dll.h
4
t-dll.h
|
|
@ -128,6 +128,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||||
void proc_repeat(const NetRepeat*);
|
void proc_repeat(const NetRepeat*);
|
||||||
void proc_stask(const NetSTask*);
|
void proc_stask(const NetSTask*);
|
||||||
bool proc_trigger(const NetEvTrig*);
|
bool proc_trigger(const NetEvTrig*);
|
||||||
|
bool proc_nb_trigger(const NetEvNBTrig*);
|
||||||
void proc_utask(const NetUTask*);
|
void proc_utask(const NetUTask*);
|
||||||
bool proc_wait(const NetEvWait*);
|
bool proc_wait(const NetEvWait*);
|
||||||
void proc_while(const NetWhile*);
|
void proc_while(const NetWhile*);
|
||||||
|
|
@ -863,13 +864,14 @@ struct ivl_statement_s {
|
||||||
ivl_scope_t def;
|
ivl_scope_t def;
|
||||||
} utask_;
|
} utask_;
|
||||||
|
|
||||||
struct { /* IVL_ST_TRIGGER IVL_ST_WAIT */
|
struct { /* IVL_ST_TRIGGER IVL_ST_NB_TRIGGER IVL_ST_WAIT */
|
||||||
unsigned needs_t0_trigger;
|
unsigned needs_t0_trigger;
|
||||||
unsigned nevent;
|
unsigned nevent;
|
||||||
union {
|
union {
|
||||||
ivl_event_t event;
|
ivl_event_t event;
|
||||||
ivl_event_t*events;
|
ivl_event_t*events;
|
||||||
};
|
};
|
||||||
|
ivl_expr_t delay;
|
||||||
ivl_statement_t stmt_;
|
ivl_statement_t stmt_;
|
||||||
} wait_;
|
} wait_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
|
* Copyright (c) 1998-2021 Stephen Williams <steve@icarus.com>
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -424,6 +424,13 @@ bool target_t::proc_trigger(const NetEvTrig*tr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool target_t::proc_nb_trigger(const NetEvNBTrig*tr)
|
||||||
|
{
|
||||||
|
cerr << tr->get_fileline() << ": error: target (" << typeid(*this).name()
|
||||||
|
<< "): Unhandled non-blocking event trigger." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void target_t::proc_stask(const NetSTask*)
|
void target_t::proc_stask(const NetSTask*)
|
||||||
{
|
{
|
||||||
cerr << "target (" << typeid(*this).name() << "): "
|
cerr << "target (" << typeid(*this).name() << "): "
|
||||||
|
|
|
||||||
3
target.h
3
target.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_target_H
|
#ifndef IVL_target_H
|
||||||
#define IVL_target_H
|
#define IVL_target_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -143,6 +143,7 @@ struct target_t {
|
||||||
virtual bool proc_release(const NetRelease*);
|
virtual bool proc_release(const NetRelease*);
|
||||||
virtual void proc_repeat(const NetRepeat*);
|
virtual void proc_repeat(const NetRepeat*);
|
||||||
virtual bool proc_trigger(const NetEvTrig*);
|
virtual bool proc_trigger(const NetEvTrig*);
|
||||||
|
virtual bool proc_nb_trigger(const NetEvNBTrig*);
|
||||||
virtual void proc_stask(const NetSTask*);
|
virtual void proc_stask(const NetSTask*);
|
||||||
virtual void proc_utask(const NetUTask*);
|
virtual void proc_utask(const NetUTask*);
|
||||||
virtual bool proc_wait(const NetEvWait*);
|
virtual bool proc_wait(const NetEvWait*);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2004-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -271,6 +271,39 @@ static void show_stmt_trigger(ivl_statement_t net, unsigned ind)
|
||||||
fprintf(out, ";\n");
|
fprintf(out, ";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A non-blocking trigger statement is the "->> name;" syntax in Verilog,
|
||||||
|
* where a non-blocking trigger signal is sent to a named event. The trigger
|
||||||
|
* statement is actually a very simple object.
|
||||||
|
*/
|
||||||
|
static void show_stmt_nb_trigger(ivl_statement_t net, unsigned ind)
|
||||||
|
{
|
||||||
|
unsigned cnt = ivl_stmt_nevent(net);
|
||||||
|
unsigned idx;
|
||||||
|
|
||||||
|
fprintf(out, "%*s->>", ind, "");
|
||||||
|
|
||||||
|
ivl_expr_t delay = ivl_stmt_delay_expr(net);
|
||||||
|
if (delay) {
|
||||||
|
fprintf(out, " #(");
|
||||||
|
show_expression(ivl_stmt_delay_expr(net), ind+4);
|
||||||
|
fprintf(out, ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||||
|
ivl_event_t event = ivl_stmt_events(net, idx);
|
||||||
|
fprintf(out, " %s", ivl_event_basename(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The compiler should make exactly one target event, so if we
|
||||||
|
find more or less, then print some error text. */
|
||||||
|
if (cnt != 1) {
|
||||||
|
fprintf(out, " /* ERROR: Expect one target event, got %u */", cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(out, ";\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The wait statement contains simply an array of events to wait on,
|
* The wait statement contains simply an array of events to wait on,
|
||||||
* and a sub-statement to execute when an event triggers.
|
* and a sub-statement to execute when an event triggers.
|
||||||
|
|
@ -537,6 +570,10 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
||||||
show_stmt_trigger(net, ind);
|
show_stmt_trigger(net, ind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
|
show_stmt_nb_trigger(net, ind);
|
||||||
|
break;
|
||||||
|
|
||||||
case IVL_ST_UTASK:
|
case IVL_ST_UTASK:
|
||||||
fprintf(out, "%*scall task ...\n", ind, "");
|
fprintf(out, "%*scall task ...\n", ind, "");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2020 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2021 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -878,6 +878,7 @@ static unsigned has_func_disable(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
case IVL_ST_STASK:
|
case IVL_ST_STASK:
|
||||||
case IVL_ST_UTASK: // this will be generated for a SV void function
|
case IVL_ST_UTASK: // this will be generated for a SV void function
|
||||||
case IVL_ST_TRIGGER:
|
case IVL_ST_TRIGGER:
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
break;
|
break;
|
||||||
/* Look for a disable in each block statement. */
|
/* Look for a disable in each block statement. */
|
||||||
case IVL_ST_BLOCK:
|
case IVL_ST_BLOCK:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2020 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2011-2021 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -1427,6 +1427,26 @@ static void emit_stmt_trigger(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
fprintf(vlog_out, "\n");
|
fprintf(vlog_out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_stmt_nb_trigger(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
|
{
|
||||||
|
fprintf(vlog_out, "%*c->> ", get_indent(), ' ');
|
||||||
|
ivl_expr_t delay = ivl_stmt_delay_expr(stmt);
|
||||||
|
if (delay) {
|
||||||
|
fprintf(vlog_out, "#(");
|
||||||
|
emit_scaled_delayx(scope, delay, 1);
|
||||||
|
fprintf(vlog_out, ") ");
|
||||||
|
}
|
||||||
|
assert(ivl_stmt_nevent(stmt) == 1);
|
||||||
|
emit_event(scope, stmt);
|
||||||
|
fprintf(vlog_out, ";");
|
||||||
|
emit_stmt_file_line(stmt);
|
||||||
|
fprintf(vlog_out, "\n");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 sorry: wait fork is not currently "
|
||||||
|
"translated.\n",
|
||||||
|
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
|
||||||
|
vlog_errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A user defined task call with arguments is generated as a block with
|
* A user defined task call with arguments is generated as a block with
|
||||||
* input assignments, a simple call and then output assignments. This is
|
* input assignments, a simple call and then output assignments. This is
|
||||||
|
|
@ -1596,6 +1616,9 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
case IVL_ST_TRIGGER:
|
case IVL_ST_TRIGGER:
|
||||||
emit_stmt_trigger(scope, stmt);
|
emit_stmt_trigger(scope, stmt);
|
||||||
break;
|
break;
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
|
emit_stmt_nb_trigger(scope, stmt);
|
||||||
|
break;
|
||||||
case IVL_ST_UTASK:
|
case IVL_ST_UTASK:
|
||||||
emit_stmt_utask(scope, stmt);
|
emit_stmt_utask(scope, stmt);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -1284,21 +1284,8 @@ static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void draw_expr_into_idx(ivl_expr_t expr, int use_idx)
|
||||||
* The delayx statement is slightly more complex in that it is
|
|
||||||
* necessary to calculate the delay first. Load the calculated delay
|
|
||||||
* into and index register and use the %delayx instruction to do the
|
|
||||||
* actual delay.
|
|
||||||
*/
|
|
||||||
static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
ivl_expr_t expr = ivl_stmt_delay_expr(net);
|
|
||||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
|
||||||
|
|
||||||
show_stmt_file_line(net, "Delay statement.");
|
|
||||||
|
|
||||||
int use_idx = allocate_word();
|
|
||||||
switch (ivl_expr_value(expr)) {
|
switch (ivl_expr_value(expr)) {
|
||||||
|
|
||||||
case IVL_VT_BOOL:
|
case IVL_VT_BOOL:
|
||||||
|
|
@ -1317,6 +1304,25 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The delayx statement is slightly more complex in that it is
|
||||||
|
* necessary to calculate the delay first. Load the calculated delay
|
||||||
|
* into and index register and use the %delayx instruction to do the
|
||||||
|
* actual delay.
|
||||||
|
*/
|
||||||
|
static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
ivl_expr_t expr = ivl_stmt_delay_expr(net);
|
||||||
|
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||||
|
|
||||||
|
show_stmt_file_line(net, "Delay statement.");
|
||||||
|
|
||||||
|
int use_idx = allocate_word();
|
||||||
|
draw_expr_into_idx(expr, use_idx);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%delayx %d;\n", use_idx);
|
fprintf(vvp_out, " %%delayx %d;\n", use_idx);
|
||||||
clr_word(use_idx);
|
clr_word(use_idx);
|
||||||
|
|
@ -1643,6 +1649,34 @@ static int show_stmt_trigger(ivl_statement_t net)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The non-blocking trigger statement is straight forward. All we have to
|
||||||
|
* do is write a single bit of fake data to the event object.
|
||||||
|
*/
|
||||||
|
static int show_stmt_nb_trigger(ivl_statement_t net)
|
||||||
|
{
|
||||||
|
ivl_event_t ev = ivl_stmt_events(net, 0);
|
||||||
|
assert(ev);
|
||||||
|
|
||||||
|
show_stmt_file_line(net, "Non-blocking event trigger statement.");
|
||||||
|
|
||||||
|
ivl_expr_t expr = ivl_stmt_delay_expr(net);
|
||||||
|
int use_idx = allocate_word();
|
||||||
|
if (expr) {
|
||||||
|
draw_expr_into_idx(expr, use_idx);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%ix/load %d, 0, 0;\n", use_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%event/nb E_%p, %d;\n", ev, use_idx);
|
||||||
|
clr_word(use_idx);
|
||||||
|
// FIXME: VVP needs to be updated to correctly support %event/nb
|
||||||
|
fprintf(stderr, "%s:%u: vvp.tgt sorry: ->> is not currently supported.\n",
|
||||||
|
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||||
|
vvp_errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int show_stmt_utask(ivl_statement_t net)
|
static int show_stmt_utask(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
ivl_scope_t task = ivl_stmt_call(net);
|
ivl_scope_t task = ivl_stmt_call(net);
|
||||||
|
|
@ -2383,6 +2417,10 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
rc += show_stmt_trigger(net);
|
rc += show_stmt_trigger(net);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IVL_ST_NB_TRIGGER:
|
||||||
|
rc += show_stmt_nb_trigger(net);
|
||||||
|
break;
|
||||||
|
|
||||||
case IVL_ST_UTASK:
|
case IVL_ST_UTASK:
|
||||||
rc += show_stmt_utask(net);
|
rc += show_stmt_utask(net);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_codes_H
|
#ifndef IVL_codes_H
|
||||||
#define IVL_codes_H
|
#define IVL_codes_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -112,6 +112,7 @@ extern bool of_DUP_REAL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DUP_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_DUP_VEC4(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_EVENT(vthread_t thr, vvp_code_t code);
|
extern bool of_EVENT(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_EVENT_NB(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_EVCTL(vthread_t thr, vvp_code_t code);
|
extern bool of_EVCTL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_EVCTLC(vthread_t thr, vvp_code_t code);
|
extern bool of_EVCTLC(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_EVCTLI(vthread_t thr, vvp_code_t code);
|
extern bool of_EVCTLI(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -167,7 +167,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%evctl/c",of_EVCTLC, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%evctl/c",of_EVCTLC, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%evctl/i",of_EVCTLI, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%evctl/i",of_EVCTLI, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
{ "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
|
{ "%event/nb", of_EVENT_NB, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%flag_inv", of_FLAG_INV, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
{ "%flag_inv", of_FLAG_INV, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||||
{ "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -517,6 +517,7 @@ that this information has been cleared. You can get an assert if
|
||||||
this information is not managed correctly.
|
this information is not managed correctly.
|
||||||
|
|
||||||
* %event <functor-label>
|
* %event <functor-label>
|
||||||
|
* %event/nb <functor-label>
|
||||||
|
|
||||||
This instruction is used to send a pulse to an event object. The
|
This instruction is used to send a pulse to an event object. The
|
||||||
<functor-label> is an event variable. This instruction simply writes
|
<functor-label> is an event variable. This instruction simply writes
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,19 @@ void schedule_propagate_vector(vvp_net_t*net,
|
||||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This needs to create a non-blocking event, but only one per time slot.
|
||||||
|
// Is schedule_event_ or execution actually filtering since the net is
|
||||||
|
// already X because this is not triggering?
|
||||||
|
void schedule_propagate_event(vvp_net_t*net,
|
||||||
|
vvp_time64_t delay)
|
||||||
|
{
|
||||||
|
vvp_vector4_t tmp (1, BIT4_X);
|
||||||
|
struct propagate_vector4_event_s*cur
|
||||||
|
= new struct propagate_vector4_event_s(tmp);
|
||||||
|
cur->net = net;
|
||||||
|
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||||
|
}
|
||||||
|
|
||||||
void schedule_assign_array_word(vvp_array_t mem,
|
void schedule_assign_array_word(vvp_array_t mem,
|
||||||
unsigned word_addr,
|
unsigned word_addr,
|
||||||
unsigned off,
|
unsigned off,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_schedule_H
|
#ifndef IVL_schedule_H
|
||||||
#define IVL_schedule_H
|
#define IVL_schedule_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -75,9 +75,15 @@ extern void schedule_force_vector(vvp_net_t*net,
|
||||||
* Create an event to propagate the output of a net.
|
* Create an event to propagate the output of a net.
|
||||||
*/
|
*/
|
||||||
extern void schedule_propagate_vector(vvp_net_t*ptr,
|
extern void schedule_propagate_vector(vvp_net_t*ptr,
|
||||||
vvp_time64_t delay,
|
vvp_time64_t delay,
|
||||||
const vvp_vector4_t&val);
|
const vvp_vector4_t&val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an event to propagate the output of an event.
|
||||||
|
*/
|
||||||
|
extern void schedule_propagate_event(vvp_net_t*ptr,
|
||||||
|
vvp_time64_t delay);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is very similar to schedule_assign_vector, but generates an
|
* This is very similar to schedule_assign_vector, but generates an
|
||||||
* event in the active queue. It is used at link time to assign a
|
* event in the active queue. It is used at link time to assign a
|
||||||
|
|
|
||||||
|
|
@ -3106,6 +3106,18 @@ bool of_EVENT(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %event/nb <var-label>, <delay>
|
||||||
|
*/
|
||||||
|
bool of_EVENT_NB(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
vvp_time64_t delay;
|
||||||
|
|
||||||
|
delay = thr->words[cp->bit_idx[0]].w_uint;
|
||||||
|
schedule_propagate_event(cp->net, delay);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool of_EVCTL(vthread_t thr, vvp_code_t cp)
|
bool of_EVCTL(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
assert(thr->event == 0 && thr->ecount == 0);
|
assert(thr->event == 0 && thr->ecount == 0);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue