Package com.cburch.logisim.std.memory

Source Code of com.cburch.logisim.std.memory.Ram

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.std.memory;

import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeEvent;
import com.cburch.logisim.data.AttributeListener;
import com.cburch.logisim.data.AttributeOption;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.AttributeSets;
import com.cburch.logisim.data.Attributes;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.gui.hex.HexFrame;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.InstanceData;
import com.cburch.logisim.instance.InstanceLogger;
import com.cburch.logisim.instance.InstancePainter;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.instance.Port;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.proj.Project;

public class Ram extends Mem {
  static final AttributeOption BUS_COMBINED
    = new AttributeOption("combined", Strings.getter("ramBusSynchCombined"));
  static final AttributeOption BUS_ASYNCH
    = new AttributeOption("asynch", Strings.getter("ramBusAsynchCombined"));
  static final AttributeOption BUS_SEPARATE
    = new AttributeOption("separate", Strings.getter("ramBusSeparate"));

  static final Attribute<AttributeOption> ATTR_BUS = Attributes.forOption("bus",
      Strings.getter("ramBusAttr"),
      new AttributeOption[] { BUS_COMBINED, BUS_ASYNCH, BUS_SEPARATE });

  private static Attribute<?>[] ATTRIBUTES = {
    Mem.ADDR_ATTR, Mem.DATA_ATTR, ATTR_BUS
  };
  private static Object[] DEFAULTS = {
    BitWidth.create(8), BitWidth.create(8), BUS_COMBINED
  };
 
  private static final int OE  = MEM_INPUTS + 0;
  private static final int CLR = MEM_INPUTS + 1;
  private static final int CLK = MEM_INPUTS + 2;
  private static final int WE  = MEM_INPUTS + 3;
  private static final int DIN = MEM_INPUTS + 4;

  private static Object[][] logOptions = new Object[9][];

  public Ram() {
    super("RAM", Strings.getter("ramComponent"), 3);
    setIconName("ram.gif");
    setInstanceLogger(Logger.class);
  }
 
  @Override
  protected void configureNewInstance(Instance instance) {
    super.configureNewInstance(instance);
    instance.addAttributeListener();
  }
 
