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)
|
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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue