Push tranif delays to the code generator.

This patch pushes delays for tranif gates to the code generator.
We still need to add checks for the number of delays, etc. For
now an error message is printed when a tranif gate is given a
non-zero delay.
This commit is contained in:
Cary R 2010-07-12 16:04:22 -07:00 committed by Stephen Williams
parent a8198b38fb
commit 2bf3f5d1d3
7 changed files with 66 additions and 89 deletions

View File

@ -687,16 +687,15 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
cur[idx]->attribute(attrib_list[adx].key, cur[idx]->attribute(attrib_list[adx].key,
attrib_list[adx].val); attrib_list[adx].val);
/* The logic devices have some uniform processing. Then /* Set the delays and drive strength for all built in gates.
all may have output delays and output drive strength. */ We still need to add checks to verify that the delays and
if (NetLogic*log = dynamic_cast<NetLogic*> (cur[idx])) { strength are consistent with the gates definition. */
log->rise_time(rise_time); cur[idx]->rise_time(rise_time);
log->fall_time(fall_time); cur[idx]->fall_time(fall_time);
log->decay_time(decay_time); cur[idx]->decay_time(decay_time);
log->pin(0).drive0(strength0()); cur[idx]->pin(0).drive0(strength0());
log->pin(0).drive1(strength1()); cur[idx]->pin(0).drive1(strength1());
}
cur[idx]->set_line(*this); cur[idx]->set_line(*this);
des->add_node(cur[idx]); des->add_node(cur[idx]);

View File

@ -255,6 +255,7 @@ ivl_stmt_sub_stmt
ivl_switch_a ivl_switch_a
ivl_switch_b ivl_switch_b
ivl_switch_basename ivl_switch_basename
ivl_switch_delay
ivl_switch_enable ivl_switch_enable
ivl_switch_file ivl_switch_file
ivl_switch_island ivl_switch_island

View File

@ -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_width(ivl_switch_t net);
extern unsigned ivl_switch_part(ivl_switch_t net); extern unsigned ivl_switch_part(ivl_switch_t net);
extern unsigned ivl_switch_offset(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 /* Not implemented yet
extern unsigned ivl_switch_attr_cnt(ivl_switch_t net); extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);

View File

@ -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) extern "C" unsigned ivl_expr_width(ivl_expr_t net)
{ {
assert(net); // assert(net);
return net->width_; return net->width_;
} }
@ -2451,6 +2451,12 @@ extern "C" unsigned ivl_switch_offset(ivl_switch_t net)
return net->offset; 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) extern "C" const char* ivl_switch_file(ivl_switch_t net)
{ {
return net->file; return net->file;

100
t-dll.cc
View File

@ -650,12 +650,11 @@ void dll_target::logic_attributes(struct ivl_net_logic_s *obj,
obj->attr = fill_in_attributes(net); obj->attr = fill_in_attributes(net);
} }
void dll_target::make_logic_delays_(struct ivl_net_logic_s*obj, void dll_target::make_delays_(ivl_expr_t*delay, const NetObj*net)
const NetObj*net)
{ {
obj->delay[0] = 0; delay[0] = 0;
obj->delay[1] = 0; delay[1] = 0;
obj->delay[2] = 0; delay[2] = 0;
/* Translate delay expressions to ivl_target form. Try to /* Translate delay expressions to ivl_target form. Try to
preserve pointer equality, not as a rule but to save on 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()) { if (net->rise_time()) {
expr_ = 0; expr_ = 0;
net->rise_time()->expr_scan(this); net->rise_time()->expr_scan(this);
obj->delay[0] = expr_; delay[0] = expr_;
expr_ = 0; expr_ = 0;
} }
if (net->fall_time()) { if (net->fall_time()) {
if (net->fall_time() == net->rise_time()) { if (net->fall_time() == net->rise_time()) {
obj->delay[1] = obj->delay[0]; delay[1] = delay[0];
} else { } else {
expr_ = 0; expr_ = 0;
net->fall_time()->expr_scan(this); net->fall_time()->expr_scan(this);
obj->delay[1] = expr_; delay[1] = expr_;
expr_ = 0; expr_ = 0;
} }
} }
if (net->decay_time()) { if (net->decay_time()) {
if (net->decay_time() == net->rise_time()) { if (net->decay_time() == net->rise_time()) {
obj->delay[2] = obj->delay[0]; delay[2] = delay[0];
} else { } else {
expr_ = 0; expr_ = 0;
net->decay_time()->expr_scan(this); net->decay_time()->expr_scan(this);
obj->delay[2] = expr_; delay[2] = expr_;
expr_ = 0; 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, void dll_target::make_lpm_delays_(struct ivl_lpm_s*obj,
const NetObj*net) const NetObj*net)
{ {
obj->delay[0] = 0; make_delays_(obj->delay, net);
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;
}
}
} }
void dll_target::make_const_delays_(struct ivl_net_const_s*obj, void dll_target::make_const_delays_(struct ivl_net_const_s*obj,
const NetObj*net) const NetObj*net)
{ {
obj->delay[0] = 0; make_delays_(obj->delay, net);
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;
}
}
} }
bool dll_target::branch(const NetBranch*net) bool dll_target::branch(const NetBranch*net)
@ -1026,6 +973,7 @@ bool dll_target::tran(const NetTran*net)
obj->lineno = net->get_lineno(); obj->lineno = net->get_lineno();
switch_attributes(obj, net); switch_attributes(obj, net);
make_switch_delays_(obj, net);
scope_add_switch(obj->scope, obj); scope_add_switch(obj->scope, obj);
return true; return true;

View File

@ -1,7 +1,7 @@
#ifndef __t_dll_H #ifndef __t_dll_H
#define __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 * 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
@ -165,7 +165,9 @@ struct dll_target : public target_t, public expr_scan_t {
void sub_off_from_expr_(long); void sub_off_from_expr_(long);
void mul_expr_by_const_(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_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_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_const_delays_(struct ivl_net_const_s*obj, const NetObj*net);
void make_scope_parameters(ivl_scope_t scope, const NetScope*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; struct ivl_attribute_s*attr;
unsigned nattr; unsigned nattr;
ivl_expr_t delay[3];
ivl_nexus_t pins[3]; ivl_nexus_t pins[3];
perm_string file; perm_string file;
unsigned lineno; unsigned lineno;

View File

@ -34,6 +34,23 @@ void draw_switch_in_scope(ivl_switch_t sw)
ivl_nexus_t nex_a, nex_b, enable; ivl_nexus_t nex_a, nex_b, enable;
const char*str_a, *str_b, *str_e; 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); island = ivl_switch_island(sw);
if (ivl_island_flag_test(island, 0) == 0) if (ivl_island_flag_test(island, 0) == 0)
draw_tran_island(island); draw_tran_island(island);
@ -68,8 +85,9 @@ void draw_switch_in_scope(ivl_switch_t sw)
break; break;
default: default:
fprintf(stderr, "%s:%u: sorry: vvp target does not support switch modeling.\n", fprintf(stderr, "%s:%u: sorry: resistive switch modeling is not "
ivl_switch_file(sw), ivl_switch_lineno(sw)); "currently supported.\n",
ivl_switch_file(sw), ivl_switch_lineno(sw));
vvp_errors += 1; vvp_errors += 1;
return; return;
} }