package ckelling.baukasten;

import java.awt.*;


/**
 *	AddressExplainer.java
 *
 *	Stellt den Wert des Adressbusses,
 *	aufgeteilt nach Tag-, Index und Byte-Anteil, dar.
 *
 *	@author		Carsten Kelling
 *	@version	0.2.0, 28.11.96
 */
public class AddressExplainer extends Panel {

	private Rechner	parent;
	private int		address;
	private int		ramSize;
	private int		cacheSize;
	private int 	lineSize;
	private int 	associativity;
	private int		addressWidth;
	private int		tagWidth;
	private int		indexWidth;
	private int		byteWidth;
	private int		tagMask;
	private int		indexMask;
	private int		byteMask;
	private boolean activated;
	private boolean	activationLocked;

    public AddressExplainer(Rechner par) {

        super();

        parent = par;

        int y1 = 14;  // defaults: 20
        int y2 = 40;  //           46
        int h  = 25;  //           19
        int lWidth = 82;  //       84

        //{{INIT_CONTROLS
        setLayout(null);
        resize(266,84);

        addressLabel=new Label("", Label.RIGHT);
        addressLabel.setFont(new Font("Dialog",Font.BOLD,10));
        add(addressLabel);
        addressLabel.reshape(0,y1,lWidth,h);
        tagArea=new TextField(9);
        tagArea.setFont(new Font("Dialog",Font.BOLD,10));
        add(tagArea);
        tagArea.reshape(91 + (lWidth-84),y1,77,h);
        indexArea=new TextField(5);
        indexArea.setFont(new Font("Dialog",Font.BOLD,10));
        add(indexArea);
        indexArea.reshape(168 + (lWidth-84),y1,49,h);
        byteArea=new TextField(5);
        byteArea.setFont(new Font("Dialog",Font.BOLD,10));
        add(byteArea);
        byteArea.reshape(217 + (lWidth-84),y1,49,h);

        addressBinLabel=new Label("", Label.RIGHT);
        addressBinLabel.setFont(new Font("Dialog",Font.BOLD,10));
        add(addressBinLabel);
        addressBinLabel.reshape(0,y2,lWidth,h);
        tagAreaBin=new TextField(9);
        tagAreaBin.setFont(new Font("Dialog",Font.BOLD,10));
        add(tagAreaBin);
        tagAreaBin.reshape(91 + (lWidth-84),y2,77,h);
        indexAreaBin=new TextField(5);
        indexAreaBin.setFont(new Font("Dialog",Font.BOLD,10));
        add(indexAreaBin);
        indexAreaBin.reshape(168 + (lWidth-84),y2,49,h);
        byteAreaBin=new TextField(5);
        byteAreaBin.setFont(new Font("Dialog",Font.BOLD,10));
        add(byteAreaBin);
        byteAreaBin.reshape(217 + (lWidth-84),y2,49,h);

        byteLower=new Label("0");
        byteLower.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(byteLower);
        byteLower.reshape(252,65,14,13);
        byteUpper=new Label("0");
        byteUpper.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(byteUpper);
        byteUpper.reshape(224,65,14,13);
        indexLower=new Label("1");
        indexLower.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(indexLower);
        indexLower.reshape(203,65,14,13);
        indexUpper=new Label("2");
        indexUpper.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(indexUpper);
        indexUpper.reshape(175,65,14,13);
        tagLower=new Label("3");
        tagLower.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(tagLower);
        tagLower.reshape(154,65,14,13);
        tagUpper=new Label("7");
        tagUpper.setFont(new Font("Helvetica",Font.PLAIN,10));
        add(tagUpper);
        tagUpper.reshape(98,65,14,13);

        titleLabel=new Label("Wert des Adreßbusses");
        add(titleLabel);
        titleLabel.reshape(91,0,147,13);
        //}}

        setBackground(parent.RULER_COLOR);

        tagArea		.setEditable(false);
        indexArea	.setEditable(false);
        byteArea	.setEditable(false);
        tagAreaBin	.setEditable(false);
        indexAreaBin.setEditable(false);
        byteAreaBin	.setEditable(false);

        setAddress(-1);
        setParameters(1, 1, 1, 1);
        activated = false;
        activationLocked = false;

    }

    public Insets insets()
    {
    	return new Insets(0, 0, 0, 0);
    }

