diff options
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.cc | 5 | ||||
-rw-r--r-- | frontends/ast/ast.h | 2 | ||||
-rw-r--r-- | frontends/ast/dpicall.cc | 17 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 27 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 70 | ||||
-rw-r--r-- | frontends/rtlil/rtlil_lexer.l | 1 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 36 | ||||
-rw-r--r-- | frontends/verilog/preproc.cc | 8 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 3 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 106 |
10 files changed, 203 insertions, 72 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index c8183580b..dc47420af 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -548,9 +548,9 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const break; case AST_CASE: - if (!children.empty() && children[0]->type == AST_CONDX) + if (children.size() > 1 && children[1]->type == AST_CONDX) fprintf(f, "%s" "casex (", indent.c_str()); - else if (!children.empty() && children[0]->type == AST_CONDZ) + else if (children.size() > 1 && children[1]->type == AST_CONDZ) fprintf(f, "%s" "casez (", indent.c_str()); else fprintf(f, "%s" "case (", indent.c_str()); @@ -1511,6 +1511,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr } } else { + modname = new_modname; log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 1b8ed22ca..907392166 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -250,6 +250,7 @@ namespace AST // simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc. // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL() bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param); + void replace_result_wire_name_in_function(const std::string &from, const std::string &to); AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init); void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope = true); void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules); @@ -264,6 +265,7 @@ namespace AST // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; bool has_const_only_constructs(bool &recommend_const_eval); + bool has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval); void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall); AstNode *eval_const_function(AstNode *fcall); bool is_simple_const_expr(); diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc index e241142d3..948c9083c 100644 --- a/frontends/ast/dpicall.cc +++ b/frontends/ast/dpicall.cc @@ -67,7 +67,7 @@ static ffi_fptr resolve_fn (std::string symbol_name) AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args) { AST::AstNode *newNode = nullptr; - union { double f64; float f32; int32_t i32; } value_store [args.size() + 1]; + union { double f64; float f32; int32_t i32; void *ptr; } value_store [args.size() + 1]; ffi_type *types [args.size() + 1]; void *values [args.size() + 1]; ffi_cif cif; @@ -92,6 +92,11 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, value_store[i].i32 = args[i]->asInt(args[i]->is_signed); values[i] = &value_store[i].i32; types[i] = &ffi_type_sint32; + } else if (argtypes[i] == "chandle") { + log(" arg %d (%s): %llx\n", i, argtypes[i].c_str(), (unsigned long long)args[i]->asInt(false)); + value_store[i].ptr = (void *)args[i]->asInt(args[i]->is_signed); + values[i] = &value_store[i].ptr; + types[i] = &ffi_type_pointer; } else { log_error("invalid argtype '%s' for argument %d.\n", argtypes[i].c_str(), i); } @@ -106,6 +111,9 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, } else if (rtype == "real") { types[args.size()] = &ffi_type_double; values[args.size()] = &value_store[args.size()].f64; + } else if (rtype == "chandle") { + types[args.size()] = &ffi_type_pointer; + values[args.size()] = &value_store[args.size()].ptr; } else { log_error("invalid rtype '%s'.\n", rtype.c_str()); } @@ -123,6 +131,13 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, newNode = new AstNode(AST_REALVALUE); newNode->realvalue = value_store[args.size()].f32; log(" return realvalue: %g\n", newNode->asReal(true)); + } else if (rtype == "chandle") { + uint64_t rawval = (uint64_t)value_store[args.size()].ptr; + std::vector<RTLIL::State> bits(64); + for (int i = 0; i < 64; i++) + bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0; + newNode = AstNode::mkconst_bits(bits, false); + log(" return chandle: %llx\n", (unsigned long long)newNode->asInt(false)); } else { newNode = AstNode::mkconst_int(value_store[args.size()].i32, false); log(" return integer: %lld\n", (long long)newNode->asInt(true)); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index e878d0dd2..b8bfdf65e 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -106,6 +106,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width); wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->is_signed = that->is_signed; for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) @@ -140,6 +141,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size()); wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->is_signed = that->is_signed; for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) @@ -1721,8 +1723,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (child->type == AST_ARGUMENT) { RTLIL::SigSpec sig; - if (child->children.size() > 0) - sig = child->children[0]->genRTLIL(); + if (child->children.size() > 0) { + AstNode *arg = child->children[0]; + int local_width_hint = -1; + bool local_sign_hint = false; + // don't inadvertently attempt to detect the width of interfaces + if (arg->type != AST_IDENTIFIER || !arg->id2ast || arg->id2ast->type != AST_CELL) + arg->detectSignWidth(local_width_hint, local_sign_hint); + sig = arg->genRTLIL(local_width_hint, local_sign_hint); + log_assert(local_sign_hint == arg->is_signed); + if (sig.is_wire()) { + // if the resulting SigSpec is a wire, its + // signedness should match that of the AstNode + log_assert(arg->is_signed == sig.as_wire()->is_signed); + } else if (arg->is_signed) { + // non-trivial signed nodes are indirected through + // signed wires to enable sign extension + RTLIL::IdString wire_name = NEW_ID; + RTLIL::Wire *wire = current_module->addWire(wire_name, arg->bits.size()); + wire->is_signed = true; + current_module->connect(wire, sig); + sig = wire; + } + } if (child->str.size() == 0) { char buf[100]; snprintf(buf, 100, "$%d", ++port_counter); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index fb6623f02..fc2976c83 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1205,6 +1205,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, current_block = this; current_block_child = children[i]; } + if (!in_param_here && type == AST_FCALL) { + bool recommend_const_eval = false; + bool require_const_eval = has_const_only_constructs(recommend_const_eval); + in_param_here = recommend_const_eval || require_const_eval; + } if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK) current_top_block = children[i]; if (i == 0 && child_0_is_self_determined) @@ -1325,6 +1330,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) { // replace with wire representing the packed structure newNode = make_packed_struct(template_node, str); + // add original input/output attribute to resolved wire + newNode->is_input = this->is_input; + newNode->is_output = this->is_output; current_scope[str] = this; goto apply_newNode; } @@ -3170,6 +3178,8 @@ skip_dynamic_range_lvalue_expansion:; if (all_args_const) { AstNode *func_workspace = current_scope[str]->clone(); + func_workspace->str = NEW_ID.str(); + func_workspace->replace_result_wire_name_in_function(str, func_workspace->str); newNode = func_workspace->eval_const_function(this); delete func_workspace; goto apply_newNode; @@ -3337,6 +3347,25 @@ skip_dynamic_range_lvalue_expansion:; wire->type = AST_LOCALPARAM; wire->attributes.erase(ID::nosync); wire->children.insert(wire->children.begin(), arg->clone()); + // args without a range implicitly have width 1 + if (wire->children.back()->type != AST_RANGE) { + // check if this wire is redeclared with an explicit size + bool uses_explicit_size = false; + for (const AstNode *other_child : decl->children) + if (other_child->type == AST_WIRE && child->str == other_child->str + && !other_child->children.empty() + && other_child->children.back()->type == AST_RANGE) { + uses_explicit_size = true; + break; + } + if (!uses_explicit_size) { + AstNode* range = new AstNode(); + range->type = AST_RANGE; + wire->children.push_back(range); + range->children.push_back(mkconst_int(0, true)); + range->children.push_back(mkconst_int(0, true)); + } + } continue; } AstNode *wire_id = new AstNode(AST_IDENTIFIER); @@ -3427,7 +3456,14 @@ replace_fcall_later:; if (current_scope[str]->children[0]->isConst()) newNode = current_scope[str]->children[0]->clone(); } - else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) { + else if (at_zero && current_scope.count(str) > 0) { + AstNode *node = current_scope[str]; + if (node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) + newNode = mkconst_int(0, sign_hint, width_hint); + } + break; + case AST_MEMRD: + if (at_zero) { newNode = mkconst_int(0, sign_hint, width_hint); } break; @@ -3683,12 +3719,12 @@ apply_newNode: return did_something; } -static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to) +void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to) { - for (auto &it : node->children) - replace_result_wire_name_in_function(it, from, to); - if (node->str == from) - node->str = to; + for (AstNode *child : children) + child->replace_result_wire_name_in_function(from, to); + if (str == from && type != AST_FCALL && type != AST_TCALL) + str = to; } // replace a readmem[bh] TCALL ast node with a block of memory assignments @@ -3881,7 +3917,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma name_map[child->str] = new_name; if (child->type == AST_FUNCTION) - replace_result_wire_name_in_function(child, child->str, new_name); + child->replace_result_wire_name_in_function(child->str, new_name); else child->str = new_name; current_scope[new_name] = child; @@ -4461,15 +4497,31 @@ bool AstNode::detect_latch(const std::string &var) bool AstNode::has_const_only_constructs(bool &recommend_const_eval) { + std::set<std::string> visited; + return has_const_only_constructs(visited, recommend_const_eval); +} + +bool AstNode::has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval) +{ + if (type == AST_FUNCTION || type == AST_TASK) + { + if (visited.count(str)) + { + recommend_const_eval = true; + return false; + } + visited.insert(str); + } + if (type == AST_FOR) recommend_const_eval = true; if (type == AST_WHILE || type == AST_REPEAT) return true; if (type == AST_FCALL && current_scope.count(str)) - if (current_scope[str]->has_const_only_constructs(recommend_const_eval)) + if (current_scope[str]->has_const_only_constructs(visited, recommend_const_eval)) return true; for (auto child : children) - if (child->AstNode::has_const_only_constructs(recommend_const_eval)) + if (child->AstNode::has_const_only_constructs(visited, recommend_const_eval)) return true; return false; } diff --git a/frontends/rtlil/rtlil_lexer.l b/frontends/rtlil/rtlil_lexer.l index 295455f53..beef220f6 100644 --- a/frontends/rtlil/rtlil_lexer.l +++ b/frontends/rtlil/rtlil_lexer.l @@ -86,7 +86,6 @@ USING_YOSYS_NAMESPACE "\\"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } "$"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } -"."[0-9]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } [0-9]+'[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; } -?[0-9]+ { diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 31c77d39c..81e14ac41 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -51,12 +51,12 @@ USING_YOSYS_NAMESPACE #include "VeriLibrary.h" #include "VeriExtensions.h" -#ifndef SYMBIOTIC_VERIFIC_API_VERSION -# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific." +#ifndef YOSYSHQ_VERIFIC_API_VERSION +# error "Only YosysHQ flavored Verific is supported. Please contact office@yosyshq.com for commercial support for Yosys+Verific." #endif -#if SYMBIOTIC_VERIFIC_API_VERSION < 20201001 -# error "Please update your version of Symbiotic EDA flavored Verific." +#if YOSYSHQ_VERIFIC_API_VERSION < 20210101 +# error "Please update your version of YosysHQ flavored Verific." #endif #ifdef __clang__ @@ -1471,7 +1471,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se continue; } - if (inst->Type() == PRIM_SEDA_INITSTATE) + if (inst->Type() == PRIM_YOSYSHQ_INITSTATE) { SigBit initstate = module->Initstate(new_verific_id(inst)); SigBit sig_o = net_map_at(inst->GetOutput()); @@ -2199,7 +2199,7 @@ struct VerificPass : public Pass { log("\n"); log(" verific -app <application>..\n"); log("\n"); - log("Execute SEDA formal application on loaded Verilog files.\n"); + log("Execute YosysHQ formal application on loaded Verilog files.\n"); log("\n"); log("Application options:\n"); log("\n"); @@ -2250,11 +2250,11 @@ struct VerificPass : public Pass { log(" WARNING: Templates only available in commercial build.\n"); log("\n"); #endif - log("Use Symbiotic EDA Suite if you need Yosys+Verifc.\n"); - log("https://www.symbioticeda.com/seda-suite\n"); + log("Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n"); + log("https://www.yosyshq.com/\n"); log("\n"); - log("Contact office@symbioticeda.com for free evaluation\n"); - log("binaries of Symbiotic EDA Suite.\n"); + log("Contact office@yosyshq.com for free evaluation\n"); + log("binaries of YosysHQ Tabby CAD Suite.\n"); log("\n"); } #ifdef YOSYS_ENABLE_VERIFIC @@ -2265,11 +2265,11 @@ struct VerificPass : public Pass { if (check_noverific_env()) log_cmd_error("This version of Yosys is built without Verific support.\n" "\n" - "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n" - "https://www.symbioticeda.com/seda-suite\n" + "Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n" + "https://www.yosyshq.com/\n" "\n" - "Contact office@symbioticeda.com for free evaluation\n" - "binaries of Symbiotic EDA Suite.\n"); + "Contact office@yosyshq.com for free evaluation\n" + "binaries of YosysHQ Tabby CAD Suite.\n"); log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n"); @@ -2926,11 +2926,11 @@ struct VerificPass : public Pass { void execute(std::vector<std::string>, RTLIL::Design *) override { log_cmd_error("This version of Yosys is built without Verific support.\n" "\n" - "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n" - "https://www.symbioticeda.com/seda-suite\n" + "Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n" + "https://www.yosyshq.com/\n" "\n" - "Contact office@symbioticeda.com for free evaluation\n" - "binaries of Symbiotic EDA Suite.\n"); + "Contact office@yosyshq.com for free evaluation\n" + "binaries of YosysHQ Tabby CAD Suite.\n"); } #endif } VerificPass; diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index ea23139e2..c451c4c20 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -321,7 +321,6 @@ struct define_body_t define_map_t::define_map_t() { add("YOSYS", "1"); - add(formal_mode ? "FORMAL" : "SYNTHESIS", "1"); } // We must define this destructor here (rather than relying on the default), because we need to @@ -391,13 +390,16 @@ static void input_file(std::istream &f, std::string filename) // the argument list); false if we finished with ','. static bool read_argument(std::string &dest) { + skip_spaces(); std::vector<char> openers; for (;;) { - skip_spaces(); std::string tok = next_token(true); if (tok == ")") { - if (openers.empty()) + if (openers.empty()) { + while (dest.size() && (dest.back() == ' ' || dest.back() == '\t')) + dest = dest.substr(0, dest.size() - 1); return true; + } if (openers.back() != '(') log_error("Mismatched brackets in macro argument: %c and %c.\n", openers.back(), tok[0]); diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 2e9c9b2e2..5319a45ad 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -446,6 +446,9 @@ struct VerilogFrontend : public Frontend { } break; } + + defines_map.add(formal_mode ? "FORMAL" : "SYNTHESIS", "1"); + extra_args(f, filename, args, argidx); log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str()); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 678ce6c87..8bd58d24c 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -282,7 +282,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list +%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %type <string> type_name %type <ast> opt_enum_init enum_type struct_type non_wire_data_type @@ -619,26 +619,19 @@ non_opt_delay: delay: non_opt_delay | %empty; -wire_type: - { - astbuf3 = new AstNode(AST_WIRE); - current_wire_rand = false; - current_wire_const = false; - } wire_type_token_list { - $$ = astbuf3; - SET_RULE_LOC(@$, @2, @$); - }; +io_wire_type: + { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; } + wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness + { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); }; -wire_type_token_list: - wire_type_token | - wire_type_token_list wire_type_token | - wire_type_token_io | - hierarchical_type_id { - astbuf3->is_custom_type = true; - astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); - astbuf3->children.back()->str = *$1; - delete $1; - }; +non_io_wire_type: + { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; } + wire_type_const_rand wire_type_token wire_type_signedness + { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); }; + +wire_type: + io_wire_type | + non_io_wire_type; wire_type_token_io: TOK_INPUT { @@ -652,8 +645,32 @@ wire_type_token_io: astbuf3->is_output = true; }; +wire_type_signedness: + TOK_SIGNED { astbuf3->is_signed = true; } | + TOK_UNSIGNED { astbuf3->is_signed = false; } | + %empty; + +wire_type_const_rand: + TOK_RAND TOK_CONST { + current_wire_rand = true; + current_wire_const = true; + } | + TOK_CONST { + current_wire_const = true; + } | + TOK_RAND { + current_wire_rand = true; + } | + %empty; + +opt_wire_type_token: + wire_type_token | %empty; + wire_type_token: - TOK_WIRE { + hierarchical_type_id { + astbuf3->is_custom_type = true; + astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); + astbuf3->children.back()->str = *$1; } | TOK_WOR { astbuf3->is_wor = true; @@ -661,20 +678,27 @@ wire_type_token: TOK_WAND { astbuf3->is_wand = true; } | + // wires + TOK_WIRE { + } | + TOK_WIRE logic_type { + } | + // regs TOK_REG { astbuf3->is_reg = true; } | - TOK_LOGIC { - astbuf3->is_logic = true; + TOK_VAR TOK_REG { + astbuf3->is_reg = true; } | + // logics TOK_VAR { astbuf3->is_logic = true; } | - TOK_INTEGER { - astbuf3->is_reg = true; - astbuf3->range_left = 31; - astbuf3->range_right = 0; - astbuf3->is_signed = true; + TOK_VAR logic_type { + astbuf3->is_logic = true; + } | + logic_type { + astbuf3->is_logic = true; } | TOK_GENVAR { astbuf3->type = AST_GENVAR; @@ -682,15 +706,15 @@ wire_type_token: astbuf3->is_signed = true; astbuf3->range_left = 31; astbuf3->range_right = 0; + }; + +logic_type: + TOK_LOGIC { } | - TOK_SIGNED { + TOK_INTEGER { + astbuf3->range_left = 31; + astbuf3->range_right = 0; astbuf3->is_signed = true; - } | - TOK_RAND { - current_wire_rand = true; - } | - TOK_CONST { - current_wire_const = true; }; non_opt_range: @@ -884,7 +908,11 @@ task_func_args: task_func_port: attr wire_type range { + bool prev_was_input = true; + bool prev_was_output = false; if (albuf) { + prev_was_input = astbuf1->is_input; + prev_was_output = astbuf1->is_output; delete astbuf1; if (astbuf2 != NULL) delete astbuf2; @@ -893,6 +921,12 @@ task_func_port: albuf = $1; astbuf1 = $2; astbuf2 = checkRange(astbuf1, $3); + if (!astbuf1->is_input && !astbuf1->is_output) { + if (!sv_mode) + frontend_verilog_yyerror("task/function argument direction missing"); + astbuf1->is_input = prev_was_input; + astbuf1->is_output = prev_was_output; + } } wire_name | { if (!astbuf1) { @@ -1793,7 +1827,7 @@ type_name: TOK_ID // first time seen ; typedef_decl: - TOK_TYPEDEF wire_type range type_name range_or_multirange ';' { + TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' { astbuf1 = $2; astbuf2 = checkRange(astbuf1, $3); if (astbuf2) |