VHDL translation for timescale

This patch generates delays with the correct VHDL units. Taking
into account the source module's timescale and precision.
This commit is contained in:
Nick Gasson 2009-02-23 19:59:37 +00:00 committed by Stephen Williams
parent 66ce204771
commit 64e85304b5
5 changed files with 45 additions and 6 deletions

View File

@ -136,7 +136,7 @@ static vhdl_expr *translate_ulong(ivl_expr_t e)
static vhdl_expr *translate_delay(ivl_expr_t e) static vhdl_expr *translate_delay(ivl_expr_t e)
{ {
return new vhdl_const_time(ivl_expr_delay_val(e), TIME_UNIT_NS); return scale_time(get_active_entity(), ivl_expr_delay_val(e));
} }
static vhdl_expr *translate_reduction(support_function_t f, bool neg, static vhdl_expr *translate_reduction(support_function_t f, bool neg,
@ -716,7 +716,7 @@ vhdl_expr *translate_time_expr(ivl_expr_t e)
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
time = time->cast(&integer); time = time->cast(&integer);
vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS); vhdl_expr *ns1 = scale_time(get_active_entity(), 1);
return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1, return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1,
vhdl_type::time()); vhdl_type::time());
} }

View File

@ -839,6 +839,10 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth)
vhdl_arch *arch = new vhdl_arch(tname, "FromVerilog"); vhdl_arch *arch = new vhdl_arch(tname, "FromVerilog");
vhdl_entity *ent = new vhdl_entity(tname, arch, depth); vhdl_entity *ent = new vhdl_entity(tname, arch, depth);
// Calculate the VHDL units to use for time values
ent->set_time_units(ivl_scope_time_units(scope),
ivl_scope_time_precision(scope));
// Build a comment to add to the entity/architecture // Build a comment to add to the entity/architecture
ostringstream ss; ostringstream ss;
ss << "Generated from Verilog module " << ivl_scope_tname(scope) ss << "Generated from Verilog module " << ivl_scope_tname(scope)

View File

@ -494,7 +494,7 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
vhdl_expr *time; vhdl_expr *time;
if (ivl_statement_type(stmt) == IVL_ST_DELAY) { if (ivl_statement_type(stmt) == IVL_ST_DELAY) {
uint64_t value = ivl_stmt_delay_val(stmt); uint64_t value = ivl_stmt_delay_val(stmt);
time = new vhdl_const_time(value, TIME_UNIT_NS); time = scale_time(get_active_entity(), value);
} }
else { else {
time = translate_time_expr(ivl_stmt_delay_expr(stmt)); time = translate_time_expr(ivl_stmt_delay_expr(stmt));

View File

@ -101,7 +101,8 @@ vhdl_scope *vhdl_scope::get_parent() const
} }
vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__) vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__)
: depth(depth__), name_(name), arch_(arch) : depth(depth__), name_(name), arch_(arch),
time_unit_(TIME_UNIT_NS)
{ {
arch->get_scope()->set_parent(&ports_); arch->get_scope()->set_parent(&ports_);
} }
@ -142,6 +143,28 @@ void vhdl_entity::emit(std::ostream &of, int level) const
arch_->emit(of, level); arch_->emit(of, level);
} }
// Return a VHDL time constant scaled to the correct time scale
// for this entity
vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t)
{
return new vhdl_const_time(t, ent->time_unit_);
}
// Work out the best VHDL units to use given the Verilog timescale
void vhdl_entity::set_time_units(int units, int precision)
{
int vhdl_units = std::min(units, precision);
if (vhdl_units >= -3)
time_unit_ = TIME_UNIT_MS;
else if (vhdl_units >= -6)
time_unit_ = TIME_UNIT_US;
else if (vhdl_units >= -9)
time_unit_ = TIME_UNIT_NS;
else
time_unit_ = TIME_UNIT_PS;
}
vhdl_arch::~vhdl_arch() vhdl_arch::~vhdl_arch()
{ {
@ -652,8 +675,10 @@ void vhdl_const_time::emit(std::ostream &of, int level) const
{ {
of << dec << value_; of << dec << value_;
switch (units_) { switch (units_) {
case TIME_UNIT_NS: case TIME_UNIT_PS: of << " ps"; break;
of << " ns"; case TIME_UNIT_NS: of << " ns"; break;
case TIME_UNIT_US: of << " us"; break;
case TIME_UNIT_MS: of << " ms"; break;
} }
} }

View File

@ -203,7 +203,10 @@ private:
}; };
enum time_unit_t { enum time_unit_t {
TIME_UNIT_PS,
TIME_UNIT_NS, TIME_UNIT_NS,
TIME_UNIT_US,
TIME_UNIT_MS,
}; };
class vhdl_const_time : public vhdl_expr { class vhdl_const_time : public vhdl_expr {
@ -837,6 +840,9 @@ public:
const std::string &get_name() const { return name_; } const std::string &get_name() const { return name_; }
vhdl_scope *get_scope() { return &ports_; } vhdl_scope *get_scope() { return &ports_; }
void set_time_units(int units, int precision);
friend vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t);
// Each entity has an associated depth which is how deep in // Each entity has an associated depth which is how deep in
// the Verilog module hierarchy it was found // the Verilog module hierarchy it was found
@ -846,6 +852,10 @@ private:
std::string name_; std::string name_;
vhdl_arch *arch_; // Entity may only have a single architecture vhdl_arch *arch_; // Entity may only have a single architecture
vhdl_scope ports_; vhdl_scope ports_;
// Entities have an associated VHDL time unit
// This is used to implement the Verilog timescale directive
time_unit_t time_unit_;
}; };
typedef std::list<vhdl_entity*> entity_list_t; typedef std::list<vhdl_entity*> entity_list_t;