diff --git a/elaborate.cc b/elaborate.cc index c1df62da6..945c0d167 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -687,16 +687,15 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const cur[idx]->attribute(attrib_list[adx].key, attrib_list[adx].val); - /* The logic devices have some uniform processing. Then - all may have output delays and output drive strength. */ - if (NetLogic*log = dynamic_cast (cur[idx])) { - log->rise_time(rise_time); - log->fall_time(fall_time); - log->decay_time(decay_time); + /* Set the delays and drive strength for all built in gates. + We still need to add checks to verify that the delays and + strength are consistent with the gates definition. */ + cur[idx]->rise_time(rise_time); + cur[idx]->fall_time(fall_time); + cur[idx]->decay_time(decay_time); - log->pin(0).drive0(strength0()); - log->pin(0).drive1(strength1()); - } + cur[idx]->pin(0).drive0(strength0()); + cur[idx]->pin(0).drive1(strength1()); cur[idx]->set_line(*this); des->add_node(cur[idx]); diff --git a/ivl.def b/ivl.def index ddb57b0a1..1fd54e66e 100644 --- a/ivl.def +++ b/ivl.def @@ -255,6 +255,7 @@ ivl_stmt_sub_stmt ivl_switch_a ivl_switch_b ivl_switch_basename +ivl_switch_delay ivl_switch_enable ivl_switch_file ivl_switch_island diff --git a/ivl_target.h b/ivl_target.h index 720dfc3a3..68cf57d61 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -2039,6 +2039,7 @@ extern ivl_island_t ivl_switch_island(ivl_switch_t net); extern unsigned ivl_switch_width(ivl_switch_t net); extern unsigned ivl_switch_part(ivl_switch_t net); extern unsigned ivl_switch_offset(ivl_switch_t net); +extern ivl_expr_t ivl_switch_delay(ivl_switch_t net, unsigned transition); /* Not implemented yet extern unsigned ivl_switch_attr_cnt(ivl_switch_t net); diff --git a/t-dll-api.cc b/t-dll-api.cc index c9e8adbc4..a2dd1c157 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -564,7 +564,7 @@ extern "C" ivl_variable_type_t ivl_expr_value(ivl_expr_t net) extern "C" unsigned ivl_expr_width(ivl_expr_t net) { - assert(net); +// assert(net); return net->width_; } @@ -2451,6 +2451,12 @@ extern "C" unsigned ivl_switch_offset(ivl_switch_t net) return net->offset; } +extern "C" ivl_expr_t ivl_switch_delay(ivl_switch_t net, unsigned transition) +{ + assert(transition < 3); + return net->delay[transition]; +} + extern "C" const char* ivl_switch_file(ivl_switch_t net) { return net->file; diff --git a/t-dll.cc b/t-dll.cc index 23721efa4..e4448d69b 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -650,12 +650,11 @@ void dll_target::logic_attributes(struct ivl_net_logic_s *obj, obj->attr = fill_in_attributes(net); } -void dll_target::make_logic_delays_(struct ivl_net_logic_s*obj, - const NetObj*net) +void dll_target::make_delays_(ivl_expr_t*delay, const NetObj*net) { - obj->delay[0] = 0; - obj->delay[1] = 0; - obj->delay[2] = 0; + delay[0] = 0; + delay[1] = 0; + delay[2] = 0; /* Translate delay expressions to ivl_target form. Try to preserve pointer equality, not as a rule but to save on @@ -663,105 +662,53 @@ void dll_target::make_logic_delays_(struct ivl_net_logic_s*obj, if (net->rise_time()) { expr_ = 0; net->rise_time()->expr_scan(this); - obj->delay[0] = expr_; + delay[0] = expr_; expr_ = 0; } if (net->fall_time()) { if (net->fall_time() == net->rise_time()) { - obj->delay[1] = obj->delay[0]; + delay[1] = delay[0]; } else { expr_ = 0; net->fall_time()->expr_scan(this); - obj->delay[1] = expr_; + delay[1] = expr_; expr_ = 0; } } if (net->decay_time()) { if (net->decay_time() == net->rise_time()) { - obj->delay[2] = obj->delay[0]; + delay[2] = delay[0]; } else { expr_ = 0; net->decay_time()->expr_scan(this); - obj->delay[2] = expr_; + delay[2] = expr_; expr_ = 0; } } } +void dll_target::make_logic_delays_(struct ivl_net_logic_s*obj, + const NetObj*net) +{ + make_delays_(obj->delay, net); +} + +void dll_target::make_switch_delays_(struct ivl_switch_s*obj, + const NetObj*net) +{ + make_delays_(obj->delay, net); +} + void dll_target::make_lpm_delays_(struct ivl_lpm_s*obj, const NetObj*net) { - obj->delay[0] = 0; - obj->delay[1] = 0; - obj->delay[2] = 0; - - /* Translate delay expressions to ivl_target form. Try to - preserve pointer equality, not as a rule but to save on - expression trees. */ - if (net->rise_time()) { - expr_ = 0; - net->rise_time()->expr_scan(this); - obj->delay[0] = expr_; - expr_ = 0; - } - if (net->fall_time()) { - if (net->fall_time() == net->rise_time()) { - obj->delay[1] = obj->delay[0]; - } else { - expr_ = 0; - net->fall_time()->expr_scan(this); - obj->delay[1] = expr_; - expr_ = 0; - } - } - if (net->decay_time()) { - if (net->decay_time() == net->rise_time()) { - obj->delay[2] = obj->delay[0]; - } else { - expr_ = 0; - net->decay_time()->expr_scan(this); - obj->delay[2] = expr_; - expr_ = 0; - } - } + make_delays_(obj->delay, net); } void dll_target::make_const_delays_(struct ivl_net_const_s*obj, const NetObj*net) { - obj->delay[0] = 0; - obj->delay[1] = 0; - obj->delay[2] = 0; - - /* Translate delay expressions to ivl_target form. Try to - preserve pointer equality, not as a rule but to save on - expression trees. */ - if (net->rise_time()) { - expr_ = 0; - net->rise_time()->expr_scan(this); - obj->delay[0] = expr_; - expr_ = 0; - } - if (net->fall_time()) { - if (net->fall_time() == net->rise_time()) { - obj->delay[1] = obj->delay[0]; - } else { - expr_ = 0; - net->fall_time()->expr_scan(this); - obj->delay[1] = expr_; - expr_ = 0; - } - } - if (net->decay_time()) { - if (net->decay_time() == net->rise_time()) { - obj->delay[2] = obj->delay[0]; - } else { - expr_ = 0; - net->decay_time()->expr_scan(this); - obj->delay[2] = expr_; - expr_ = 0; - } - } + make_delays_(obj->delay, net); } bool dll_target::branch(const NetBranch*net) @@ -1026,6 +973,7 @@ bool dll_target::tran(const NetTran*net) obj->lineno = net->get_lineno(); switch_attributes(obj, net); + make_switch_delays_(obj, net); scope_add_switch(obj->scope, obj); return true; diff --git a/t-dll.h b/t-dll.h index ab7670840..9625650c5 100644 --- a/t-dll.h +++ b/t-dll.h @@ -1,7 +1,7 @@ #ifndef __t_dll_H #define __t_dll_H /* - * Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2010 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,9 @@ struct dll_target : public target_t, public expr_scan_t { void sub_off_from_expr_(long); void mul_expr_by_const_(long); + void make_delays_(ivl_expr_t*delay, const NetObj*net); void make_logic_delays_(struct ivl_net_logic_s*obj, const NetObj*net); + void make_switch_delays_(struct ivl_switch_s*obj, const NetObj*net); void make_lpm_delays_(struct ivl_lpm_s*obj, const NetObj*net); void make_const_delays_(struct ivl_net_const_s*obj, const NetObj*net); void make_scope_parameters(ivl_scope_t scope, const NetScope*net); @@ -479,6 +481,8 @@ struct ivl_switch_s { struct ivl_attribute_s*attr; unsigned nattr; + ivl_expr_t delay[3]; + ivl_nexus_t pins[3]; perm_string file; unsigned lineno; diff --git a/tgt-vvp/draw_switch.c b/tgt-vvp/draw_switch.c index 732fd0cf4..a7da8ff66 100644 --- a/tgt-vvp/draw_switch.c +++ b/tgt-vvp/draw_switch.c @@ -34,6 +34,23 @@ void draw_switch_in_scope(ivl_switch_t sw) ivl_nexus_t nex_a, nex_b, enable; const char*str_a, *str_b, *str_e; + ivl_expr_t rise_exp = ivl_switch_delay(sw, 0); + ivl_expr_t fall_exp = ivl_switch_delay(sw, 1); + + /* We do not support tran delays. */ + if ((rise_exp || fall_exp) && + (!number_is_immediate(rise_exp, 64, 0) || + number_is_unknown(rise_exp) || + (get_number_immediate(rise_exp) != 0) || + !number_is_immediate(fall_exp, 64, 0) || + number_is_unknown(fall_exp) || + (get_number_immediate(rise_exp) != 0))) { + fprintf(stderr, "%s:%u: sorry: tranif gates with a delay are not " + "currently support.\n", + ivl_switch_file(sw), ivl_switch_lineno(sw)); + exit(1); + } + island = ivl_switch_island(sw); if (ivl_island_flag_test(island, 0) == 0) draw_tran_island(island); @@ -68,8 +85,9 @@ void draw_switch_in_scope(ivl_switch_t sw) break; default: - fprintf(stderr, "%s:%u: sorry: vvp target does not support switch modeling.\n", - ivl_switch_file(sw), ivl_switch_lineno(sw)); + fprintf(stderr, "%s:%u: sorry: resistive switch modeling is not " + "currently supported.\n", + ivl_switch_file(sw), ivl_switch_lineno(sw)); vvp_errors += 1; return; }