1 /*
2  * Copyright (c) 2016 Helmut Neemann
3  * Use of this source code is governed by the GPL v3 license
4  * that can be found in the LICENSE file.
5  */
6 package de.neemann.digital.core.memory;
7 
8 import de.neemann.digital.core.*;
9 import de.neemann.digital.core.element.Element;
10 import de.neemann.digital.core.element.ElementAttributes;
11 import de.neemann.digital.core.element.ElementTypeDescription;
12 import de.neemann.digital.core.element.Keys;
13 import de.neemann.digital.core.stats.Countable;
14 
15 import static de.neemann.digital.core.element.PinInfo.input;
16 
17 /**
18  * A simple register.
19  */
20 public class Register extends Node implements Element, Countable, ProgramCounter {
21 
22     /**
23      * The registers {@link ElementTypeDescription}
24      */
25     public static final ElementTypeDescription DESCRIPTION
26             = new ElementTypeDescription(Register.class, input("D"), input("C").setClock(), input("en"))
27             .addAttribute(Keys.ROTATE)
28             .addAttribute(Keys.BITS)
29             .addAttribute(Keys.LABEL)
30             .addAttribute(Keys.INVERTER_CONFIG)
31             .addAttribute(Keys.IS_PROGRAM_COUNTER)
32             .addAttribute(Keys.VALUE_IS_PROBE)
33             .supportsHDL();
34 
35     private final int bits;
36     private final boolean isProbe;
37     private final String label;
38     private final boolean isProgramCounter;
39     private final ObservableValue q;
40     private ObservableValue dVal;
41     private ObservableValue clockVal;
42     private ObservableValue enableVal;
43     private boolean lastClock;
44     private long value;
45     private boolean enable;
46 
47     /**
48      * Creates a new instance
49      *
50      * @param attributes the elements attributes
51      */
Register(ElementAttributes attributes)52     public Register(ElementAttributes attributes) {
53         super(true);
54         bits = attributes.getBits();
55         this.q = new ObservableValue("Q", bits).setPinDescription(DESCRIPTION);
56         isProbe = attributes.get(Keys.VALUE_IS_PROBE);
57         label = attributes.get(Keys.LABEL);
58         isProgramCounter = attributes.get(Keys.IS_PROGRAM_COUNTER);
59     }
60 
61     @Override
readInputs()62     public void readInputs() throws NodeException {
63         enable = enableVal.getBool();
64         boolean clock = clockVal.getBool();
65         if (clock && !lastClock && enable)
66             value = dVal.getValue();
67         lastClock = clock;
68     }
69 
70     @Override
writeOutputs()71     public void writeOutputs() throws NodeException {
72         q.setValue(value);
73     }
74 
75     @Override
setInputs(ObservableValues inputs)76     public void setInputs(ObservableValues inputs) throws BitsException {
77         dVal = inputs.get(0).checkBits(bits, this);
78         clockVal = inputs.get(1).addObserverToValue(this).checkBits(1, this);
79         enableVal = inputs.get(2).checkBits(1, this);
80     }
81 
82     @Override
getOutputs()83     public ObservableValues getOutputs() {
84         return q.asList();
85     }
86 
87     @Override
registerNodes(Model model)88     public void registerNodes(Model model) {
89         super.registerNodes(model);
90         if (isProbe)
91             model.addSignal(new Signal(label, q, (value, highZ) -> setValue(value)).setTestOutput());
92     }
93 
94     @Override
isProgramCounter()95     public boolean isProgramCounter() {
96         return isProgramCounter;
97     }
98 
99     @Override
getProgramCounter()100     public long getProgramCounter() {
101         return value;
102     }
103 
104     @Override
getDataBits()105     public int getDataBits() {
106         return bits;
107     }
108 
109     /**
110      * Returns the stored value.
111      * Used to improve custom testing capabilities.
112      *
113      * @return the stared value
114      */
getValue()115     public long getValue() {
116         return value;
117     }
118 
119     /**
120      * Sets the stored value.
121      * Used to improve custom testing capabilities.
122      *
123      * @param v the value
124      */
setValue(long v)125     public void setValue(long v) {
126         value = v;
127         q.setValue(value);
128     }
129 
130     /**
131      * Returns the used label.
132      * Used to improve custom testing capabilities.
133      *
134      * @return the label
135      */
getLabel()136     public String getLabel() {
137         return label;
138     }
139 
140     /**
141      * Returns the enable input value.
142      * Used to improve custom testing capabilities.
143      *
144      * @return true if enable was set at the last clock change.
145      */
isEnabled()146     public boolean isEnabled() {
147         return enable;
148     }
149 }
150