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:
parent
a8198b38fb
commit
2bf3f5d1d3
17
elaborate.cc
17
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<NetLogic*> (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]);
|
||||
|
|
|
|||
1
ivl.def
1
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
100
t-dll.cc
100
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;
|
||||
|
|
|
|||
6
t-dll.h
6
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue