From 6a57764e0ec48cc89f10afd4e762dae9d17d5e87 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 19 May 2012 17:34:13 -0700 Subject: [PATCH] Elaborate fork-join_none and fork-join_any statements. --- Statement.cc | 9 ++++++++- Statement.h | 10 +++++++--- design_dump.cc | 6 ++++++ elab_scope.cc | 4 +++- elaborate.cc | 18 +++++++++++++++--- ivl_target.h | 10 ++++++---- net_nex_input.cc | 4 ++-- netlist.h | 2 +- parse.y | 13 +++++++++---- t-dll-api.cc | 8 +++++++- t-dll-proc.cc | 19 +++++++++++++++---- tgt-stub/statement.c | 24 +++++++++++++++++++++++- 12 files changed, 102 insertions(+), 25 deletions(-) diff --git a/Statement.cc b/Statement.cc index a99e8b37e..64df85ebd 100644 --- a/Statement.cc +++ b/Statement.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008,2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008,2010,2012 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 @@ -114,6 +114,13 @@ PBlock::~PBlock() delete list_[idx]; } +void PBlock::set_join_type(PBlock::BL_TYPE type) +{ + assert(bl_type_ == BL_PAR); + assert(type == BL_JOIN_NONE || type==BL_JOIN_ANY); + bl_type_ = type; +} + void PBlock::set_statement(const vector&st) { list_ = st; diff --git a/Statement.h b/Statement.h index 049aa118e..48c58a800 100644 --- a/Statement.h +++ b/Statement.h @@ -1,7 +1,7 @@ #ifndef __Statement_H #define __Statement_H /* - * Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008,2012 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 @@ -165,7 +165,7 @@ class PAssignNB : public PAssign_ { class PBlock : public PScope, public Statement { public: - enum BL_TYPE { BL_SEQ, BL_PAR }; + enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY }; // If the block has a name, it is a scope and also has a parent. explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t); @@ -175,6 +175,10 @@ class PBlock : public PScope, public Statement { BL_TYPE bl_type() const { return bl_type_; } + // If the bl_type() is BL_PAR, it is possible to replace it + // with JOIN_NONE or JOIN_ANY. This is to help the parser. + void set_join_type(BL_TYPE); + void set_statement(const std::vector&st); virtual void dump(ostream&out, unsigned ind) const; @@ -183,7 +187,7 @@ class PBlock : public PScope, public Statement { virtual void elaborate_sig(Design*des, NetScope*scope) const; private: - const BL_TYPE bl_type_; + BL_TYPE bl_type_; std::vectorlist_; }; diff --git a/design_dump.cc b/design_dump.cc index ce16ec862..9d5b3b678 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -40,6 +40,12 @@ static ostream& operator<< (ostream&o, NetBlock::Type t) case NetBlock::PARA: o << "fork"; break; + case NetBlock::PARA_JOIN_NONE: + o << "fork-join_none"; + break; + case NetBlock::PARA_JOIN_ANY: + o << "fork-join_any"; + break; } return o; } diff --git a/elab_scope.cc b/elab_scope.cc index 685dfac2c..796f60633 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1564,7 +1564,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const << "Elaborate block scope " << use_name << " within " << scope_path(scope) << endl; - my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR + // The scope type is begin-end or fork-join. The + // sub-types of fork-join are not interesting to the scope. + my_scope = new NetScope(scope, use_name, bl_type_!=BL_SEQ ? NetScope::FORK_JOIN : NetScope::BEGIN_END); my_scope->set_line(get_file(), get_lineno()); diff --git a/elaborate.cc b/elaborate.cc index 25767e5c7..319051b18 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2633,9 +2633,21 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const { assert(scope); - NetBlock::Type type = (bl_type_==PBlock::BL_PAR) - ? NetBlock::PARA - : NetBlock::SEQU; + NetBlock::Type type; + switch (bl_type_) { + case PBlock::BL_SEQ: + type = NetBlock::SEQU; + break; + case PBlock::BL_PAR: + type = NetBlock::PARA; + break; + case PBlock::BL_JOIN_NONE: + type = NetBlock::PARA_JOIN_NONE; + break; + case PBlock::BL_JOIN_ANY: + type = NetBlock::PARA_JOIN_ANY; + break; + } NetScope*nscope = 0; if (pscope_name() != 0) { diff --git a/ivl_target.h b/ivl_target.h index fddcf86f5..2933ac0e6 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1,7 +1,7 @@ #ifndef __ivl_target_H #define __ivl_target_H /* - * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2012 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 @@ -406,6 +406,8 @@ typedef enum ivl_statement_type_e { IVL_ST_FORCE = 14, IVL_ST_FOREVER = 15, IVL_ST_FORK = 16, + IVL_ST_FORK_JOIN_ANY = 28, + IVL_ST_FORK_JOIN_NONE = 29, IVL_ST_FREE = 26, IVL_ST_RELEASE = 17, IVL_ST_REPEAT = 18, @@ -2069,11 +2071,11 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * triggers. The statement waits even if the sub-statement is nul. */ - /* IVL_ST_BLOCK, IVL_ST_FORK */ + /* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */ extern unsigned ivl_stmt_block_count(ivl_statement_t net); - /* IVL_ST_BLOCK, IVL_ST_FORK */ + /* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */ extern ivl_scope_t ivl_stmt_block_scope(ivl_statement_t net); - /* IVL_ST_BLOCK, IVL_ST_FORK */ + /* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */ extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i); /* IVL_ST_UTASK IVL_ST_DISABLE */ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net); diff --git a/net_nex_input.cc b/net_nex_input.cc index 5642e6164..784ff9d01 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2012 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 @@ -257,7 +257,7 @@ NexusSet* NetBlock::nex_input(bool rem_out) if (last_ == 0) return new NexusSet; - if (type_ == PARA) { + if (type_ != SEQU) { cerr << get_fileline() << ": internal error: Sorry, " << "I don't know how to synthesize fork/join blocks." << endl; diff --git a/netlist.h b/netlist.h index 284d28896..3dc0a628c 100644 --- a/netlist.h +++ b/netlist.h @@ -2491,7 +2491,7 @@ class NetAssignNB : public NetAssignBase { class NetBlock : public NetProc { public: - enum Type { SEQU, PARA }; + enum Type { SEQU, PARA, PARA_JOIN_ANY, PARA_JOIN_NONE }; NetBlock(Type t, NetScope*subscope); ~NetBlock(); diff --git a/parse.y b/parse.y index 219a1960b..27c8d7e5a 100644 --- a/parse.y +++ b/parse.y @@ -356,6 +356,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector PGBuiltin::Type gatetype; NetNet::PortType porttype; ivl_variable_type_t vartype; + PBlock::BL_TYPE join_keyword; PWire*wire; svector*wires; @@ -574,6 +575,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type analog_statement +%type join_keyword + %type spec_polarity %type specify_path_identifiers @@ -1084,10 +1087,11 @@ integer_vector_type /* IEEE1800-2005: A.2.2.1 */ join_keyword /* IEEE1800-2005: A.6.3 */ : K_join + { $$ = PBlock::BL_PAR; } | K_join_none - { yyerror(@1, "sorry: join_none not supported."); } + { $$ = PBlock::BL_JOIN_NONE; } | K_join_any - { yyerror(@1, "sorry: join_any not supported."); } + { $$ = PBlock::BL_JOIN_ANY; } ; jump_statement /* IEEE1800-2005: A.6.5 */ @@ -5335,12 +5339,12 @@ statement_item /* This is roughly statement_item in the LRM */ code generator can do the right thing. */ | K_fork join_keyword - { PBlock*tmp = new PBlock(PBlock::BL_PAR); + { PBlock*tmp = new PBlock($2); FILE_NAME(tmp, @1); $$ = tmp; } | K_fork statement_or_null_list join_keyword - { PBlock*tmp = new PBlock(PBlock::BL_PAR); + { PBlock*tmp = new PBlock($3); FILE_NAME(tmp, @1); tmp->set_statement(*$2); delete $2; @@ -5357,6 +5361,7 @@ statement_item /* This is roughly statement_item in the LRM */ assert(! current_block_stack.empty()); PBlock*tmp = current_block_stack.top(); current_block_stack.pop(); + tmp->set_join_type($7); if ($6) tmp->set_statement(*$6); delete[]$3; delete $6; diff --git a/t-dll-api.cc b/t-dll-api.cc index 008847127..150258cac 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2012 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 @@ -2271,6 +2271,8 @@ extern "C" ivl_scope_t ivl_stmt_block_scope(ivl_statement_t net) switch (net->type_) { case IVL_ST_BLOCK: case IVL_ST_FORK: + case IVL_ST_FORK_JOIN_ANY: + case IVL_ST_FORK_JOIN_NONE: return net->u_.block_.scope; default: assert(0); @@ -2283,6 +2285,8 @@ extern "C" unsigned ivl_stmt_block_count(ivl_statement_t net) switch (net->type_) { case IVL_ST_BLOCK: case IVL_ST_FORK: + case IVL_ST_FORK_JOIN_ANY: + case IVL_ST_FORK_JOIN_NONE: return net->u_.block_.nstmt_; default: assert(0); @@ -2296,6 +2300,8 @@ extern "C" ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, switch (net->type_) { case IVL_ST_BLOCK: case IVL_ST_FORK: + case IVL_ST_FORK_JOIN_ANY: + case IVL_ST_FORK_JOIN_NONE: return net->u_.block_.stmt_ + i; default: assert(0); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index fbc55464e..8874dbb5d 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2012 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 @@ -386,9 +386,20 @@ bool dll_target::proc_block(const NetBlock*net) it, so fill in the block fields of the existing statement, and generate the contents for the statement array. */ - stmt_cur_->type_ = (net->type() == NetBlock::SEQU) - ? IVL_ST_BLOCK - : IVL_ST_FORK; + switch (net->type()) { + case NetBlock::SEQU: + stmt_cur_->type_ = IVL_ST_BLOCK; + break; + case NetBlock::PARA: + stmt_cur_->type_ = IVL_ST_FORK; + break; + case NetBlock::PARA_JOIN_ANY: + stmt_cur_->type_ = IVL_ST_FORK_JOIN_ANY; + break; + case NetBlock::PARA_JOIN_NONE: + stmt_cur_->type_ = IVL_ST_FORK_JOIN_NONE; + break; + } stmt_cur_->u_.block_.nstmt_ = count; stmt_cur_->u_.block_.stmt_ = (struct ivl_statement_s*) calloc(count, sizeof(struct ivl_statement_s)); diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 401b049e7..1b89e43ec 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2007,2012 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 @@ -329,6 +329,28 @@ void show_statement(ivl_statement_t net, unsigned ind) break; } + case IVL_ST_FORK_JOIN_ANY: { + unsigned cnt = ivl_stmt_block_count(net); + fprintf(out, "%*sfork\n", ind, ""); + for (idx = 0 ; idx < cnt ; idx += 1) { + ivl_statement_t cur = ivl_stmt_block_stmt(net, idx); + show_statement(cur, ind+4); + } + fprintf(out, "%*sjoin_any\n", ind, ""); + break; + } + + case IVL_ST_FORK_JOIN_NONE: { + unsigned cnt = ivl_stmt_block_count(net); + fprintf(out, "%*sfork\n", ind, ""); + for (idx = 0 ; idx < cnt ; idx += 1) { + ivl_statement_t cur = ivl_stmt_block_stmt(net, idx); + show_statement(cur, ind+4); + } + fprintf(out, "%*sjoin_none\n", ind, ""); + break; + } + case IVL_ST_FREE: fprintf(out, "%*sfree automatic storage ...\n", ind, ""); break;