diff --git a/src/sdf/sdf-node.c b/src/sdf/sdf-node.c index f9d77a442..bed67c8d9 100644 --- a/src/sdf/sdf-node.c +++ b/src/sdf/sdf-node.c @@ -44,7 +44,7 @@ static const imask_t has_map[S_LAST_NODE_KIND] = { (I_IDENT | I_VALUE), // S_SIGNAL - (I_SUBKIND | I_IDENT | I_DIMS | I_FLAGS | I_VALUE), + (I_SUBKIND | I_IDENT | I_DIMS | I_FLAGS | I_VALUE | I_CONDS), // S_DELVAL (I_LITERALS), diff --git a/src/sdf/sdf-parse.c b/src/sdf/sdf-parse.c index c3291e367..3c6102b4d 100644 --- a/src/sdf/sdf-parse.c +++ b/src/sdf/sdf-parse.c @@ -384,7 +384,7 @@ static ident_t p_qstring(void) BEGIN("qstring"); - // Qstring identifier is stored including the surrounding + // qstring identifier is stored including the surrounding // apostrophes. // TODO: Check how is tSTRING handled in lexer. Right now it re-uses VHDL string. @@ -1030,9 +1030,14 @@ static ident_t p_cell_instance(void) consume(tLPAREN); consume(tINSTANCE); - // TODO: Hierarchical identifier shall be optional here! - ident_t hier = optional(tTIMES) ? ident_new("*") : - p_hierarchical_identifier(); + ident_t hier = NULL; + if (scan(tTIMES, tID)) { + if (optional(tTIMES)) + hier = ident_new("*"); + else + hier = p_hierarchical_identifier(); + } + consume(tRPAREN); return hier; @@ -1181,7 +1186,8 @@ static sdf_node_t p_path_constraint(void) sdf_add_signal(constr, p_port_instance()); sdf_add_signal(constr, p_port_instance()); - // TODO: Add optional follow-up of "port_instance" + while (scan(tID)) + sdf_add_signal(constr, p_port_instance()); sdf_add_value(constr, p_rvalue()); sdf_add_value(constr, p_rvalue()); @@ -1272,8 +1278,10 @@ static sdf_node_t p_sum_constraint(void) sdf_add_signal(constr, p_constraint_path()); sdf_add_signal(constr, p_constraint_path()); - // TODO: Add optional follow-up constraint paths. - // To decide if it is rvalue or constraint_path, we need second token lookup! + // Both next follow-up tokens start with tLPAREN. + // Decide based on second next token + if (peek_nth(2) == tID) + sdf_add_signal(constr, p_constraint_path()); sdf_add_value(constr, p_rvalue()); if (scan(tLPAREN)) @@ -1596,11 +1604,15 @@ static sdf_node_t p_port_tchk(void) consume(tLPAREN); consume(tCOND); - // TODO: Add optional qstring + sdf_node_t cond = sdf_new(S_COND); + + if (scan(tSTRING)) + sdf_set_ident(cond, p_qstring()); + + sdf_set_expr(cond, p_timing_check_condition()); - sdf_node_t expr = p_timing_check_condition(); sdf_node_t port = p_port_spec(); - sdf_set_expr(port, expr); + sdf_add_cond(port, cond); consume(tRPAREN); @@ -1691,7 +1703,7 @@ static sdf_node_t p_skew_timing_check(void) \ sdf_node_t tcheck = sdf_new(S_TIMING_CHECK); \ sdf_set_subkind(tcheck, subkind); \ - sdf_add_signal(tcheck, p_port_tchk()); \ + sdf_add_signal(tcheck, p_port_tchk()); \ sdf_add_value(tcheck, p_value()); \ \ consume(tRPAREN); \ @@ -1718,8 +1730,8 @@ DEFINE_1P1V_TCHK(p_period_timing_check, "period timing check", tPERIOD, S_TCHECK \ sdf_node_t tcheck = sdf_new(S_TIMING_CHECK); \ sdf_set_subkind(tcheck, subkind); \ - sdf_add_signal(tcheck, p_port_tchk()); \ - sdf_add_signal(tcheck, p_port_tchk()); \ + sdf_add_signal(tcheck, p_port_tchk()); \ + sdf_add_signal(tcheck, p_port_tchk()); \ sdf_add_value(tcheck, p_rvalue()); \ sdf_add_value(tcheck, p_rvalue()); \ \ @@ -1750,8 +1762,8 @@ DEFINE_2P2RV_TCHK(p_recrem_timing_check, "recrem timing check", tRECREM, \ sdf_node_t tcheck = sdf_new(S_TIMING_CHECK); \ sdf_set_subkind(tcheck, subkind); \ - sdf_add_signal(tcheck, p_port_tchk()); \ - sdf_add_signal(tcheck, p_port_tchk()); \ + sdf_add_signal(tcheck, p_port_tchk()); \ + sdf_add_signal(tcheck, p_port_tchk()); \ sdf_add_value(tcheck, p_value()); \ \ consume(tRPAREN); \ @@ -1907,8 +1919,8 @@ static void p_condelse_def(sdf_node_t delay) consume(tLPAREN); consume(tCONDELSE); - // TODO: Should we introduce flag to S_COND that says if it is COND or CONDELSE? - // Or is it enough to distinguish by sdf_has_expr ? + // S_COND and S_CONDELSE are distinguished by missing expression in + // S_CONDELSE sdf_node_t cond = sdf_new(S_COND); sdf_add_cond(delay, cond); @@ -1994,10 +2006,6 @@ static void p_netdelay_def(sdf_node_t delay) consume(tRPAREN); } -// Grammar for port_spec derives the same as for net_spec -// TODO: Should we somehow track difference between "net" and "port" -// (flag, separate sdf_kind_t) ? Should we then differentiate/check if a delay -// for "net" is applied to something of type "port" and vice-versa? static void p_device_def(sdf_node_t delay) { // device_def ::=