Cleanup
This commit is contained in:
parent
306e4cfa6b
commit
11c944f5e9
|
|
@ -758,7 +758,7 @@ static int process_generation(const char*name)
|
|||
else if (strcmp(name,"no-specify") == 0)
|
||||
gen_specify = "no-specify";
|
||||
|
||||
else if (strcmp(name,"interconnect") == 0)
|
||||
else if (strcmp(name,"interconnect") == 0)
|
||||
gen_interconnect = "interconnect";
|
||||
|
||||
else if (strcmp(name,"no-interconnect") == 0)
|
||||
|
|
|
|||
38
elaborate.cc
38
elaborate.cc
|
|
@ -1600,23 +1600,23 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
// Add module input buffers if needed
|
||||
if (need_bufz_for_input_port(prts) || gn_interconnect_flag == true) {
|
||||
// FIXME improve this for multiple module instances
|
||||
NetScope* inner_scope = scope->instance_arrays[get_name()][0];
|
||||
// FIXME improve this for multiple module instances
|
||||
NetScope* inner_scope = scope->instance_arrays[get_name()][0];
|
||||
|
||||
NetBUFZ*tmp = new NetBUFZ(inner_scope, inner_scope->local_symbol(),
|
||||
sig->vector_width(), true, gn_interconnect_flag ? idx : -1);
|
||||
tmp->set_line(*this);
|
||||
des->add_node(tmp);
|
||||
connect(tmp->pin(1), sig->pin(0));
|
||||
NetBUFZ*tmp = new NetBUFZ(inner_scope, inner_scope->local_symbol(),
|
||||
sig->vector_width(), true, gn_interconnect_flag ? idx : -1);
|
||||
tmp->set_line(*this);
|
||||
des->add_node(tmp);
|
||||
connect(tmp->pin(1), sig->pin(0));
|
||||
|
||||
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
|
||||
sig->vector_width()-1,0);
|
||||
NetNet*tmp2 = new NetNet(inner_scope, inner_scope->local_symbol(),
|
||||
NetNet::WIRE, tmp2_vec);
|
||||
tmp2->local_flag(true);
|
||||
tmp2->set_line(*this);
|
||||
connect(tmp->pin(0), tmp2->pin(0));
|
||||
sig = tmp2;
|
||||
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
|
||||
sig->vector_width()-1,0);
|
||||
NetNet*tmp2 = new NetNet(inner_scope, inner_scope->local_symbol(),
|
||||
NetNet::WIRE, tmp2_vec);
|
||||
tmp2->local_flag(true);
|
||||
tmp2->set_line(*this);
|
||||
connect(tmp->pin(0), tmp2->pin(0));
|
||||
sig = tmp2;
|
||||
}
|
||||
|
||||
// If we have a real signal driving a bit/vector port
|
||||
|
|
@ -1938,12 +1938,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
// the delay being applied to other drivers of
|
||||
// the external signal.
|
||||
if (prts[0]->delay_paths() > 0 || (gn_interconnect_flag == true && ptype == NetNet::POUTPUT)) {
|
||||
// FIXME improve this for multiple module instances
|
||||
NetScope* inner_scope = scope->instance_arrays[get_name()][0];
|
||||
// FIXME improve this for multiple module instances
|
||||
NetScope* inner_scope = scope->instance_arrays[get_name()][0];
|
||||
|
||||
isolate_and_connect(des, inner_scope, this, prts[0], sig, ptype, gn_interconnect_flag ? idx : -1);
|
||||
isolate_and_connect(des, inner_scope, this, prts[0], sig, ptype, gn_interconnect_flag ? idx : -1);
|
||||
} else {
|
||||
connect(prts[0]->pin(0), sig->pin(0));
|
||||
connect(prts[0]->pin(0), sig->pin(0));
|
||||
}
|
||||
|
||||
} else if (sig->vector_width()==prts_vector_width/instance.size()
|
||||
|
|
|
|||
13
t-dll.cc
13
t-dll.cc
|
|
@ -893,13 +893,12 @@ bool dll_target::bufz(const NetBUFZ*net)
|
|||
|
||||
scope_add_logic(scop, obj);
|
||||
|
||||
// Add bufz to the corresponding port_info entry,
|
||||
// if it is an input / output buffer
|
||||
// This is needed for the SDF interconnect feature
|
||||
// to access the buffers directly from the port_info
|
||||
if (obj->is_port_buffer)
|
||||
{
|
||||
scop->module_ports_info[net->port_info_index()].buffer = obj;
|
||||
// Add bufz to the corresponding port_info entry,
|
||||
// if it is an input / output buffer
|
||||
// This is needed for the SDF interconnect feature
|
||||
// to access the buffers directly from the port_info
|
||||
if (obj->is_port_buffer) {
|
||||
scop->module_ports_info[net->port_info_index()].buffer = obj;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ int signal_is_return_value(ivl_signal_t sig)
|
|||
*/
|
||||
int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
|
||||
{
|
||||
// If bufz is a module input/output buffer do not elide
|
||||
// If bufz is a module input/output buffer do not elide
|
||||
if (ivl_logic_port_buffer(net)) return 0;
|
||||
|
||||
ivl_nexus_t in_n, out_n;
|
||||
|
|
@ -2403,20 +2403,20 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
if( ivl_scope_type(net) == IVL_SCT_MODULE ) {
|
||||
|
||||
// Port data for VPI: needed for vpiPorts property of vpiModule
|
||||
for( idx = 0; idx < ivl_scope_mod_module_ports(net); ++idx ) {
|
||||
const char *name = ivl_scope_mod_module_port_name(net,idx);
|
||||
ivl_signal_port_t ptype = ivl_scope_mod_module_port_type(net,idx);
|
||||
unsigned width = ivl_scope_mod_module_port_width(net,idx);
|
||||
ivl_net_logic_t buffer = ivl_scope_mod_module_port_buffer(net,idx);
|
||||
if( name == 0 )
|
||||
name = "";
|
||||
fprintf( vvp_out, " .port_info %u %s %u \"%s\"",
|
||||
idx, vvp_port_info_type_str(ptype), width,
|
||||
vvp_mangle_name(name) );
|
||||
if (buffer) fprintf( vvp_out, " L_%p;\n", buffer);
|
||||
else fprintf( vvp_out, ";\n");
|
||||
}
|
||||
// Port data for VPI: needed for vpiPorts property of vpiModule
|
||||
for( idx = 0; idx < ivl_scope_mod_module_ports(net); ++idx ) {
|
||||
const char *name = ivl_scope_mod_module_port_name(net,idx);
|
||||
ivl_signal_port_t ptype = ivl_scope_mod_module_port_type(net,idx);
|
||||
unsigned width = ivl_scope_mod_module_port_width(net,idx);
|
||||
ivl_net_logic_t buffer = ivl_scope_mod_module_port_buffer(net,idx);
|
||||
if( name == 0 )
|
||||
name = "";
|
||||
fprintf( vvp_out, " .port_info %u %s %u \"%s\"",
|
||||
idx, vvp_port_info_type_str(ptype), width,
|
||||
vvp_mangle_name(name) );
|
||||
if (buffer) fprintf( vvp_out, " L_%p;\n", buffer);
|
||||
else fprintf( vvp_out, ";\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -160,26 +160,31 @@ program_version
|
|||
hierarchy_divider
|
||||
: '(' K_DIVIDER '.' ')'
|
||||
{ sdf_use_hchar = '.';
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n", sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n",
|
||||
sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
}
|
||||
| '(' K_DIVIDER '/' ')'
|
||||
{ sdf_use_hchar = '/';
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n", sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n",
|
||||
sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
}
|
||||
| '(' K_DIVIDER HCHAR ')'
|
||||
{ /* sdf_use_hchar no-change */
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n", sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Divider: \"%c\"\n",
|
||||
sdf_parse_path, @1.first_line, sdf_use_hchar);
|
||||
}
|
||||
;
|
||||
|
||||
voltage
|
||||
: '(' K_VOLTAGE rtriple ')'
|
||||
{ /* The value must be defined. */
|
||||
if (! $3.defined) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Chosen value not defined.\n", sdf_parse_path, @1.first_line);
|
||||
}
|
||||
else if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Voltage: %f\n",
|
||||
sdf_parse_path, @2.first_line, $3.value);
|
||||
if (! $3.defined) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Chosen value not defined.\n",
|
||||
sdf_parse_path, @1.first_line);
|
||||
} else if (sdf_flag_inform) {
|
||||
vpi_printf("SDF INFO: %s:%d: Voltage: %f\n",
|
||||
sdf_parse_path, @2.first_line, $3.value);
|
||||
}
|
||||
}
|
||||
| '(' K_VOLTAGE signed_real_number ')'
|
||||
{ if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Voltage: %f\n",
|
||||
|
|
@ -198,10 +203,10 @@ process
|
|||
temperature
|
||||
: '(' K_TEMPERATURE rtriple ')'
|
||||
{ /* The value must be defined. */
|
||||
if (! $3.defined) vpi_printf("SDF ERROR: %s:%d: Chosen value not defined.\n",
|
||||
sdf_parse_path, @1.first_line);
|
||||
else if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Temperature: %f\n",
|
||||
sdf_parse_path, @2.first_line, $3.value);
|
||||
if (! $3.defined) vpi_printf("SDF ERROR: %s:%d: Chosen value not defined.\n",
|
||||
sdf_parse_path, @1.first_line);
|
||||
else if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Temperature: %f\n",
|
||||
sdf_parse_path, @2.first_line, $3.value);
|
||||
}
|
||||
| '(' K_TEMPERATURE signed_real_number ')'
|
||||
{ if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Temperature: %f\n",
|
||||
|
|
@ -338,18 +343,21 @@ del_def
|
|||
/* | '(' K_INTERCONNECT port_instance port_instance delval_list ')' */
|
||||
| '(' K_INTERCONNECT port_interconnect port_interconnect delval_list ')'
|
||||
{
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: INTERCONNECT with "
|
||||
"port1 = %s index = %d, port2 = %s index = %d\n",
|
||||
sdf_parse_path, @2.first_line, $3.name, $3.index, $4.name, $4.index);
|
||||
if (sdf_flag_inform) {
|
||||
vpi_printf("SDF INFO: %s:%d: INTERCONNECT with "
|
||||
"port1 = %s index = %d, port2 = %s index = %d\n",
|
||||
sdf_parse_path, @2.first_line, $3.name, $3.index, $4.name, $4.index);
|
||||
}
|
||||
|
||||
sdf_interconnect_delays($3, $4, &$5, @2.first_line);
|
||||
sdf_interconnect_delays($3, $4, &$5, @2.first_line);
|
||||
|
||||
free($3.name);
|
||||
free($4.name);
|
||||
free($3.name);
|
||||
free($4.name);
|
||||
}
|
||||
| '(' K_INTERCONNECT error ')'
|
||||
{ vpi_printf("SDF ERROR: %s:%d: Invalid/malformed INTERCONNECT\n",
|
||||
sdf_parse_path, @2.first_line); }
|
||||
sdf_parse_path, @2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
tchk_def_list
|
||||
|
|
@ -465,13 +473,13 @@ port
|
|||
port_interconnect
|
||||
: hierarchical_identifier
|
||||
{
|
||||
struct interconnect_port_s tmp = {$1, -1};
|
||||
$$ = tmp;
|
||||
struct interconnect_port_s tmp = {$1, -1};
|
||||
$$ = tmp;
|
||||
}
|
||||
| hierarchical_identifier '[' INTEGER ']'
|
||||
{
|
||||
struct interconnect_port_s tmp = {$1, $3};
|
||||
$$ = tmp;
|
||||
struct interconnect_port_s tmp = {$1, $3};
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,13 +60,15 @@ struct interconnect_port_s {
|
|||
|
||||
extern void sdf_select_instance(const char*celltype, const char*inst,
|
||||
const int sdf_lineno);
|
||||
|
||||
extern void sdf_iopath_delays(int vpi_edge, const char*src, const char*dst,
|
||||
const struct sdf_delval_list_s*delval,
|
||||
const int sdf_lineno);
|
||||
|
||||
extern void sdf_interconnect_delays(struct interconnect_port_s port1, struct interconnect_port_s port2,
|
||||
const struct sdf_delval_list_s*delval_list,
|
||||
const int sdf_lineno);
|
||||
extern void sdf_interconnect_delays(struct interconnect_port_s port1,
|
||||
struct interconnect_port_s port2,
|
||||
const struct sdf_delval_list_s*delval_list,
|
||||
const int sdf_lineno);
|
||||
|
||||
#endif /* IVL_sdf_priv_h */
|
||||
|
||||
|
|
|
|||
177
vpi/sys_sdf.c
177
vpi/sys_sdf.c
|
|
@ -76,9 +76,11 @@ void sdf_select_instance(const char*celltype, const char*cellinst, const int sdf
|
|||
|
||||
/* Test for wildcard character */
|
||||
if (cellinst == NULL) {
|
||||
if (sdf_flag_warning) vpi_printf("SDF WARNING: %s:%d: sorry: "
|
||||
"Wildcard cell instance specification (*) currently not supported.\n",
|
||||
sdf_fname, sdf_lineno);
|
||||
if (sdf_flag_warning) {
|
||||
vpi_printf("SDF WARNING: %s:%d: sorry: "
|
||||
"Wildcard cell instance specification (*) currently not supported.\n",
|
||||
sdf_fname, sdf_lineno);
|
||||
}
|
||||
sdf_cur_cell = 0;
|
||||
return;
|
||||
}
|
||||
|
|
@ -89,45 +91,45 @@ void sdf_select_instance(const char*celltype, const char*cellinst, const int sdf
|
|||
const char*src = cellinst;
|
||||
const char*dp;
|
||||
while ( (dp=strchr(src, '.')) ) {
|
||||
unsigned len = dp - src;
|
||||
assert(dp >= src);
|
||||
assert(len < sizeof buffer);
|
||||
strncpy(buffer, src, len);
|
||||
buffer[len] = 0;
|
||||
unsigned len = dp - src;
|
||||
assert(dp >= src);
|
||||
assert(len < sizeof buffer);
|
||||
strncpy(buffer, src, len);
|
||||
buffer[len] = 0;
|
||||
|
||||
vpiHandle tmp_scope = find_scope(scope, buffer);
|
||||
if (tmp_scope == 0) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Cannot find %s in scope %s.\n",
|
||||
sdf_fname, sdf_lineno, buffer, vpi_get_str(vpiFullName, scope));
|
||||
break;
|
||||
}
|
||||
assert(tmp_scope);
|
||||
scope = tmp_scope;
|
||||
vpiHandle tmp_scope = find_scope(scope, buffer);
|
||||
if (tmp_scope == 0) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Cannot find %s in scope %s.\n",
|
||||
sdf_fname, sdf_lineno, buffer, vpi_get_str(vpiFullName, scope));
|
||||
break;
|
||||
}
|
||||
assert(tmp_scope);
|
||||
scope = tmp_scope;
|
||||
|
||||
src = dp + 1;
|
||||
src = dp + 1;
|
||||
}
|
||||
|
||||
/* Now find the cell. */
|
||||
if (src[0] == 0)
|
||||
sdf_cur_cell = sdf_scope;
|
||||
sdf_cur_cell = sdf_scope;
|
||||
else
|
||||
sdf_cur_cell = find_scope(scope, src);
|
||||
sdf_cur_cell = find_scope(scope, src);
|
||||
if (sdf_cur_cell == 0) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Unable to find %s in scope %s.\n",
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope));
|
||||
return;
|
||||
vpi_printf("SDF ERROR: %s:%d: Unable to find %s in scope %s.\n",
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope));
|
||||
return;
|
||||
}
|
||||
|
||||
/* The scope that matches should be a module. */
|
||||
if (vpi_get(vpiType,sdf_cur_cell) != vpiModule) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Scope %s in %s is not a module.\n",
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope));
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope));
|
||||
}
|
||||
|
||||
/* The matching scope (a module) should have the expected type. */
|
||||
if (strcmp(celltype,vpi_get_str(vpiDefName,sdf_cur_cell)) != 0) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Module %s in %s is not a %s; it is a ",
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope), celltype);
|
||||
sdf_fname, sdf_lineno, src, vpi_get_str(vpiFullName, scope), celltype);
|
||||
vpi_printf("%s\n", vpi_get_str(vpiDefName, sdf_cur_cell));
|
||||
}
|
||||
|
||||
|
|
@ -148,45 +150,40 @@ vpiHandle get_port_handle(char* port_name, const int sdf_lineno)
|
|||
{
|
||||
vpiHandle scope = sdf_cur_cell;
|
||||
|
||||
// Get occurences of '.' in the name
|
||||
// Get occurences of '.' in the name
|
||||
int submodules = 0;
|
||||
|
||||
for (int i=0; port_name[i] != '\0'; i++)
|
||||
{
|
||||
if (port_name[i] == '.') submodules++;
|
||||
for (int i=0; port_name[i] != '\0'; i++) {
|
||||
if (port_name[i] == '.') submodules++;
|
||||
}
|
||||
|
||||
// Extract the first token
|
||||
// Extract the first token
|
||||
char* token = strtok(port_name, ".");;
|
||||
|
||||
// Change scope into submodule
|
||||
while (submodules--)
|
||||
{
|
||||
scope = vpi_handle_by_name(token, scope);
|
||||
// Change scope into submodule
|
||||
while (submodules--) {
|
||||
scope = vpi_handle_by_name(token, scope);
|
||||
|
||||
if (!scope) vpi_printf("SDF ERROR: %s:%d: Submodule %s in port path not found!\n", sdf_fname, sdf_lineno, token);
|
||||
if (!scope) vpi_printf("SDF ERROR: %s:%d: Submodule %s in port path not found!\n", sdf_fname, sdf_lineno, token);
|
||||
|
||||
// Extract next token
|
||||
token = strtok(NULL, ".");
|
||||
token = strtok(NULL, ".");
|
||||
}
|
||||
|
||||
// Iterate over ports
|
||||
// Iterate over ports
|
||||
vpiHandle port_i = vpi_iterate(vpiPort, scope) ;
|
||||
vpiHandle port;
|
||||
vpiHandle port_handle = NULL;
|
||||
|
||||
while ((port=vpi_scan(port_i)) != NULL)
|
||||
{
|
||||
char *port_name_ = vpi_get_str(vpiName, port) ;
|
||||
while ((port=vpi_scan(port_i)) != NULL) {
|
||||
char *port_name_ = vpi_get_str(vpiName, port) ;
|
||||
|
||||
if (strcmp(port_name_, token) == 0)
|
||||
{
|
||||
if (port_handle != NULL)
|
||||
{
|
||||
if (sdf_flag_warning) vpi_printf("SDF WARNING: %s:%d: Found multiple matching ports for %s !\n", sdf_fname, sdf_lineno, token);
|
||||
}
|
||||
port_handle = port;
|
||||
}
|
||||
if (strcmp(port_name_, token) == 0) {
|
||||
if (port_handle != NULL) {
|
||||
if (sdf_flag_warning) vpi_printf("SDF WARNING: %s:%d: Found multiple matching ports for %s !\n", sdf_fname, sdf_lineno, token);
|
||||
}
|
||||
port_handle = port;
|
||||
}
|
||||
}
|
||||
|
||||
return port_handle;
|
||||
|
|
@ -198,52 +195,46 @@ void sdf_interconnect_delays(struct interconnect_port_s port1, struct interconne
|
|||
const int sdf_lineno)
|
||||
{
|
||||
|
||||
// Get handles for both ports
|
||||
// After calling get_port_handle, the name is invalid
|
||||
// Get handles for both ports
|
||||
// After calling get_port_handle, the name is invalid
|
||||
vpiHandle port1_handle = get_port_handle(port1.name, sdf_lineno);
|
||||
vpiHandle port2_handle = get_port_handle(port2.name, sdf_lineno);
|
||||
|
||||
if (port1_handle && port2_handle)
|
||||
{
|
||||
if (port1_handle && port2_handle) {
|
||||
// Get interModPath for the two ports
|
||||
vpiHandle intermodpath = vpi_handle_multi(vpiInterModPath, port1_handle, port2_handle);
|
||||
vpiHandle intermodpath = vpi_handle_multi(vpiInterModPath, port1_handle, port2_handle);
|
||||
|
||||
if (intermodpath)
|
||||
{
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Created a vpiInterModPath\n", sdf_fname, sdf_lineno);
|
||||
if (intermodpath) {
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Created a vpiInterModPath\n", sdf_fname, sdf_lineno);
|
||||
|
||||
s_vpi_delay delays;
|
||||
struct t_vpi_time delay_vals[12];
|
||||
s_vpi_delay delays;
|
||||
struct t_vpi_time delay_vals[12];
|
||||
|
||||
// Initialize delay structure
|
||||
delays.da = delay_vals;
|
||||
delays.no_of_delays = delval_list->count;
|
||||
delays.time_type = vpiScaledRealTime;
|
||||
delays.mtm_flag = 0;
|
||||
delays.append_flag = 0;
|
||||
delays.pulsere_flag = 0;
|
||||
vpi_get_delays(intermodpath, &delays);
|
||||
// Initialize delay structure
|
||||
delays.da = delay_vals;
|
||||
delays.no_of_delays = delval_list->count;
|
||||
delays.time_type = vpiScaledRealTime;
|
||||
delays.mtm_flag = 0;
|
||||
delays.append_flag = 0;
|
||||
delays.pulsere_flag = 0;
|
||||
vpi_get_delays(intermodpath, &delays);
|
||||
|
||||
for (int idx = 0 ; idx < delval_list->count ; idx += 1) {
|
||||
delay_vals[idx].type = vpiScaledRealTime;
|
||||
if (delval_list->val[idx].defined) {
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Putting delay: %f for index %d\n",
|
||||
sdf_fname, sdf_lineno, delval_list->val[idx].value, idx);
|
||||
delay_vals[idx].real = delval_list->val[idx].value;
|
||||
}
|
||||
}
|
||||
for (int idx = 0 ; idx < delval_list->count ; idx += 1) {
|
||||
delay_vals[idx].type = vpiScaledRealTime;
|
||||
if (delval_list->val[idx].defined) {
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: %s:%d: Putting delay: %f for index %d\n",
|
||||
sdf_fname, sdf_lineno, delval_list->val[idx].value, idx);
|
||||
delay_vals[idx].real = delval_list->val[idx].value;
|
||||
}
|
||||
}
|
||||
|
||||
// Put the new delays
|
||||
vpi_put_delays(intermodpath, &delays);
|
||||
}
|
||||
else
|
||||
{
|
||||
vpi_printf("SDF ERROR: %s:%d: Could not find intermodpath!\n", sdf_fname, sdf_lineno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vpi_printf("SDF ERROR: %s:%d: Could not find handles for both ports!\n", sdf_fname, sdf_lineno);
|
||||
// Put the new delays
|
||||
vpi_put_delays(intermodpath, &delays);
|
||||
} else {
|
||||
vpi_printf("SDF ERROR: %s:%d: Could not find intermodpath!\n", sdf_fname, sdf_lineno);
|
||||
}
|
||||
} else {
|
||||
vpi_printf("SDF ERROR: %s:%d: Could not find handles for both ports!\n", sdf_fname, sdf_lineno);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,10 +305,10 @@ void sdf_iopath_delays(int vpi_edge, const char*src, const char*dst,
|
|||
}
|
||||
|
||||
if (match_count == 0) {
|
||||
vpi_printf("SDF ERROR: %s:%d: Unable to match ModPath %s%s -> %s in %s\n",
|
||||
sdf_fname, sdf_lineno,
|
||||
edge_str(vpi_edge), src, dst,
|
||||
vpi_get_str(vpiFullName, sdf_cur_cell));
|
||||
vpi_printf("SDF ERROR: %s:%d: Unable to match ModPath %s%s -> %s in %s\n",
|
||||
sdf_fname, sdf_lineno,
|
||||
edge_str(vpi_edge), src, dst,
|
||||
vpi_get_str(vpiFullName, sdf_cur_cell));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -409,10 +400,12 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (sdf_flag_inform) vpi_printf("SDF INFO: Loading %s from %s:%d\n",
|
||||
fname,
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
if (sdf_flag_inform) {
|
||||
vpi_printf("SDF INFO: Loading %s from %s:%d\n",
|
||||
fname,
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
}
|
||||
|
||||
sdf_fd = fopen(fname, "r");
|
||||
if (sdf_fd == 0) {
|
||||
|
|
|
|||
|
|
@ -1120,10 +1120,10 @@ vvp_fun_intermodpath::vvp_fun_intermodpath(vvp_net_t*net, unsigned width)
|
|||
: net_(net)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 12 ; idx += 1)
|
||||
delay_[idx] = 0;
|
||||
delay_[idx] = 0;
|
||||
|
||||
cur_vec4_ = vvp_vector4_t(width, BIT4_X);
|
||||
schedule_init_propagate(net_, cur_vec4_); // TODO is this needed?
|
||||
schedule_init_propagate(net_, cur_vec4_);
|
||||
}
|
||||
|
||||
vvp_fun_intermodpath::~vvp_fun_intermodpath()
|
||||
|
|
@ -1252,12 +1252,11 @@ static vpiHandle intermodpath_iterate(int code, vpiHandle ref)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine will put specific dimension of delay[] values
|
||||
* into a vpiHandle. In this case, we will put
|
||||
* specific delays values in a vpiInterModPath object
|
||||
* TODO code duplication
|
||||
*
|
||||
*/
|
||||
static void intermodpath_put_delays (vpiHandle ref, p_vpi_delay delays)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -236,6 +236,8 @@ class vvp_fun_modpath_edge : public vvp_fun_modpath_src {
|
|||
|
||||
/*
|
||||
* The intermodpath is used to implement the SDF INTERCONNECT feature
|
||||
* Upon a (INTERCONNECT ...) statement an intermodpath will be inserted
|
||||
* between port1 and port2 and its delay can be annotated
|
||||
*/
|
||||
class vvp_fun_intermodpath : public vvp_net_fun_t, private vvp_gen_event_s {
|
||||
|
||||
|
|
|
|||
185
vvp/vpi_priv.cc
185
vvp/vpi_priv.cc
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2022 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2023 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2023 Leo Moser (leo.moser@pm.me)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -33,16 +34,6 @@
|
|||
# include <cmath>
|
||||
# include <iostream>
|
||||
|
||||
# include "npmos.h"
|
||||
# include "vvp_island.h"
|
||||
# include "resolv.h"
|
||||
# include "bufif.h"
|
||||
# include "latch.h"
|
||||
# include "dff.h"
|
||||
# include "event.h"
|
||||
# include "arith.h"
|
||||
# include "part.h"
|
||||
|
||||
using namespace std;
|
||||
vpi_mode_t vpi_mode_flag = VPI_MODE_NONE;
|
||||
FILE*vpi_trace = 0;
|
||||
|
|
@ -1570,144 +1561,132 @@ vpiHandle vpi_handle_multi(PLI_INT32 type,
|
|||
vpiHandle ref2)
|
||||
{
|
||||
if (vpi_trace) {
|
||||
fprintf(vpi_trace, "vpi_handle_multi(%d, %p, %p) -->\n",
|
||||
type, ref1, ref2);
|
||||
fprintf(vpi_trace, "vpi_handle_multi(%d, %p, %p) -->\n",
|
||||
type, ref1, ref2);
|
||||
}
|
||||
|
||||
if (type != vpiInterModPath) {
|
||||
fprintf(stderr, "sorry: vpi_handle_multi currently supports"
|
||||
"only vpiInterModPath\n");
|
||||
return nullptr;
|
||||
fprintf(stderr, "sorry: vpi_handle_multi currently supports"
|
||||
"only vpiInterModPath\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vpiPortInfo* port1 = dynamic_cast<vpiPortInfo*>(ref1);
|
||||
|
||||
if (!port1) {
|
||||
fprintf(stderr, "sorry: second argument of vpi_handle_multi"
|
||||
"must be a vpiPort\n");
|
||||
return nullptr;
|
||||
fprintf(stderr, "sorry: second argument of vpi_handle_multi"
|
||||
"must be a vpiPort\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vpiPortInfo* port2 = dynamic_cast<vpiPortInfo*>(ref2);
|
||||
|
||||
if (!port2) {
|
||||
fprintf(stderr, "sorry: third argument of vpi_handle_multi"
|
||||
"must be a vpiPort\n");
|
||||
return nullptr;
|
||||
fprintf(stderr, "sorry: third argument of vpi_handle_multi"
|
||||
"must be a vpiPort\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If both ports are vpiOutput, we have to reassign the __vpiSignal from port1
|
||||
// to port2 because otherwise the non-delayed version of the signal is dumped
|
||||
// even tho the intermodpath is correctly inserted
|
||||
// If both ports are vpiOutput, we have to reassign the __vpiSignal from port1
|
||||
// to port2 because otherwise the non-delayed version of the signal is dumped
|
||||
// even tho the intermodpath is correctly inserted
|
||||
__vpiSignal* output_signal = nullptr;
|
||||
|
||||
if (port1->get_direction() == vpiOutput && port2->get_direction() == vpiOutput)
|
||||
{
|
||||
vpiHandle scope_port2 = vpi_handle(vpiScope, ref2);
|
||||
assert(scope_port2);
|
||||
std::string port2_name(vpi_get_str(vpiName, ref2));
|
||||
if (port1->get_direction() == vpiOutput && port2->get_direction() == vpiOutput) {
|
||||
vpiHandle scope_port2 = vpi_handle(vpiScope, ref2);
|
||||
assert(scope_port2);
|
||||
std::string port2_name(vpi_get_str(vpiName, ref2));
|
||||
|
||||
// Iterate over nets in the scope of port2
|
||||
vpiHandle net_i = vpi_iterate(vpiNet, scope_port2) ;
|
||||
vpiHandle net;
|
||||
vpiHandle net_i = vpi_iterate(vpiNet, scope_port2) ;
|
||||
vpiHandle net;
|
||||
|
||||
while ((net = vpi_scan(net_i)) != NULL)
|
||||
{
|
||||
std::string net_name(vpi_get_str(vpiName, net));
|
||||
while ((net = vpi_scan(net_i)) != NULL) {
|
||||
std::string net_name(vpi_get_str(vpiName, net));
|
||||
|
||||
// Compare whether the net matches with the port name
|
||||
if (net_name == port2_name)
|
||||
{
|
||||
output_signal = dynamic_cast<__vpiSignal*>(net);
|
||||
}
|
||||
}
|
||||
// Compare whether the net matches with the port name
|
||||
if (net_name == port2_name) {
|
||||
output_signal = dynamic_cast<__vpiSignal*>(net);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_net_t* net1 = port1->get_port();
|
||||
vvp_net_t* net2 = port2->get_port();
|
||||
|
||||
if (net1 == nullptr || net2 == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not find net. "
|
||||
"Did you run iverilog with '-ginterconnect'?\n");
|
||||
return nullptr;
|
||||
if (net1 == nullptr || net2 == nullptr) {
|
||||
fprintf(stderr, "Error: Could not find net. "
|
||||
"Did you run iverilog with '-ginterconnect'?\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (net1 == net2)
|
||||
{
|
||||
fprintf(stderr, "Error: Net for both ports is the same. "
|
||||
"Did you pass the same port twice?\n");
|
||||
return nullptr;
|
||||
if (net1 == net2) {
|
||||
fprintf(stderr, "Error: Net for both ports is the same. "
|
||||
"Did you pass the same port twice?\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!dynamic_cast<vvp_fun_buft*>(net1->fun))
|
||||
{
|
||||
fprintf(stderr, "Error: functor of net1 must be"
|
||||
"vvp_fun_buft\n");
|
||||
return nullptr;
|
||||
if (!dynamic_cast<vvp_fun_buft*>(net1->fun)) {
|
||||
fprintf(stderr, "Error: functor of net1 must be"
|
||||
"vvp_fun_buft\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!dynamic_cast<vvp_fun_buft*>(net2->fun))
|
||||
{
|
||||
fprintf(stderr, "Error: functor of net2 must be"
|
||||
"vvp_fun_buft\n");
|
||||
return nullptr;
|
||||
if (!dynamic_cast<vvp_fun_buft*>(net2->fun)) {
|
||||
fprintf(stderr, "Error: functor of net2 must be"
|
||||
"vvp_fun_buft\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Iterate over all nodes connected to port1
|
||||
// Iterate over all nodes connected to port1
|
||||
vvp_net_ptr_t cur = net1->out_;
|
||||
vvp_net_ptr_t prev = vvp_net_ptr_t(nullptr, 0);
|
||||
|
||||
while (cur.ptr())
|
||||
{
|
||||
while (cur.ptr()) {
|
||||
// Port2 is directly connected to port1
|
||||
if (cur.ptr() == net2)
|
||||
{
|
||||
vvp_net_t*new_net = new vvp_net_t;
|
||||
if (cur.ptr() == net2) {
|
||||
vvp_net_t*new_net = new vvp_net_t;
|
||||
|
||||
int width = 1; // TODO
|
||||
vvp_fun_intermodpath*obj = new vvp_fun_intermodpath(new_net, width);
|
||||
new_net->fun = obj;
|
||||
new_net->out_ = cur; // TODO pointer to current net
|
||||
// Create new node with intermodpath and connect port2 to it
|
||||
int width = 1; // TODO
|
||||
vvp_fun_intermodpath*obj = new vvp_fun_intermodpath(new_net, width);
|
||||
new_net->fun = obj;
|
||||
new_net->out_ = cur;
|
||||
|
||||
// Port2 is in the middle of the list
|
||||
// Insert intermodpath before port2 and keep everything else intact
|
||||
if (prev.ptr())
|
||||
{
|
||||
prev.ptr()->port[prev.port()] = vvp_net_ptr_t(new_net, 0); // Point to port 0 of vvp_fun_intermodpath
|
||||
new_net->port[0] = cur.ptr()->port[cur.port()]; // Connect the next net in list
|
||||
cur.ptr()->port[cur.port()] = vvp_net_ptr_t(nullptr, 0); // Only port2 is connected to intermodpath
|
||||
}
|
||||
// Port2 is first in list
|
||||
// Insert intermodpath before port2 and keep everything else intact
|
||||
else
|
||||
{
|
||||
net1->out_ = vvp_net_ptr_t(new_net, 0); // Point to port 0 of vvp_fun_intermodpath
|
||||
new_net->port[0] = cur.ptr()->port[cur.port()]; // Connect the next net in list
|
||||
cur.ptr()->port[cur.port()] = vvp_net_ptr_t(nullptr, 0); // Only port2 is connected to intermodpath
|
||||
}
|
||||
// Port2 is in the middle of the list
|
||||
// Insert intermodpath before port2 and keep everything else intact
|
||||
if (prev.ptr()) {
|
||||
prev.ptr()->port[prev.port()] = vvp_net_ptr_t(new_net, 0); // Point to port 0 of vvp_fun_intermodpath
|
||||
new_net->port[0] = cur.ptr()->port[cur.port()]; // Connect the next net in list
|
||||
cur.ptr()->port[cur.port()] = vvp_net_ptr_t(nullptr, 0); // Only port2 is connected to intermodpath
|
||||
// Port2 is first in list
|
||||
// Insert intermodpath before port2 and keep everything else intact
|
||||
} else {
|
||||
net1->out_ = vvp_net_ptr_t(new_net, 0); // Point to port 0 of vvp_fun_intermodpath
|
||||
new_net->port[0] = cur.ptr()->port[cur.port()]; // Connect the next net in list
|
||||
cur.ptr()->port[cur.port()] = vvp_net_ptr_t(nullptr, 0); // Only port2 is connected to intermodpath
|
||||
}
|
||||
|
||||
// If both ports are vpiOutput, we have to reassign the __vpiSignal
|
||||
if (output_signal)
|
||||
{
|
||||
net2->fil = net1->fil;
|
||||
net1->fil = nullptr;
|
||||
output_signal->node = net2;
|
||||
}
|
||||
// If both ports are vpiOutput, we have to reassign the __vpiSignal
|
||||
if (output_signal) {
|
||||
net2->fil = net1->fil;
|
||||
net1->fil = nullptr;
|
||||
output_signal->node = net2;
|
||||
}
|
||||
|
||||
// Create the VPI intermodpath object
|
||||
__vpiInterModPath* intermodpath = vpip_make_intermodpath(new_net, port1, port2);
|
||||
intermodpath->intermodpath = obj;
|
||||
// Create the VPI intermodpath object
|
||||
__vpiInterModPath* intermodpath = vpip_make_intermodpath(new_net, port1, port2);
|
||||
intermodpath->intermodpath = obj;
|
||||
|
||||
// Finally done, return the intermodpath object
|
||||
return intermodpath;
|
||||
}
|
||||
// Finally done, return the intermodpath object
|
||||
return intermodpath;
|
||||
}
|
||||
|
||||
prev = cur;
|
||||
cur = cur.ptr()->port[cur.port()]; // Next net in linked list
|
||||
prev = cur;
|
||||
cur = cur.ptr()->port[cur.port()]; // Next net in linked list
|
||||
}
|
||||
|
||||
std::cout << "sorry: Could not insert intermodpath!" << std::endl;
|
||||
fprintf(stderr, "VPI error: Could not insert intermodpath!\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -742,7 +742,7 @@ vpiHandle vpiPortInfo::vpi_handle(int code)
|
|||
*/
|
||||
void compile_port_info( unsigned index, int vpi_direction, unsigned width, const char *name, char* buffer )
|
||||
{
|
||||
vpiHandle obj = new vpiPortInfo( vpip_peek_current_scope(),
|
||||
index, vpi_direction, width, name, buffer );
|
||||
vpip_attach_to_current_scope(obj);
|
||||
vpiHandle obj = new vpiPortInfo( vpip_peek_current_scope(),
|
||||
index, vpi_direction, width, name, buffer );
|
||||
vpip_attach_to_current_scope(obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,7 @@ class vvp_net_t {
|
|||
public: // Method to support $countdrivers
|
||||
void count_drivers(unsigned idx, unsigned counts[4]);
|
||||
|
||||
// This needs to be public so that SDF interconnects can be inserted
|
||||
public:
|
||||
vvp_net_ptr_t out_;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue