Add support for module input port default values (issue #489).

This commit is contained in:
Martin Whitaker 2021-03-10 08:21:42 +00:00
parent 60a77b08d2
commit c7eaa06a2b
5 changed files with 40 additions and 5 deletions

View File

@ -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
@ -104,6 +104,11 @@ perm_string Module::get_port_name(unsigned idx) const
return ports[idx]->name; return ports[idx]->name;
} }
PExpr* Module::get_port_default_value(unsigned idx) const
{
assert(idx < ports.size());
return ports[idx] ? ports[idx]->default_value : 0;
}
PGate* Module::get_gate(perm_string name) PGate* Module::get_gate(perm_string name)

View File

@ -1,7 +1,7 @@
#ifndef IVL_Module_H #ifndef IVL_Module_H
#define IVL_Module_H #define IVL_Module_H
/* /*
* 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
@ -60,11 +60,13 @@ class Module : public PScopeExtra, public PNamedItem {
objects. Each port has a name and an ordered list of objects. Each port has a name and an ordered list of
wires. The name is the means that the outside uses to wires. The name is the means that the outside uses to
access the port, the wires are the internal connections to access the port, the wires are the internal connections to
the port. */ the port. In SystemVerilog, input ports may also have a
default value. */
public: public:
struct port_t { struct port_t {
perm_string name; perm_string name;
vector<PEIdent*> expr; vector<PEIdent*> expr;
PExpr*default_value;
}; };
public: public:
@ -148,6 +150,8 @@ class Module : public PScopeExtra, public PNamedItem {
// Return port name ("" for undeclared port) // Return port name ("" for undeclared port)
perm_string get_port_name(unsigned idx) const; perm_string get_port_name(unsigned idx) const;
PExpr* get_port_default_value(unsigned idx) const;
PGate* get_gate(perm_string name); PGate* get_gate(perm_string name);
const list<PGate*>& get_gates() const; const list<PGate*>& get_gates() const;

View File

@ -1323,9 +1323,15 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
perm_string port_name = rmod->get_port_name(idx); perm_string port_name = rmod->get_port_name(idx);
// Skip unconnected module ports. This happens when a // If the port is unconnected, substitute the default
// null parameter is passed in. // value. The parser ensures that a default value only
// exists for input ports.
if (pins[idx] == 0)
pins[idx] = rmod->get_port_default_value(idx);
// Skip unconnected module ports. This happens when a
// null parameter is passed in and there is no default
// value.
if (pins[idx] == 0) { if (pins[idx] == 0) {
if (pins_fromwc[idx]) { if (pins_fromwc[idx]) {

19
parse.y
View File

@ -4634,6 +4634,22 @@ port_declaration
delete[]$4; delete[]$4;
$$ = ptmp; $$ = ptmp;
} }
| attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression
{ if (!gn_system_verilog()) {
yyerror("error: Default port values require SystemVerilog.");
}
Module::port_t*ptmp;
perm_string name = lex_strings.make($5);
data_type_t*use_type = $4;
ptmp = pform_module_port_reference(name, @2.text, @2.first_line);
ptmp->default_value = $7;
pform_module_define_port(@2, name, NetNet::PINPUT, $3, use_type, $1);
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.port_net_type = $3;
port_declaration_context.data_type = $4;
delete[]$5;
$$ = ptmp;
}
| attribute_list_opt K_inout net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt | attribute_list_opt K_inout net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt
{ Module::port_t*ptmp; { Module::port_t*ptmp;
perm_string name = lex_strings.make($5); perm_string name = lex_strings.make($5);
@ -5972,6 +5988,7 @@ port_reference
Module::port_t*ptmp = new Module::port_t; Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string(); ptmp->name = perm_string();
ptmp->expr.push_back(wtmp); ptmp->expr.push_back(wtmp);
ptmp->default_value = 0;
delete[]$1; delete[]$1;
$$ = ptmp; $$ = ptmp;
@ -5995,6 +6012,7 @@ port_reference
Module::port_t*ptmp = new Module::port_t; Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string(); ptmp->name = perm_string();
ptmp->expr.push_back(tmp); ptmp->expr.push_back(tmp);
ptmp->default_value = 0;
delete[]$1; delete[]$1;
$$ = ptmp; $$ = ptmp;
} }
@ -6006,6 +6024,7 @@ port_reference
FILE_NAME(wtmp, @1); FILE_NAME(wtmp, @1);
ptmp->name = lex_strings.make($1); ptmp->name = lex_strings.make($1);
ptmp->expr.push_back(wtmp); ptmp->expr.push_back(wtmp);
ptmp->default_value = 0;
delete[]$1; delete[]$1;
$$ = ptmp; $$ = ptmp;
} }

View File

@ -1394,6 +1394,7 @@ Module::port_t* pform_module_port_reference(perm_string name,
FILE_NAME(tmp, file, lineno); FILE_NAME(tmp, file, lineno);
ptmp->name = name; ptmp->name = name;
ptmp->expr.push_back(tmp); ptmp->expr.push_back(tmp);
ptmp->default_value = 0;
return ptmp; return ptmp;
} }