Add support to handle attributes at module instantiation sites.

(* my_fancy_attribute *)
foobar1 foobar (clk(clk), rst(rst) ...);

  - Modifies PGModule to hold the attribute map (can be verified with pform_dump)
  - pform_make_modgate(s) bind the attributes from the parser to the above map
  - The attributes from PGModule are inserted into the NetScope of that module
    PGModule::elaborate_scope_mod_instances_
  - Currently these attributes automatically make it into netlist
  - These attributes are accessible via ivl_scope_attr_cnt and ivl_scope_attr_val
    from ivl_target.h
This commit is contained in:
Vamsi Vytla 2017-03-16 07:41:10 -07:00 committed by Vamsi Vytla
parent fbd69e1774
commit cfd3b893be
6 changed files with 25 additions and 9 deletions

View File

@ -217,6 +217,8 @@ class PGModule : public PGate {
// method to pass the range to the pform. // method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb); void set_range(PExpr*msb, PExpr*lsb);
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const; virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const; virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const; virtual void elaborate_scope(Design*des, NetScope*sc) const;

View File

@ -1728,6 +1728,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl; << "." << endl;
} }
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
// Run through the module instances, and make scopes out of // Run through the module instances, and make scopes out of
// them. Also do parameter overrides that are done on the // them. Also do parameter overrides that are done on the
// instantiation line. // instantiation line.
@ -1762,6 +1766,9 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
get_lineno(), mod->get_lineno()); get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name()); my_scope->set_module_name(mod->mod_name());
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
instances[idx] = my_scope; instances[idx] = my_scope;
set_scope_timescale(des, my_scope, mod); set_scope_timescale(des, my_scope, mod);
@ -1820,6 +1827,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
mod->elaborate_scope(des, my_scope, replace); mod->elaborate_scope(des, my_scope, replace);
} }
delete[]attrib_list;
/* Stash the instance array of scopes into the parent /* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to scope. Later elaboration passes will use this vector to

View File

@ -4855,9 +4855,8 @@ module_item
| attribute_list_opt | attribute_list_opt
IDENTIFIER parameter_value_opt gate_instance_list ';' IDENTIFIER parameter_value_opt gate_instance_list ';'
{ perm_string tmp1 = lex_strings.make($2); { perm_string tmp1 = lex_strings.make($2);
pform_make_modgates(@2, tmp1, $3, $4); pform_make_modgates(@2, tmp1, $3, $4, $1);
delete[]$2; delete[]$2;
if ($1) delete $1;
} }
| attribute_list_opt | attribute_list_opt

View File

@ -2213,7 +2213,8 @@ static void pform_make_modgate(perm_string type,
struct parmvalue_t*overrides, struct parmvalue_t*overrides,
list<PExpr*>*wires, list<PExpr*>*wires,
PExpr*msb, PExpr*lsb, PExpr*msb, PExpr*lsb,
const char*fn, unsigned ln) const char*fn, unsigned ln,
std::list<named_pexpr_t>*attr)
{ {
for (list<PExpr*>::iterator idx = wires->begin() for (list<PExpr*>::iterator idx = wires->begin()
; idx != wires->end() ; ++idx) { ; idx != wires->end() ; ++idx) {
@ -2244,6 +2245,7 @@ static void pform_make_modgate(perm_string type,
pform_cur_generate->add_gate(cur); pform_cur_generate->add_gate(cur);
else else
pform_cur_module.front()->add_gate(cur); pform_cur_module.front()->add_gate(cur);
pform_bind_attributes(cur->attributes, attr);
} }
static void pform_make_modgate(perm_string type, static void pform_make_modgate(perm_string type,
@ -2251,7 +2253,8 @@ static void pform_make_modgate(perm_string type,
struct parmvalue_t*overrides, struct parmvalue_t*overrides,
list<named_pexpr_t>*bind, list<named_pexpr_t>*bind,
PExpr*msb, PExpr*lsb, PExpr*msb, PExpr*lsb,
const char*fn, unsigned ln) const char*fn, unsigned ln,
std::list<named_pexpr_t>*attr)
{ {
unsigned npins = bind->size(); unsigned npins = bind->size();
named<PExpr*>*pins = new named<PExpr*>[npins]; named<PExpr*>*pins = new named<PExpr*>[npins];
@ -2288,12 +2291,14 @@ static void pform_make_modgate(perm_string type,
pform_cur_generate->add_gate(cur); pform_cur_generate->add_gate(cur);
else else
pform_cur_module.front()->add_gate(cur); pform_cur_module.front()->add_gate(cur);
pform_bind_attributes(cur->attributes, attr);
} }
void pform_make_modgates(const struct vlltype&loc, void pform_make_modgates(const struct vlltype&loc,
perm_string type, perm_string type,
struct parmvalue_t*overrides, struct parmvalue_t*overrides,
svector<lgate>*gates) svector<lgate>*gates,
std::list<named_pexpr_t>*attr)
{ {
assert(! pform_cur_module.empty()); assert(! pform_cur_module.empty());
if (pform_cur_module.front()->program_block) { if (pform_cur_module.front()->program_block) {
@ -2315,7 +2320,7 @@ void pform_make_modgates(const struct vlltype&loc,
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
cur.parms_by_name, cur.parms_by_name,
cur.range.first, cur.range.second, cur.range.first, cur.range.second,
cur.file, cur.lineno); cur.file, cur.lineno, attr);
} else if (cur.parms) { } else if (cur.parms) {
@ -2329,14 +2334,14 @@ void pform_make_modgates(const struct vlltype&loc,
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
cur.parms, cur.parms,
cur.range.first, cur.range.second, cur.range.first, cur.range.second,
cur.file, cur.lineno); cur.file, cur.lineno, attr);
} else { } else {
list<PExpr*>*wires = new list<PExpr*>; list<PExpr*>*wires = new list<PExpr*>;
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
wires, wires,
cur.range.first, cur.range.second, cur.range.first, cur.range.second,
cur.file, cur.lineno); cur.file, cur.lineno, attr);
} }
} }

View File

@ -478,7 +478,8 @@ extern void pform_makegates(const struct vlltype&loc,
extern void pform_make_modgates(const struct vlltype&loc, extern void pform_make_modgates(const struct vlltype&loc,
perm_string type, perm_string type,
struct parmvalue_t*overrides, struct parmvalue_t*overrides,
svector<lgate>*gates); svector<lgate>*gates,
list<named_pexpr_t>*attr);
/* Make a continuous assignment node, with optional bit- or part- select. */ /* Make a continuous assignment node, with optional bit- or part- select. */
extern void pform_make_pgassign_list(list<PExpr*>*alist, extern void pform_make_pgassign_list(list<PExpr*>*alist,

View File

@ -729,6 +729,7 @@ void PGModule::dump(ostream&out, unsigned ind) const
dump_pins(out); dump_pins(out);
} }
out << ");" << endl; out << ");" << endl;
dump_attributes_map(out, attributes, 8);
} }
void Statement::dump(ostream&out, unsigned ind) const void Statement::dump(ostream&out, unsigned ind) const