| /******************************************************************************* |
| * Copyright (c) 2005 The Regents of the University of California. |
| * This material was produced under U.S. Government contract W-7405-ENG-36 |
| * for Los Alamos National Laboratory, which is operated by the University |
| * of California for the U.S. Department of Energy. The U.S. Government has |
| * rights to use, reproduce, and distribute this software. NEITHER THE |
| * GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR |
| * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified |
| * to produce derivative works, such modified software should be clearly marked, |
| * so as not to confuse it with the version available from LANL. |
| * |
| * Additionally, this program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * LA-CC 04-115 |
| *******************************************************************************/ |
| package org.eclipse.ptp.debug.internal.core.pdi.manager; |
| |
| |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.ptp.core.util.BitList; |
| import org.eclipse.ptp.debug.core.ExtFormat; |
| import org.eclipse.ptp.debug.core.pdi.IPDISession; |
| import org.eclipse.ptp.debug.core.pdi.PDIException; |
| import org.eclipse.ptp.debug.core.pdi.event.IPDIDataReadMemoryInfo; |
| import org.eclipse.ptp.debug.core.pdi.event.IPDIEvent; |
| import org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager; |
| import org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock; |
| import org.eclipse.ptp.debug.core.pdi.request.IPDIDataReadMemoryRequest; |
| |
| /** |
| * @author Clement chu |
| * |
| */ |
| public class MemoryManager extends AbstractPDIManager implements IPDIMemoryManager { |
| IPDIMemoryBlock[] EMPTY_MEMORY_BLOCKS = {}; |
| Map<BitList, List<IPDIMemoryBlock>> blockMap; |
| |
| public MemoryManager(IPDISession session) { |
| super(session, true); |
| blockMap = new Hashtable<BitList, List<IPDIMemoryBlock>>(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager#createMemoryBlock(org.eclipse.ptp.core.util.BitList, java.lang.String, int, int) |
| */ |
| public IPDIMemoryBlock createMemoryBlock(BitList qTasks, String address, int units, int wordSize) throws PDIException { |
| IPDIDataReadMemoryInfo info = createDataReadMemoryInfo(qTasks, address, units, wordSize); |
| IPDIMemoryBlock block = session.getModelFactory().newMemoryBlock(session, qTasks, address, wordSize, true, info); |
| List<IPDIMemoryBlock> blockList = getMemoryBlockList(qTasks); |
| blockList.add(block); |
| IPDIEvent event = session.getEventFactory().newCreatedEvent( |
| session.getEventFactory().newMemoryBlockInfo(session, qTasks, new BigInteger[] { block.getStartAddress() }, block)); |
| session.getEventManager().fireEvents(new IPDIEvent[] { event }); |
| return block; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager#getMemoryBlocks(org.eclipse.ptp.core.util.BitList) |
| */ |
| public IPDIMemoryBlock[] getMemoryBlocks(BitList qTasks) throws PDIException { |
| List<IPDIMemoryBlock> blockList = getMemoryBlockList(qTasks); |
| return (IPDIMemoryBlock[]) blockList.toArray(new IPDIMemoryBlock[blockList.size()]); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager#removeAllBlocks(org.eclipse.ptp.core.util.BitList) |
| */ |
| public void removeAllBlocks(BitList qTasks) throws PDIException { |
| IPDIMemoryBlock[] blocks = getMemoryBlocks(qTasks); |
| removeBlocks(qTasks, blocks); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager#removeBlocks(org.eclipse.ptp.core.util.BitList, org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock[]) |
| */ |
| public void removeBlocks(BitList qTasks, IPDIMemoryBlock[] memoryBlocks) throws PDIException { |
| List<IPDIMemoryBlock> blockList = blockMap.get(qTasks); |
| if (blockList != null) { |
| blockList.removeAll(Arrays.asList(memoryBlocks)); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.internal.core.pdi.AbstractPDIManager#shutdown() |
| */ |
| public void shutdown() { |
| blockMap.clear(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.internal.core.pdi.AbstractPDIManager#update(org.eclipse.ptp.core.util.BitList) |
| */ |
| public void update(BitList qTasks) { |
| List<IPDIMemoryBlock> blockList = getMemoryBlockList(qTasks); |
| IPDIMemoryBlock[] blocks = (IPDIMemoryBlock[]) blockList.toArray(new IPDIMemoryBlock[blockList.size()]); |
| List<IPDIEvent> eventList = new ArrayList<IPDIEvent>(blocks.length); |
| for (int i = 0; i < blocks.length; i++) { |
| if (! blocks[i].isFrozen()) { |
| try { |
| update(blocks[i], eventList); |
| } catch (PDIException e) { |
| } |
| } |
| } |
| IPDIEvent[] events = (IPDIEvent[])eventList.toArray(new IPDIEvent[0]); |
| session.getEventManager().fireEvents(events); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager#update(org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock, java.util.List) |
| */ |
| public BigInteger[] update(IPDIMemoryBlock block, List<IPDIEvent> aList) throws PDIException { |
| IPDIMemoryBlock newBlock = cloneBlock(block); |
| boolean newAddress = ! newBlock.getStartAddress().equals(block.getStartAddress()); |
| BigInteger[] array = compareBlocks(block, newBlock); |
| block.setDataReadMemoryInfo(newBlock.getDataReadMemoryInfo()); |
| if (array.length > 0 || newAddress) { |
| IPDIEvent event = session.getEventFactory().newChangedEvent( |
| session.getEventFactory().newMemoryBlockInfo(session, block.getTasks(), array, block)); |
| if (aList != null) { |
| aList.add(event); |
| } else { |
| session.getEventManager().fireEvents(new IPDIEvent[] { event }); |
| } |
| } |
| return array; |
| } |
| |
| /** |
| * @param block |
| * @return |
| * @throws PDIException |
| */ |
| private IPDIMemoryBlock cloneBlock(IPDIMemoryBlock block) throws PDIException { |
| String exp = block.getExpression(); |
| int wordSize = block.getWordSize(); |
| IPDIDataReadMemoryInfo info = createDataReadMemoryInfo(block.getTasks(), exp, (int)block.getLength(), wordSize); |
| return session.getModelFactory().newMemoryBlock(session, block.getTasks(), exp, wordSize, true, info); |
| } |
| |
| /** |
| * @param oldBlock |
| * @param newBlock |
| * @return |
| * @throws PDIException |
| */ |
| private BigInteger[] compareBlocks(IPDIMemoryBlock oldBlock, IPDIMemoryBlock newBlock) throws PDIException { |
| byte[] oldBytes = oldBlock.getBytes(); |
| byte[] newBytes = newBlock.getBytes(); |
| List<BigInteger> aList = new ArrayList<BigInteger>(newBytes.length); |
| BigInteger distance = newBlock.getStartAddress().subtract(oldBlock.getStartAddress()); |
| int diff = distance.intValue(); |
| if ( Math.abs(diff) < newBytes.length) { |
| for (int i = 0; i < newBytes.length; i++) { |
| if (i + diff < oldBytes.length && i + diff >= 0) { |
| if (oldBytes[i + diff] != newBytes[i]) { |
| aList.add(newBlock.getStartAddress().add(BigInteger.valueOf(i))); |
| } |
| } |
| } |
| } |
| return (BigInteger[]) aList.toArray(new BigInteger[aList.size()]); |
| } |
| |
| /** |
| * @param qTasks |
| * @param exp |
| * @param units |
| * @param wordSize |
| * @return |
| * @throws PDIException |
| */ |
| private IPDIDataReadMemoryInfo createDataReadMemoryInfo(BitList qTasks, String exp, int units, int wordSize) throws PDIException { |
| IPDIDataReadMemoryRequest request = session.getRequestFactory().getDataReadMemoryRequest(session, qTasks, 0, exp, ExtFormat.HEXADECIMAL, wordSize, 1, units, null); |
| session.getEventRequestManager().addEventRequest(request); |
| return request.getDataReadMemoryInfo(qTasks); |
| } |
| |
| /** |
| * @param qTasks |
| * @return |
| */ |
| private synchronized List<IPDIMemoryBlock> getMemoryBlockList(BitList qTasks) { |
| List<IPDIMemoryBlock> blockList = blockMap.get(qTasks); |
| if (blockList == null) { |
| blockList = Collections.synchronizedList(new ArrayList<IPDIMemoryBlock>()); |
| blockMap.put(qTasks, blockList); |
| } |
| return blockList; |
| } |
| } |