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:
parent
66ce204771
commit
64e85304b5
|
|
@ -136,7 +136,7 @@ static vhdl_expr *translate_ulong(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,
|
||||
|
|
@ -716,7 +716,7 @@ vhdl_expr *translate_time_expr(ivl_expr_t e)
|
|||
vhdl_type integer(VHDL_TYPE_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,
|
||||
vhdl_type::time());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_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
|
||||
ostringstream ss;
|
||||
ss << "Generated from Verilog module " << ivl_scope_tname(scope)
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
|
|||
vhdl_expr *time;
|
||||
if (ivl_statement_type(stmt) == IVL_ST_DELAY) {
|
||||
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 {
|
||||
time = translate_time_expr(ivl_stmt_delay_expr(stmt));
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ vhdl_scope *vhdl_scope::get_parent() const
|
|||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
|
@ -142,6 +143,28 @@ void vhdl_entity::emit(std::ostream &of, int level) const
|
|||
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()
|
||||
{
|
||||
|
||||
|
|
@ -652,8 +675,10 @@ void vhdl_const_time::emit(std::ostream &of, int level) const
|
|||
{
|
||||
of << dec << value_;
|
||||
switch (units_) {
|
||||
case TIME_UNIT_NS:
|
||||
of << " ns";
|
||||
case TIME_UNIT_PS: of << " ps"; break;
|
||||
case TIME_UNIT_NS: of << " ns"; break;
|
||||
case TIME_UNIT_US: of << " us"; break;
|
||||
case TIME_UNIT_MS: of << " ms"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,10 @@ private:
|
|||
};
|
||||
|
||||
enum time_unit_t {
|
||||
TIME_UNIT_PS,
|
||||
TIME_UNIT_NS,
|
||||
TIME_UNIT_US,
|
||||
TIME_UNIT_MS,
|
||||
};
|
||||
|
||||
class vhdl_const_time : public vhdl_expr {
|
||||
|
|
@ -838,6 +841,9 @@ public:
|
|||
|
||||
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
|
||||
// the Verilog module hierarchy it was found
|
||||
// This is used to limit the maximum depth of modules emitted
|
||||
|
|
@ -846,6 +852,10 @@ private:
|
|||
std::string name_;
|
||||
vhdl_arch *arch_; // Entity may only have a single architecture
|
||||
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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue