Add some context.
[matthijs/master-project/report.git] / Utils / Metapost.tex
index cac69ddbd68bac88ae4bbf2b8591e862376ea5f8..63b0620bd7b2556fa4bfec26aa8e378e10bee277 100644 (file)
@@ -8,6 +8,7 @@ input metaobj;
 setObjectDefaultOption("Box")("framewidth")(.75mm);
 setObjectDefaultOption("Circle")("framewidth")(.75mm);
 setObjectDefaultOption("Circle")("circmargin")(3mm);
+setObjectDefaultOption("Mux")("framewidth")(.75mm);
 %ahlength := 1.5mm;
 ahangle := 60;
 
@@ -16,4 +17,143 @@ setCurveDefaultOption("linewidth",.75mm);
 % included in the bounding box for line cutoff.
 setCurveDefaultOption("nodesep",curve_linewidth_default);
 
+
+% Define a register.
+% |v| is either a picture, a string or an object given by its number which
+% will be contained inside the register. Supports the same options as Box,
+% plus:
+%   reflect    Reflect the register vertically, so input is right and output
+%              is left. (default: false)
+%   labels     Show labels for the input and output ports. (default: false)
+vardef newReg@#(expr v) text options=
+  ExecuteOptions(@#)(options);
+  assignObj(@#,"Reg");
+  StandardInterface;
+  
+  % We contain a box (that contains the passed object in turn)
+  SubObject(box,obj(newobjstring_));
+  newBox.obj(@#box)(v) options;
+  % Some points for ports
+  ObjPoint ck,d,out;
+
+  ObjCode StandardEquations,
+    % Align our bounding box with the enclosed box
+    "obj(@#box).c = @#c",
+    "obj(@#box).se = @#se",
+    "obj(@#box).nw = @#nw",
+    % Put the clock, data and output ports at the right spots
+    if OptionValue@#("reflect"):
+      "xpart @#out = xpart @#w",
+      "xpart @#d = xpart @#ck = xpart @#e",
+    else:
+      "xpart @#out = xpart @#e",
+      "xpart @#d = xpart @#ck = xpart @#w",
+    fi
+    "ypart @#out = ypart midpoint(@#n, @#s)",
+    "ypart @#d = ypart (@#sw * .25 + @#nw * .75)",
+    "ypart @#ck = ypart (@#sw * .75 + @#nw * .25)";
+
+  StandardTies;
+enddef;
+
+% Draw a register
+def drawReg(suffix reg)=
+  save clkwh, refl;
+  % Draw the box
+  drawObj(obj(reg.box));
+
+  % Fill refl with 1 or -1, to invert coordinates when reflected.
+  if OptionValue.reg("reflect"):
+    refl = -1;
+  else:
+    refl = 1;
+  fi;
+
+  % Calculate (half of) the height and width of the triangle
+  clkwh = ypart((reg.n - reg.s)) * .1;
+  % Draw the "clock" triangle
+  draw ((0, clkwh) -- (refl * clkwh, 0) -- (0, -clkwh)) shifted reg.ck;
+
+  % Draw input and output labels
+  if OptionValue.reg("labels"):
+    if OptionValue.reg("reflect"):
+      label.lft(\sometxt{D}, reg.d);
+      label.rt(\sometxt{O}, reg.out);
+    else:
+      label.rt(\sometxt{D}, reg.d);
+      label.lft(\sometxt{O}, reg.out);
+    fi;
+  fi
+enddef;
+
+% Bounding path for a register
+def BpathReg(suffix n)=BpathObj(obj(n.box)) enddef;
+
+% Define options
+define_global_boolean_option("reflect");
+define_global_boolean_option("labels");
+setObjectDefaultOption("Reg")("reflect")(false);
+setObjectDefaultOption("Reg")("labels")(false);
+
+% Define a Multiplexer.
+vardef newMux@# text options=
+  ExecuteOptions(@#)(options);
+  assignObj(@#,"Mux");
+  StandardInterface;
+  % Add ports
+  ObjPoint inpa, inpb, out, sel;
+  ObjCode MinimumStandardEquations,
+    % Make it a parallel trapezium
+    "xpart(@#ne - @#nw) = xpart(@#se - @#sw)",
+    "ypart(@#ne - @#nw) = -1 * ypart(@#se - @#sw)",
+    % Use a 22.5 degree angle for the sides
+    "ypart(@#nw) - ypart(@#ne) = xpart(@#ne-@#nw) / 2",
+    % With a specific width and height
+    "@#e-@#w = (" & decimal OptionValue@#("width") & ", 0mm)",
+    "@#n-@#s = (0mm, " & decimal OptionValue@#("height") & ")",
+    % And space the input ports evenly
+    "@#inpa = midpoint(@#nw, @#w)",
+    "@#inpb = midpoint(@#w, @#sw)",
+    "@#out = @#e", 
+    "@#sel = @#n"; 
+
+  StandardTies;
+enddef;
+
+% Draw a multiplexer
+def drawMux(suffix mux)=
+  draw mux.n -- mux.s;
+  % Use our bounding path to draw
+  drawFramedOrFilledObject_(mux);
+enddef;
+
+% Bounding path for a multiplexer
+def BpathMux(suffix n)=StandardBpath(n) enddef;
+
+% Define options
+define_local_numeric_option("width");
+define_local_numeric_option("height");
+setObjectDefaultOption("Mux")("width")(5mm);
+setObjectDefaultOption("Mux")("height")(15mm);
+setObjectDefaultOption("Mux")("framed")(true);
+% Overidden above
+%setObjectDefaultOption("Mux")("framewidth")(.5bp);
+setObjectDefaultOption("Mux")("framecolor")(black);
+setObjectDefaultOption("Mux")("framestyle")("");
+setObjectDefaultOption("Mux")("shadow")(false);
+setObjectDefaultOption("Mux")("shadowcolor")(black);
+setObjectDefaultOption("Mux")("filled")(false);
+setObjectDefaultOption("Mux")("fillcolor")(black);
+
+
+def midpoint(expr a, b) = ((a + b) / 2) enddef;
+
 \stopMPinclusions
+
+% Make \overrightarrow "unexpanded", to make it work within metapost.
+% http://www.ntg.nl/pipermail/ntg-context/2009/043620.html. Will be fixed in
+% context.
+\let\normaloverrightarrow\overrightarrow                                                                                                                     
+\unexpanded\def\overrightarrow{\normaloverrightarrow}