  @Override
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
    super.instanceAttributeChanged(instance, attr);
    configurePorts(instance);
  }
 
  @Override
  void configurePorts(Instance instance) {
    Object bus = instance.getAttributeValue(ATTR_BUS);
    if (bus == null) bus = BUS_COMBINED;
    boolean asynch = bus == null ? false : bus.equals(BUS_ASYNCH);
    boolean separate = bus == null ? false : bus.equals(BUS_SEPARATE);

    int portCount = MEM_INPUTS;
    if (asynch) portCount += 2;
    else if (separate) portCount += 5;
    else portCount += 3;
    Port[] ps = new Port[portCount];

    configureStandardPorts(instance, ps);
    ps[OE= new Port(-50, 40, Port.INPUT, 1);
    ps[OE].setToolTip(Strings.getter("ramOETip"));
    ps[CLR] = new Port(-30, 40, Port.INPUT, 1);
    ps[CLR].setToolTip(Strings.getter("ramClrTip"));
    if (!asynch) {
      ps[CLK] = new Port(-70, 40, Port.INPUT, 1);
      ps[CLK].setToolTip(Strings.getter("ramClkTip"));
    }
    if (separate) {
      ps[WE] = new Port(-110, 40, Port.INPUT, 1);
      ps[WE].setToolTip(Strings.getter("ramWETip"));
      ps[DIN] = new Port(-140, 20, Port.INPUT, DATA_ATTR);
      ps[DIN].setToolTip(Strings.getter("ramInTip"));
    } else {
      ps[DATA].setToolTip(Strings.getter("ramBusTip"));
    }
    instance.setPorts(ps);
  }

  @Override
  public AttributeSet createAttributeSet() {
    return AttributeSets.fixedSet(ATTRIBUTES, DEFAULTS);
  }

  @Override
  MemState getState(InstanceState state) {
    BitWidth addrBits = state.getAttributeValue(ADDR_ATTR);
    BitWidth dataBits = state.getAttributeValue(DATA_ATTR);

    RamState myState = (RamState) state.getData();
    if (myState == null) {
      MemContents contents = MemContents.create(addrBits.getWidth(), dataBits.getWidth());
      Instance instance = state.getInstance();
      myState = new RamState(instance, contents, new MemListener(instance));
      state.setData(myState);
    } else {
      myState.setRam(state.getInstance());
    }
    return myState;
  }

  @Override
  MemState getState(Instance instance, CircuitState state) {
    BitWidth addrBits = instance.getAttributeValue(ADDR_ATTR);
    BitWidth dataBits = instance.getAttributeValue(DATA_ATTR);

    RamState myState = (RamState) instance.getData(state);
    if (myState == null) {
      MemContents contents = MemContents.create(addrBits.getWidth(), dataBits.getWidth());
      myState = new RamState(instance, contents, new MemListener(instance));
      instance.setData(state, myState);
    } else {
      myState.setRam(instance);
    }
    return myState;
  }

  @Override
  HexFrame getHexFrame(Project proj, Instance instance, CircuitState circState) {
    RamState state = (RamState) getState(instance, circState);
    return state.getHexFrame(proj);
  }

  @Override
  public void propagate(InstanceState state) {
    RamState myState = (RamState) getState(state);
    BitWidth dataBits = state.getAttributeValue(DATA_ATTR);
    Object busVal = state.getAttributeValue(ATTR_BUS);
    boolean asynch = busVal == null ? false : busVal.equals(BUS_ASYNCH);
    boolean separate = busVal == null ? false : busVal.equals(BUS_SEPARATE);

    Value addrValue = state.getPort(ADDR);
    boolean chipSelect = state.getPort(CS) != Value.FALSE;
    boolean triggered = asynch || myState.setClock(state.getPort(CLK), StdAttr.TRIG_RISING);
    boolean outputEnabled = state.getPort(OE) != Value.FALSE;
    boolean shouldClear = state.getPort(CLR) == Value.TRUE;
   
    if (shouldClear) {
      myState.getContents().clear();
    }
   
    if (!chipSelect) {
      myState.setCurrent(-1);
      state.setPort(DATA, Value.createUnknown(dataBits), DELAY);
      return;
    }

    int addr = addrValue.toIntValue();
    if (!addrValue.isFullyDefined() || addr < 0)
      return;
    if (addr != myState.getCurrent()) {
      myState.setCurrent(addr);
      myState.scrollToShow(addr);
    }

    if (!shouldClear && triggered) {
      boolean shouldStore;
      if (separate) {
        shouldStore = state.getPort(WE) != Value.FALSE;
      } else {
        shouldStore = !outputEnabled;
      }
      if (shouldStore) {
        Value dataValue = state.getPort(separate ? DIN : DATA);
        myState.getContents().set(addr, dataValue.toIntValue());
      }
    }

    if (outputEnabled) {
      int val = myState.getContents().get(addr);
      state.setPort(DATA, Value.createKnown(dataBits, val), DELAY);
    } else {
      state.setPort(DATA, Value.createUnknown(dataBits), DELAY);
    }
  }

  @Override
  public void paintInstance(InstancePainter painter) {
    super.paintInstance(painter);
    Object busVal = painter.getAttributeValue(ATTR_BUS);
    boolean asynch = busVal == null ? false : busVal.equals(BUS_ASYNCH);
    boolean separate = busVal == null ? false : busVal.equals(BUS_SEPARATE);
   
    if (!asynch) painter.drawClock(CLK, Direction.NORTH);
    painter.drawPort(OE, Strings.get("ramOELabel"), Direction.SOUTH);
    painter.drawPort(CLR, Strings.get("ramClrLabel"), Direction.SOUTH);

    if (separate) {
      painter.drawPort(WE, Strings.get("ramWELabel"), Direction.SOUTH);
      painter.getGraphics().setColor(Color.BLACK);
      painter.drawPort(DIN, Strings.get("ramDataLabel"), Direction.EAST);
    }
  }

  private static class RamState extends MemState
      implements InstanceData, AttributeListener {
    private Instance parent;
    private MemListener listener;
    private HexFrame hexFrame = null;
    private ClockState clockState;

    RamState(Instance parent, MemContents contents, MemListener listener) {
      super(contents);
      this.parent = parent;
      this.listener = listener;
      this.clockState = new ClockState();
      if (parent != null) parent.getAttributeSet().addAttributeListener(this);
      contents.addHexModelListener(listener);
    }
   
    void setRam(Instance value) {
      if (parent == value) return;
      if (parent != null) parent.getAttributeSet().removeAttributeListener(this);
      parent = value;
      if (value != null) value.getAttributeSet().addAttributeListener(this);
    }
   
    @Override
    public RamState clone() {
      RamState ret = (RamState) super.clone();
      ret.parent = null;
      ret.clockState = this.clockState.clone();
      ret.getContents().addHexModelListener(listener);
      return ret;
    }
   
    // Retrieves a HexFrame for editing within a separate window
    public HexFrame getHexFrame(Project proj) {
      if (hexFrame == null) {
        hexFrame = new HexFrame(proj, getContents());
        hexFrame.addWindowListener(new WindowAdapter() {
          @Override
          public void windowClosed(WindowEvent e) {
            hexFrame = null;
          }
        });
      }
      return hexFrame;
    }
   
    //
    // methods for accessing the write-enable data
    //
    public boolean setClock(Value newClock, Object trigger) {
      return clockState.updateClock(newClock, trigger);
    }

    public void attributeListChanged(AttributeEvent e) { }

    public void attributeValueChanged(AttributeEvent e) {
      AttributeSet attrs = e.getSource();
      BitWidth addrBits = attrs.getValue(Mem.ADDR_ATTR);
      BitWidth dataBits = attrs.getValue(Mem.DATA_ATTR);
      getContents().setDimensions(addrBits.getWidth(), dataBits.getWidth());
    }
  }
 
  public static class Logger extends InstanceLogger {
    @Override
    public Object[] getLogOptions(InstanceState state) {
      int addrBits = state.getAttributeValue(ADDR_ATTR).getWidth();
      if (addrBits >= logOptions.length) addrBits = logOptions.length - 1;
      synchronized(logOptions) {
        Object[] ret = logOptions[addrBits];
        if (ret == null) {
          ret = new Object[1 << addrBits];
          logOptions[addrBits] = ret;
          for (int i = 0; i < ret.length; i++) {
            ret[i] = Integer.valueOf(i);
          }
        }
        return ret;
      }
    }

    @Override
    public String getLogName(InstanceState state, Object option) {
      if (option instanceof Integer) {
        String disp = Strings.get("ramComponent");
        Location loc = state.getInstance().getLocation();
        return disp + loc + "[" + option + "]";
      } else {
        return null;
      }
    }

    @Override
    public Value getLogValue(InstanceState state, Object option) {
      if (option instanceof Integer) {
        MemState s = (MemState) state.getData();
        int addr = ((Integer) option).intValue();
        return Value.createKnown(BitWidth.create(s.getDataBits()),
            s.getContents().get(addr));
      } else {
        return Value.NIL;
      }
    }
  }
}
TOP

Related Classes of com.cburch.logisim.std.memory.Ram

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.