DMASequencer.cc (6369:82ac95f4d9f0) DMASequencer.cc (6433:0f0f0fbef977)
1
2#include "mem/ruby/system/DMASequencer.hh"
3#include "mem/ruby/buffers/MessageBuffer.hh"
4#include "mem/ruby/slicc_interface/AbstractController.hh"
5
6/* SLICC generated types */
7#include "mem/protocol/DMARequestMsg.hh"
8#include "mem/protocol/DMARequestType.hh"
9#include "mem/protocol/DMAResponseMsg.hh"
10#include "mem/ruby/system/System.hh"
11
12DMASequencer::DMASequencer(const string & name)
13 : RubyPort(name)
14{
15}
16
17void DMASequencer::init(const vector<string> & argv)
18{
19 m_version = -1;
20 m_controller = NULL;
21 for (size_t i=0;i<argv.size();i+=2) {
22 if (argv[i] == "controller")
23 m_controller = RubySystem::getController(argv[i+1]);
24 else if (argv[i] == "version")
25 m_version = atoi(argv[i+1].c_str());
26 }
27 assert(m_controller != NULL);
28 assert(m_version != -1);
29
30 m_mandatory_q_ptr = m_controller->getMandatoryQueue();
31 m_is_busy = false;
32 m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
33}
34
35int64_t DMASequencer::makeRequest(const RubyRequest & request)
36{
37 uint64_t paddr = request.paddr;
38 uint8_t* data = request.data;
39 int len = request.len;
40 bool write = false;
41 switch(request.type) {
42 case RubyRequestType_LD:
43 write = false;
44 break;
45 case RubyRequestType_ST:
46 write = true;
47 break;
48 case RubyRequestType_NULL:
49 case RubyRequestType_IFETCH:
50 case RubyRequestType_Locked_Read:
51 case RubyRequestType_Locked_Write:
52 case RubyRequestType_RMW_Read:
53 case RubyRequestType_RMW_Write:
1
2#include "mem/ruby/system/DMASequencer.hh"
3#include "mem/ruby/buffers/MessageBuffer.hh"
4#include "mem/ruby/slicc_interface/AbstractController.hh"
5
6/* SLICC generated types */
7#include "mem/protocol/DMARequestMsg.hh"
8#include "mem/protocol/DMARequestType.hh"
9#include "mem/protocol/DMAResponseMsg.hh"
10#include "mem/ruby/system/System.hh"
11
12DMASequencer::DMASequencer(const string & name)
13 : RubyPort(name)
14{
15}
16
17void DMASequencer::init(const vector<string> & argv)
18{
19 m_version = -1;
20 m_controller = NULL;
21 for (size_t i=0;i<argv.size();i+=2) {
22 if (argv[i] == "controller")
23 m_controller = RubySystem::getController(argv[i+1]);
24 else if (argv[i] == "version")
25 m_version = atoi(argv[i+1].c_str());
26 }
27 assert(m_controller != NULL);
28 assert(m_version != -1);
29
30 m_mandatory_q_ptr = m_controller->getMandatoryQueue();
31 m_is_busy = false;
32 m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
33}
34
35int64_t DMASequencer::makeRequest(const RubyRequest & request)
36{
37 uint64_t paddr = request.paddr;
38 uint8_t* data = request.data;
39 int len = request.len;
40 bool write = false;
41 switch(request.type) {
42 case RubyRequestType_LD:
43 write = false;
44 break;
45 case RubyRequestType_ST:
46 write = true;
47 break;
48 case RubyRequestType_NULL:
49 case RubyRequestType_IFETCH:
50 case RubyRequestType_Locked_Read:
51 case RubyRequestType_Locked_Write:
52 case RubyRequestType_RMW_Read:
53 case RubyRequestType_RMW_Write:
54 case RubyRequestType_NUM:
54 assert(0);
55 }
56
57 assert(!m_is_busy); // only support one outstanding DMA request
58 m_is_busy = true;
59
60 active_request.start_paddr = paddr;
61 active_request.write = write;
62 active_request.data = data;
63 active_request.len = len;
64 active_request.bytes_completed = 0;
65 active_request.bytes_issued = 0;
66 active_request.id = makeUniqueRequestID();
67
68 DMARequestMsg msg;
69 msg.getPhysicalAddress() = Address(paddr);
70 msg.getLineAddress() = line_address(msg.getPhysicalAddress());
71 msg.getType() = write ? DMARequestType_WRITE : DMARequestType_READ;
72 msg.getOffset() = paddr & m_data_block_mask;
73 msg.getLen() = (msg.getOffset() + len) <= RubySystem::getBlockSizeBytes() ?
74 len :
75 RubySystem::getBlockSizeBytes() - msg.getOffset();
76 if (write) {
77 msg.getType() = DMARequestType_WRITE;
78 msg.getDataBlk().setData(data, msg.getOffset(), msg.getLen());
79 } else {
80 msg.getType() = DMARequestType_READ;
81 }
82 m_mandatory_q_ptr->enqueue(msg);
83 active_request.bytes_issued += msg.getLen();
84
85 return active_request.id;
86}
87
88void DMASequencer::issueNext()
89{
90 assert(m_is_busy == true);
91 active_request.bytes_completed = active_request.bytes_issued;
92 if (active_request.len == active_request.bytes_completed) {
93 m_hit_callback(active_request.id);
94 m_is_busy = false;
95 return;
96 }
97
98 DMARequestMsg msg;
99 msg.getPhysicalAddress() = Address(active_request.start_paddr +
100 active_request.bytes_completed);
101 assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
102 msg.getLineAddress() = line_address(msg.getPhysicalAddress());
103 msg.getOffset() = 0;
104 msg.getType() = (active_request.write ? DMARequestType_WRITE :
105 DMARequestType_READ);
106 msg.getLen() = (active_request.len -
107 active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
108 active_request.len - active_request.bytes_completed :
109 RubySystem::getBlockSizeBytes());
110 if (active_request.write) {
111 msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed],
112 0, msg.getLen());
113 msg.getType() = DMARequestType_WRITE;
114 } else {
115 msg.getType() = DMARequestType_READ;
116 }
117 m_mandatory_q_ptr->enqueue(msg);
118 active_request.bytes_issued += msg.getLen();
119}
120
121void DMASequencer::dataCallback(const DataBlock & dblk)
122{
123 assert(m_is_busy == true);
124 int len = active_request.bytes_issued - active_request.bytes_completed;
125 int offset = 0;
126 if (active_request.bytes_completed == 0)
127 offset = active_request.start_paddr & m_data_block_mask;
128 assert( active_request.write == false );
129 memcpy(&active_request.data[active_request.bytes_completed],
130 dblk.getData(offset, len), len);
131 issueNext();
132}
133
134void DMASequencer::ackCallback()
135{
136 issueNext();
137}
138
139void DMASequencer::printConfig(ostream & out)
140{
141
142}
55 assert(0);
56 }
57
58 assert(!m_is_busy); // only support one outstanding DMA request
59 m_is_busy = true;
60
61 active_request.start_paddr = paddr;
62 active_request.write = write;
63 active_request.data = data;
64 active_request.len = len;
65 active_request.bytes_completed = 0;
66 active_request.bytes_issued = 0;
67 active_request.id = makeUniqueRequestID();
68
69 DMARequestMsg msg;
70 msg.getPhysicalAddress() = Address(paddr);
71 msg.getLineAddress() = line_address(msg.getPhysicalAddress());
72 msg.getType() = write ? DMARequestType_WRITE : DMARequestType_READ;
73 msg.getOffset() = paddr & m_data_block_mask;
74 msg.getLen() = (msg.getOffset() + len) <= RubySystem::getBlockSizeBytes() ?
75 len :
76 RubySystem::getBlockSizeBytes() - msg.getOffset();
77 if (write) {
78 msg.getType() = DMARequestType_WRITE;
79 msg.getDataBlk().setData(data, msg.getOffset(), msg.getLen());
80 } else {
81 msg.getType() = DMARequestType_READ;
82 }
83 m_mandatory_q_ptr->enqueue(msg);
84 active_request.bytes_issued += msg.getLen();
85
86 return active_request.id;
87}
88
89void DMASequencer::issueNext()
90{
91 assert(m_is_busy == true);
92 active_request.bytes_completed = active_request.bytes_issued;
93 if (active_request.len == active_request.bytes_completed) {
94 m_hit_callback(active_request.id);
95 m_is_busy = false;
96 return;
97 }
98
99 DMARequestMsg msg;
100 msg.getPhysicalAddress() = Address(active_request.start_paddr +
101 active_request.bytes_completed);
102 assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
103 msg.getLineAddress() = line_address(msg.getPhysicalAddress());
104 msg.getOffset() = 0;
105 msg.getType() = (active_request.write ? DMARequestType_WRITE :
106 DMARequestType_READ);
107 msg.getLen() = (active_request.len -
108 active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
109 active_request.len - active_request.bytes_completed :
110 RubySystem::getBlockSizeBytes());
111 if (active_request.write) {
112 msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed],
113 0, msg.getLen());
114 msg.getType() = DMARequestType_WRITE;
115 } else {
116 msg.getType() = DMARequestType_READ;
117 }
118 m_mandatory_q_ptr->enqueue(msg);
119 active_request.bytes_issued += msg.getLen();
120}
121
122void DMASequencer::dataCallback(const DataBlock & dblk)
123{
124 assert(m_is_busy == true);
125 int len = active_request.bytes_issued - active_request.bytes_completed;
126 int offset = 0;
127 if (active_request.bytes_completed == 0)
128 offset = active_request.start_paddr & m_data_block_mask;
129 assert( active_request.write == false );
130 memcpy(&active_request.data[active_request.bytes_completed],
131 dblk.getData(offset, len), len);
132 issueNext();
133}
134
135void DMASequencer::ackCallback()
136{
137 issueNext();
138}
139
140void DMASequencer::printConfig(ostream & out)
141{
142
143}