📄 at_interconnect.h
字号:
tlm::tlm_sync_enum status;
status = targ_socket[init]->nb_transport_bw( trans, phase, delay );
if (status == tlm::TLM_COMPLETED)
{
assert( phase == tlm::BEGIN_RESP );
assert( rsp_in_progress[init] );
end_rsp_event[init].notify();
}
return status;
}
virtual void invalidate_direct_mem_ptr( int id, sc_dt::uint64 start_range,
sc_dt::uint64 end_range )
{
// Reconstruct address range in system memory map
sc_dt::uint64 bw_start_range = reconstruct_address(start_range, id);
sc_dt::uint64 bw_end_range = reconstruct_address(end_range, id);
// Propagate call backward to all initiators
for (unsigned int i = 0; i < targ_socket.size(); i++)
targ_socket[i]->invalidate_direct_mem_ptr(bw_start_range, bw_end_range);
}
private:
void end_req_process( unsigned int target )
{
// Called whenever END_REQ is received from a target
assert( req_in_progress[target] );
if ( req_queue[target].empty() )
{
req_in_progress[target] = 0;
}
else
{
// Requests are serviced in a first-come-first-served order
// You would re-write this to implement the arbitration strategy of
// your particular interconnect component.
Trans req = req_queue[target].front();
req_queue[target].pop_front();
gp_ptr trans = req.trans;
tlm::tlm_phase phase = tlm::BEGIN_REQ;
sc_time delay;
if (req.time < sc_time_stamp())
delay = SC_ZERO_TIME;
else
delay = req.time - sc_time_stamp();
req_in_progress[target] = trans;
route_extension* ext;
accessor(*trans).get_extension(ext);
assert(ext);
assert( ext->target == int(target) );
int init = ext->init;
tlm::tlm_sync_enum status;
status = init_socket[target]->nb_transport_fw( *trans, phase, delay );
if (status == tlm::TLM_UPDATED)
{
if ((phase == tlm::END_REQ) || (phase == tlm::BEGIN_RESP))
{
assert( req_in_progress[target] );
end_req_event[target].notify();
}
// Need to check response exclusion rule
if (phase == tlm::BEGIN_RESP)
{
if (rsp_in_progress[init])
{
queue_the_rsp_to_be_sent_bw_later( init, trans, delay );
return;
}
rsp_in_progress[init] = trans;
}
// Need to propagate transaction to initiator on backward path
send_bw_to_initiator( trans, phase, delay);
}
else if (status == tlm::TLM_COMPLETED)
{
// The original BEGIN_REQ was stalled because there was an outstanding request on the
// target-side socket. Then on finally sending the delayed BEGIN_REQ to the target,
// the target immediately returns TLM_COMPLETED. This suggests a weird target!
assert( req_in_progress[target] );
end_req_event[target].notify();
// Once target has returned TLM_COMPLETED, do not propagate transaction forward again
ext->dont_propagate_fw = true;
// Need to propagate response to initiator on backward path
phase = tlm::BEGIN_RESP;
// Need to check response exclusion rule
if (rsp_in_progress[init])
{
queue_the_rsp_to_be_sent_bw_later( init, trans, delay );
return;
}
rsp_in_progress[init] = trans;
// Need to propagate transaction to initiator on backward path
send_bw_to_initiator( trans, phase, delay);
}
// Finally finished with the delayed request transaction
trans->release();
}
}
void queue_the_rsp_to_be_sent_bw_later( unsigned int init, tlm::tlm_generic_payload* trans, sc_time& delay )
{
trans->acquire();
Trans rsp;
rsp.trans = trans;
rsp.time = sc_time_stamp() + delay;
rsp_queue[init].push_back( rsp );
}
void end_rsp_process( unsigned int init )
{
// Called whenever END_RESP (or TLM_COMPLETED) is received from an initiator
assert( rsp_in_progress[init] );
if ( rsp_queue[init].empty() )
{
rsp_in_progress[init] = 0;
}
else
{
Trans rsp = rsp_queue[init].front();
rsp_queue[init].pop_front();
gp_ptr trans = rsp.trans;
tlm::tlm_phase phase = tlm::BEGIN_RESP;
sc_time delay;
if (rsp.time < sc_time_stamp())
delay = SC_ZERO_TIME;
else
delay = rsp.time - sc_time_stamp();
rsp_in_progress[init] = trans;
// Need to propagate transaction to initiator on backward path
send_bw_to_initiator( trans, phase, delay);
// Finally finished with the delayed response transaction
trans->release();
}
}
void send_bw_to_initiator( tlm::tlm_generic_payload* trans,
tlm::tlm_phase& phase, sc_time& delay )
{
// Propagate END_REQ or BEGIN_RESP transaction to initiator on backward path
route_extension* ext;
accessor(*trans).get_extension(ext);
assert(ext);
int init = ext->init;
int target = ext->target;
tlm::tlm_sync_enum status = targ_socket[init]->nb_transport_bw( *trans, phase, delay );
if (status == tlm::TLM_UPDATED || status == tlm::TLM_COMPLETED)
{
// Initiator would normally return TLM_COMPLETED here
// TLM_UPDATED only makes sense when an extended phase will be sent later
assert( rsp_in_progress[init] );
end_rsp_event[init].notify();
if (ext->dont_propagate_fw)
return;
// Need to propagate END_RESP transaction to target on forward path
phase = tlm::END_RESP;
status = init_socket[target]->nb_transport_fw( *trans, phase, delay );
assert( status != tlm::TLM_UPDATED );
// Ignore return value
}
}
unsigned int decode_address( sc_dt::uint64 address, sc_dt::uint64& masked_address )
{
// You would re-write this function to implement the particular routing strategy
// of your interconnect component.
// Use the top bits of the address to indicate target
masked_address = address & 0xff;
unsigned int target = (unsigned int)(address >> 8);
// If address is too big, just wrap around the target number
return target % n_targets;
}
sc_dt::uint64 reconstruct_address ( uint64 address, unsigned int target )
{
return address | (target << 8);
}
private:
unsigned int n_targets;
unsigned int n_inits;
typedef tlm::tlm_generic_payload* gp_ptr;
// Extension to store routing information in transaction
struct route_extension: tlm_utils::instance_specific_extension<route_extension>
{
int init;
int target;
bool dont_propagate_fw;
};
tlm_utils::instance_specific_extension_accessor accessor;
// Flags, events and queues to implement the request and response exclusion rules
gp_ptr* req_in_progress;
gp_ptr* rsp_in_progress;
sc_event* end_req_event;
sc_event* end_rsp_event;
struct Trans
{
gp_ptr trans;
sc_time time;
};
std::deque<Trans>* req_queue;
std::deque<Trans>* rsp_queue;
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -