/* * Copyright (c) 2012, IRISA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.backends.llvm.tta.architecture.util; import net.sf.orcc.backends.llvm.tta.architecture.Design; import net.sf.orcc.backends.llvm.tta.architecture.Memory; import net.sf.orcc.backends.llvm.tta.architecture.Processor; import net.sf.orcc.backends.util.BackendUtil; import net.sf.orcc.df.Action; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Connection; import net.sf.orcc.df.Instance; import net.sf.orcc.df.util.DfVisitor; import net.sf.orcc.graph.Vertex; import net.sf.orcc.ir.Procedure; import net.sf.orcc.ir.Type; import net.sf.orcc.ir.TypeList; import net.sf.orcc.ir.Var; import net.sf.orcc.ir.util.AbstractIrVisitor; import net.sf.orcc.util.OrccLogger; /** * The class defines an estimator of the quantity of memory needed by an design * after the projection of an application on this design. * * @author Herve Yviquel */ public class ArchitectureMemoryEstimator extends ArchitectureVisitor<Void> { final double ERROR_MARGIN = 0.4; /** * The class defines a Network visitor used to evaluate the memory needs of * the given dataflow entities. */ private class InnerDfVisitor extends DfVisitor<Long> { private int fifosize = 0; private class InnerIrVisitor extends AbstractIrVisitor<Long> { @Override public Long caseProcedure(Procedure procedure) { long bits = 0; for (Var local : procedure.getLocals()) { bits += doSwitch(local); } return bits; } @Override public Long caseVar(Var var) { return (long) getSize(var.getType()); } } public InnerDfVisitor(int fifosize) { this.irVisitor = new InnerIrVisitor(); this.fifosize = fifosize; } @Override public Long caseAction(Action action) { long bits = doSwitch(action.getScheduler()) + doSwitch(action.getBody()); return (long) Math.ceil(bits + bits * ERROR_MARGIN); } @Override public Long caseActor(Actor actor) { long bits = 0; for (Var var : actor.getStateVars()) { if (var.isAssignable() || var.getType().isList()) { int tmp = getSize(var.getType()); bits += tmp; } } for (Action action : actor.getActions()) { long tmp = doSwitch(action); bits += tmp; } return bits; } @Override public Long caseConnection(Connection connection) { Integer size = connection.getSize(); if (size == null) { size = fifosize; } int bits = size * getSize(connection.getSourcePort().getType()) + 2 * 32; return (long) Math.ceil(bits); } @Override public Long caseInstance(Instance instance) { return doSwitch(instance.getActor()); } } private DfVisitor<Long> dfVisitor; public ArchitectureMemoryEstimator(int fifosize) { dfVisitor = new InnerDfVisitor(fifosize); } @Override public Void caseDesign(Design design) { long lramSize = 0, sramSize = 0; OrccLogger.noticeln("****** Memory size estimation ******"); super.caseDesign(design); OrccLogger.traceln("Size of shared RAMs (in bits)"); for(Memory smem : design.getSharedMemories()) { OrccLogger.traceln(smem.getName() + " = " + smem.getSizeAsString()); sramSize += smem.getDepth() * smem.getWordWidth(); } OrccLogger.traceln("Size of local RAMs (in bits)"); for(Processor processor : design.getProcessors()) { Memory lram = processor.getLocalRAMs().get(0); OrccLogger.traceln("Processor " + processor.getName() + " = " + lram.getSizeAsString()); lramSize += lram.getDepth() * lram.getWordWidth(); } OrccLogger.traceln("Total size of shared RAM = " + sramSize / 8 + " Bytes"); OrccLogger.traceln("Total size of local RAM = " + lramSize / 8 + " Bytes"); OrccLogger.noticeln("******************************"); return null; } @Override public Void caseMemory(Memory buffer) { int bits = 0; for (Connection connection : buffer.getMappedConnections()) { bits += dfVisitor.doSwitch(connection); } buffer.setDepth(BackendUtil.quantizeUp(bits / 8 + 64)); buffer.setWordWidth(8); buffer.setMinAddress(0); return null; } @Override public Void caseProcessor(Processor processor) { Memory rom = processor.getROM(); rom.setDepth(480000); rom.setWordWidth(8); rom.setMinAddress(0); // Compute size of the local circular buffer for (Memory ram : processor.getLocalRAMs()) { doSwitch(ram); } // Increase the size of the first RAM according to the memory needs for // the stack and the state of the actors. long bits = 0; for (Vertex entity : processor.getMappedActors()) { bits += dfVisitor.doSwitch(entity); } Memory ram = processor.getLocalRAMs().get(0); long size = BackendUtil.quantizeUp(ram.getDepth() + bits / 8); ram.setDepth(size); ram.setWordWidth(8); ram.setMinAddress(0); return null; } /** * Compute the size in bits of the given type. The method getSizeInBits() of * the class Type is not relevant here because the TCE consider boolean as * an 8-bits type. * * @param type * the type to evaluate * @return the size of the type in bits. */ private int getSize(Type type) { int size; if (type.isList()) { size = getSize(((TypeList) type).getInnermostType()); for (int dim : type.getDimensions()) { size *= dim; } } else if (type.isBool()) { size = 8; } else { size = type.getSizeInBits(); } return size; } }