incr.html 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <html>
  2. <head>
  3. <title>Gray Code Incrementer</title>
  4. </head>
  5. <body bgcolor="FFFFFF">
  6. <h1>Gray Code Incrementer</h1>
  7. <p>Each component included in a library is defined by creating a subclass of
  8. <code>InstanceFactory</code> found in the
  9. <code>com.cburch.logisim.instance</code> package. This subclass has all
  10. the code involved</p>
  11. <p>(Here we're describing the API for the current version of Logisim.
  12. You may find some libraries developed for older versions of Logisim, in
  13. which components were developed by defining two classes, one extending
  14. <code>Component</code> and another extending <code>ComponentFactory</code>.
  15. Version 2.3.0 introduced the much simpler <code>InstanceFactory</code> API; the
  16. older technique is deprecated.)</p>
  17. <p>Three Logisim packages define most of the classes relevant to defining
  18. component libraries.</p>
  19. <dl>
  20. <dt><code>com.cburch.logisim.instance</code></dt>
  21. <dd><p>Contains classes specifically related to defining components,
  22. including the <code>InstanceFactory</code>, <code>InstanceState</code>,
  23. <code>InstancePainter</code>, and <code>Instance</code> classes.</p></dd>
  24. <dt><code>com.cburch.logisim.data</code></dt>
  25. <dd><p>Contains classes related to data elements associated with components,
  26. such as the <code>Bounds</code> class for representing bounding rectangles
  27. or the <code>Value</code> class for representing values that can
  28. exist on a wire.</p></dd>
  29. <dt><code>com.cburch.logisim.tools</code></dt>
  30. <dd><p>Contains classes related to the library definition.</p></dd>
  31. </dl>
  32. <h2>About Gray codes</h2>
  33. <p>Before we go on, let me briefly describe the Gray code on which these
  34. examples are based. It's not really important to understanding how these
  35. examples work, so you can safely skip to the code below if you wish -
  36. particularly if you already know Gray codes.</p>
  37. <p>Gray code is a technique (named after Frank Gray) for iterating through
  38. <var>n</var>-bit sequences with only one bit changed for each step. As an
  39. example, consider the 4-bit Gray code listed below.</p>
  40. <blockquote><table><tbody>
  41. <tr><td valign="top">000<u>0</u>
  42. <br>00<u>0</u>1
  43. <br>001<u>1</u>
  44. <br>0<u>0</u>10
  45. </td><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  46. </td><td valign="top">011<u>0</u>
  47. <br>01<u>1</u>1
  48. <br>010<u>1</u>
  49. <br><u>0</u>100
  50. </td><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  51. </td><td valign="top">110<u>0</u>
  52. <br>11<u>0</u>1
  53. <br>111<u>1</u>
  54. <br>1<u>1</u>10
  55. </td><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  56. </td><td valign="top">101<u>0</u>
  57. <br>10<u>1</u>1
  58. <br>100<u>1</u>
  59. <br><u>1</u>000
  60. </td></tr></tbody></table></blockquote>
  61. <p>Each value has the bit underlined that will change for the next value in
  62. the sequence. For example, after 0000 comes 0001, in which the final bit has
  63. been toggled, so the final bit is underlined.</p>
  64. <p>Logisim's built-in components don't include anything working with Gray codes.
  65. But electronics designers find Gray codes useful sometimes. One
  66. particularly notable instance of Gray codes is along the axes in Karnaugh
  67. maps.</p>
  68. <h2>GrayIncrementer</h2>
  69. <p>This is a minimal example illustrating the essential elements
  70. to defining a component. This particular component is an incrementer,
  71. which takes an multibit input and produces the next Gray code following it
  72. in sequence.</p>
  73. <pre>
  74. package com.cburch.gray;
  75. import com.cburch.logisim.data.Attribute;
  76. import com.cburch.logisim.data.BitWidth;
  77. import com.cburch.logisim.data.Bounds;
  78. import com.cburch.logisim.data.Value;
  79. import com.cburch.logisim.instance.InstanceFactory;
  80. import com.cburch.logisim.instance.InstancePainter;
  81. import com.cburch.logisim.instance.InstanceState;
  82. import com.cburch.logisim.instance.Port;
  83. import com.cburch.logisim.instance.StdAttr;
  84. /** This component takes a multibit input and outputs the value that follows it
  85. * in Gray Code. For instance, given input 0100 the output is 1100. */
  86. class GrayIncrementer extends InstanceFactory {
  87. /* Note that there are no instance variables. There is only one instance of
  88. * this class created, which manages all instances of the component. Any
  89. * information associated with individual instances should be handled
  90. * through attributes. For GrayIncrementer, each instance has a "bit width"
  91. * that it works with, and so we'll have an attribute. */
  92. /** The constructor configures the factory. */
  93. GrayIncrementer() {
  94. super("Gray Code Incrementer");
  95. /* This is how we can set up the attributes for GrayIncrementers. In
  96. * this case, there is just one attribute - the width - whose default
  97. * is 4. The StdAttr class defines several commonly occurring
  98. * attributes, including one for "bit width." It's best to use those
  99. * StdAttr attributes when appropriate: A user can then select several
  100. * components (even from differing factories) with the same attribute
  101. * and modify them all at once. */
  102. setAttributes(new Attribute[] { StdAttr.WIDTH },
  103. new Object[] { BitWidth.create(4) });
  104. /* The "offset bounds" is the location of the bounding rectangle
  105. * relative to the mouse location. Here, we're choosing the component to
  106. * be 30x30, and we're anchoring it relative to its primary output
  107. * (as is typical for Logisim), which happens to be in the center of the
  108. * east edge. Thus, the top left corner of the bounding box is 30 pixels
  109. * west and 15 pixels north of the mouse location. */
  110. setOffsetBounds(Bounds.create(-30, -15, 30, 30));
  111. /* The ports are locations where wires can be connected to this
  112. * component. Each port object says where to find the port relative to
  113. * the component's anchor location, then whether the port is an
  114. * input/output/both, and finally the expected bit width for the port.
  115. * The bit width can be a constant (like 1) or an attribute (as here).
  116. */
  117. setPorts(new Port[] {
  118. new Port(-30, 0, Port.INPUT, StdAttr.WIDTH),
  119. new Port(0, 0, Port.OUTPUT, StdAttr.WIDTH),
  120. });
  121. }
  122. /** Computes the current output for this component. This method is invoked
  123. * any time any of the inputs change their values; it may also be invoked in
  124. * other circumstances, even if there is no reason to expect it to change
  125. * anything. */
  126. public void propagate(InstanceState state) {
  127. // First we retrieve the value being fed into the input. Note that in
  128. // the setPorts invocation above, the component's input was included at
  129. // index 0 in the parameter array, so we use 0 as the parameter below.
  130. Value in = state.getPort(0);
  131. // Now compute the output. We've farmed this out to a helper method,
  132. // since the same logic is needed for the library's other components.
  133. Value out = nextGray(in);
  134. // Finally we propagate the output into the circuit. The first parameter
  135. // is 1 because in our list of ports (configured by invocation of
  136. // setPorts above) the output is at index 1. The second parameter is the
  137. // value we want to send on that port. And the last parameter is its
  138. // "delay" - the number of steps it will take for the output to update
  139. // after its input.
  140. state.setPort(1, out, out.getWidth() + 1);
  141. }
  142. /** Says how an individual instance should appear on the canvas. */
  143. public void paintInstance(InstancePainter painter) {
  144. // As it happens, InstancePainter contains several convenience methods
  145. // for drawing, and we'll use those here. Frequently, you'd want to
  146. // retrieve its Graphics object (painter.getGraphics) so you can draw
  147. // directly onto the canvas.
  148. painter.drawRectangle(painter.getBounds(), "G+1");
  149. painter.drawPorts();
  150. }
  151. /** Computes the next gray value in the sequence after prev. This static
  152. * method just does some bit twiddling; it doesn't have much to do with
  153. * Logisim except that it manipulates Value and BitWidth objects. */
  154. static Value nextGray(Value prev) {
  155. BitWidth bits = prev.getBitWidth();
  156. if(!prev.isFullyDefined()) return Value.createError(bits);
  157. int x = prev.toIntValue();
  158. int ct = (x >> 16) ^ x; // compute parity of x
  159. ct = (ct >> 8) ^ ct;
  160. ct = (ct >> 4) ^ ct;
  161. ct = (ct >> 2) ^ ct;
  162. ct = (ct >> 1) ^ ct;
  163. if((ct & 1) == 0) { // if parity is even, flip 1's bit
  164. x = x ^ 1;
  165. } else { // else flip bit just above last 1
  166. int y = x ^ (x & (x - 1)); // first compute the last 1
  167. y = (y << 1) & bits.getMask();
  168. x = (y == 0 ? 0 : x ^ y);
  169. }
  170. return Value.createKnown(bits, x);
  171. }
  172. }
  173. </pre>
  174. <p>This example by itself is not enough to create a working JAR file;
  175. you must also provide a Library class, as illustrated on the next page.</p>
  176. <p><strong>Next:</strong> <a href="library.html">Library Class</a>.</p>
  177. </body>
  178. </html>