    public boolean handleEvent(Event event) {
        return super.handleEvent(event);
    }

    //{{DECLARE_CONTROLS
    Label addressLabel;
    TextField tagAreaBin;
    TextField indexAreaBin;
    TextField byteAreaBin;
    Label byteLower;
    Label byteUpper;
    Label indexLower;
    Label indexUpper;
    Label tagLower;
    Label tagUpper;
    TextField tagArea;
    TextField indexArea;
    TextField byteArea;
    Label addressBinLabel;
    Label titleLabel;
    //}}


	/**
	public void paint(Graphics g)
	{
		super.paint(g);
		if (activated)
			activate();
		else
			deactivate();
	}
	*/


    public void activate()
    {
    	if (! activationLocked)
    	{
	    	activated = true;

	    	int t = (address & tagMask) >> (indexWidth + byteWidth);
	    	int i = (address & indexMask) >> byteWidth;
	    	int b = address & byteMask;

	    	int tMax = (int) Math.pow(2, (double) tagWidth);
	    	int iMax = (int) Math.pow(2, (double) indexWidth);
	    	int bMax = lineSize;

	    	int addressMax = ramSize;
	    	addressLabel.setText(parent.expandToString(address, addressMax) + " =");
	    	addressBinLabel.setText(parent.expandToString(address, addressMax, 2) + " =");

	    	if (byteWidth <= 0)
	    	{
	    		byteArea.setText("");
	    		byteAreaBin.setText("");
		    }
		    else
		    {
		    	byteArea.setText(parent.expandToString(b, bMax));
		    	byteAreaBin.setText(parent.expandToString(b, bMax, 2));
		    }
		    if (indexWidth <= 0)
		    {
		    	indexArea.setText("");
		    	indexAreaBin.setText("");
		    }
		    else
		    {
		    	indexArea.setText(parent.expandToString(i, iMax));
		    	indexAreaBin.setText(parent.expandToString(i, iMax, 2));
		    }
	    	tagArea.setText(parent.expandToString(t, tMax));
	    	tagAreaBin.setText(parent.expandToString(t, tMax, 2));
	    }
    }

    public void deactivate()
    {
    	if (! activationLocked)
    	{
	    	activated = false;

	    	tagArea.setText("TAG");
	    	indexArea.setText("INDEX");
	    	byteArea.setText("BYTE");

	    	tagAreaBin.setText("");
	    	indexAreaBin.setText("");
	    	byteAreaBin.setText("");

	    	addressLabel.setText("");
	    	addressBinLabel.setText("");
	    }
    }

    private void setBitLabels()
    {
    	if (byteWidth <= 0)
    	{
	    	byteLower.setText("");
	    	byteUpper.setText("");
	    }
	    else
	    {
	    	byteLower.setText("0");
	    	byteUpper.setText("" + (byteWidth - 1));
	    }
	    if (indexWidth <= 0)
	    {
	    	indexLower.setText("");
	    	indexUpper.setText("");
	    }
	    else
	    {
	    	indexLower.setText("" + byteWidth);
	    	indexUpper.setText("" + (indexWidth + byteWidth - 1));
	    }
	    tagLower.setText("" + (indexWidth + byteWidth));
	    tagUpper.setText("" + (tagWidth + indexWidth + byteWidth - 1));
    }


    public void setAddress(int adr)
    {
    	address = adr;
    }

    public void setParameters(int rSize, int cSize, int lSize, int assoc)
    {
    	ramSize = rSize;
    	cacheSize = cSize;
    	lineSize = lSize;
    	associativity = assoc;

    	addressWidth = parent.log(ramSize, 2);
    	tagWidth = addressWidth + parent.log(associativity, 2) - parent.log(cacheSize, 2);
    	byteWidth = parent.log(lineSize, 2);
    	indexWidth = addressWidth - tagWidth - byteWidth;

	    tagMask = ramSize - cacheSize;
	    byteMask = lineSize - 1;
	    indexMask = cacheSize - 1 - byteMask;

    	int assocMask = (indexMask + byteMask) / associativity;
    	assocMask = indexMask + byteMask - assocMask;

    	tagMask = tagMask + assocMask;
    	indexMask = indexMask - assocMask;

    	setBitLabels();
    }

	public void lock()
	{
		activationLocked = true;
	}

	public void unlock()
	{
		activationLocked = false;
	}
} /* end AddressExplainer */


