diff --git a/configs/example/memtest-ruby.py b/configs/example/memtest-ruby.py index c0569944e..abc22a93b 100644 --- a/configs/example/memtest-ruby.py +++ b/configs/example/memtest-ruby.py @@ -104,6 +104,7 @@ class L2Cache(RubyCache): # l1_cntrl_nodes = [] dir_cntrl_nodes = [] +dma_cntrl_nodes = [] # # Must create the individual controllers before the network to ensure the @@ -138,12 +139,15 @@ for (i, cpu) in enumerate(cpus): directory = RubyDirectoryMemory(), memBuffer = RubyMemoryControl()) + dma_cntrl = DMA_Controller(version = i, + dma_sequencer = DMASequencer()) # # As noted above: Two independent list are track to maintain the order of # nodes/controllers assumed by the ruby network # l1_cntrl_nodes.append(l1_cntrl) dir_cntrl_nodes.append(dir_cntrl) + dma_cntrl_nodes.append(dma_cntrl) # # Finally tie the memtester ports to the correct system ports @@ -157,7 +161,8 @@ for (i, cpu) in enumerate(cpus): # constructor. # network = SimpleNetwork(topology = makeCrossbar(l1_cntrl_nodes + \ - dir_cntrl_nodes)) + dir_cntrl_nodes + \ + dma_cntrl_nodes)) mem_size_mb = sum([int(dir_cntrl.directory.size_mb) \ for dir_cntrl in dir_cntrl_nodes]) @@ -166,7 +171,9 @@ system.ruby = RubySystem(clock = '1GHz', network = network, profiler = RubyProfiler(), tracer = RubyTracer(), - debug = RubyDebug(), + debug = RubyDebug(filter_string = 'qQin', + verbosity_string = 'high', + protocol_trace = True), mem_size_mb = mem_size_mb) diff --git a/src/mem/protocol/MOESI_hammer-dma.sm b/src/mem/protocol/MOESI_hammer-dma.sm index 079485a05..12cf65c2f 100644 --- a/src/mem/protocol/MOESI_hammer-dma.sm +++ b/src/mem/protocol/MOESI_hammer-dma.sm @@ -28,7 +28,8 @@ machine(DMA, "DMA Controller") -: int request_latency = 6 +: DMASequencer * dma_sequencer, + int request_latency = 6 { MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true"; @@ -47,20 +48,14 @@ machine(DMA, "DMA Controller") Ack, desc="DMA write to memory completed"; } - external_type(DMASequencer) { - void ackCallback(); - void dataCallback(DataBlock); - } - MessageBuffer mandatoryQueue, ordered="false", no_vector="true"; - DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])', no_vector="true"; State cur_state, no_vector="true"; State getState(Address addr) { return cur_state; } void setState(Address addr, State state) { - cur_state := state; + cur_state := state; } out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="..."); diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm index 386ae2ee1..10e3711c5 100644 --- a/src/mem/protocol/RubySlicc_Types.sm +++ b/src/mem/protocol/RubySlicc_Types.sm @@ -122,6 +122,11 @@ external_type(MemoryControl, inport="yes", outport="yes") { } +external_type(DMASequencer) { + void ackCallback(); + void dataCallback(DataBlock); +} + external_type(TimerTable, inport="yes") { bool isReady(); Address readyAddress(); diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index 330e9f6af..007f92b80 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -8,6 +8,10 @@ #include "mem/protocol/SequencerRequestType.hh" #include "mem/ruby/system/System.hh" +// +// Fix me: This code needs comments! +// + DMASequencer::DMASequencer(const Params *p) : RubyPort(p) { @@ -15,6 +19,7 @@ DMASequencer::DMASequencer(const Params *p) void DMASequencer::init() { + RubyPort::init(); m_is_busy = false; m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); } @@ -58,11 +63,16 @@ int64_t DMASequencer::makeRequest(const RubyRequest & request) msg.getLineAddress() = line_address(msg.getPhysicalAddress()); msg.getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD; int offset = paddr & m_data_block_mask; + msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? len : RubySystem::getBlockSizeBytes() - offset; - if (write) + + if (write) { msg.getDataBlk().setData(data, offset, msg.getLen()); + } + + assert(m_mandatory_q_ptr != NULL); m_mandatory_q_ptr->enqueue(msg); active_request.bytes_issued += msg.getLen(); @@ -82,14 +92,18 @@ void DMASequencer::issueNext() SequencerMsg msg; msg.getPhysicalAddress() = Address(active_request.start_paddr + active_request.bytes_completed); + assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0); msg.getLineAddress() = line_address(msg.getPhysicalAddress()); + msg.getType() = (active_request.write ? SequencerRequestType_ST : SequencerRequestType_LD); + msg.getLen() = (active_request.len - active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? active_request.len - active_request.bytes_completed : RubySystem::getBlockSizeBytes()); + if (active_request.write) { msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed], 0, msg.getLen()); @@ -97,6 +111,8 @@ void DMASequencer::issueNext() } else { msg.getType() = SequencerRequestType_LD; } + + assert(m_mandatory_q_ptr != NULL); m_mandatory_q_ptr->enqueue(msg); active_request.bytes_issued += msg.getLen(); } diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 867886436..4f25f68e9 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -38,6 +38,7 @@ python_class_map = {"int": "Int", "Sequencer": "RubySequencer", "DirectoryMemory": "RubyDirectoryMemory", "MemoryControl": "RubyMemoryControl", + "DMASequencer": "DMASequencer" } class StateMachine(Symbol): @@ -359,7 +360,7 @@ $c_ident::$c_ident(const Params *p) # contains_sequencer = False for param in self.config_parameters: - if param.name == "sequencer": + if param.name == "sequencer" or param.name == "dma_sequencer": contains_sequencer = True if param.pointer: code('m_${{param.name}}_ptr = p->${{param.name}};') @@ -378,7 +379,19 @@ $c_ident::$c_ident(const Params *p) code(''' m_sequencer_ptr->setController(this); ''') + # + # For the DMA controller, pass the sequencer a pointer to the + # controller. + # + if self.ident == "DMA": + if not contains_sequencer: + self.error("The DMA controller must include the sequencer " \ + "configuration parameter") + code(''' +m_dma_sequencer_ptr->setController(this); +''') + code('m_num_controllers++;') for var in self.objects: if var.ident.find("mandatoryQueue") >= 0: