00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "seqSchema.h"
00024 #include <iostream>
00025 #include <assert.h>
00026
00027 using namespace std;
00028
00029 enum {kHorDir, kUpDir, kDownDir};
00030
00031 static double computeHorzGap(schema* a, schema* b);
00032 static int direction(const point& a, const point& b);
00033
00034
00035
00036
00043 schema * makeSeqSchema (schema* s1, schema* s2)
00044 {
00045 unsigned int o = s1->outputs();
00046 unsigned int i = s2->inputs();
00047
00048 schema* a = (o < i) ? makeParSchema(s1, makeCableSchema(i-o)) : s1;
00049 schema* b = (o > i) ? makeParSchema(s2, makeCableSchema(o-i)) : s2;
00050
00051 return new seqSchema(a, b, computeHorzGap(a,b));
00052 }
00053
00054
00055
00056
00057
00062 seqSchema::seqSchema (schema* s1, schema* s2, double hgap)
00063 : schema( s1->inputs(),
00064 s2->outputs(),
00065 s1->width() + hgap + s2->width(),
00066 max(s1->height(), s2->height()) ),
00067 fSchema1(s1),
00068 fSchema2(s2),
00069 fHorzGap(hgap)
00070 {
00071 assert(s1->outputs() == s2->inputs());
00072 }
00073
00074
00075
00076
00077
00082 void seqSchema::place(double ox, double oy, int orientation)
00083 {
00084 beginPlace(ox, oy, orientation);
00085
00086 double y1 = max(0.0, 0.5*(fSchema2->height() - fSchema1->height()));
00087 double y2 = max(0.0, 0.5*(fSchema1->height() - fSchema2->height()));
00088
00089 if (orientation == kLeftRight) {
00090 fSchema1->place(ox, oy+y1, orientation);
00091 fSchema2->place(ox+fSchema1->width()+fHorzGap, oy+y2, orientation);
00092 } else {
00093 fSchema2->place(ox, oy+y2, orientation);
00094 fSchema1->place(ox+fSchema2->width()+fHorzGap, oy+y1, orientation);
00095 }
00096 endPlace();
00097 }
00098
00099
00103 point seqSchema::inputPoint(unsigned int i)
00104 {
00105 return fSchema1->inputPoint(i);
00106 }
00107
00108
00112 point seqSchema::outputPoint(unsigned int i)
00113 {
00114 return fSchema2->outputPoint(i);
00115 }
00116
00117
00118
00119
00120
00121
00125 void seqSchema::draw(device& dev)
00126 {
00127 assert(placed());
00128 assert(fSchema1->outputs() == fSchema2->inputs());
00129
00130 fSchema1->draw(dev);
00131 fSchema2->draw(dev);
00132 drawInternalWires(dev);
00133 }
00134
00135
00141 void seqSchema::drawInternalWires(device& dev)
00142 {
00143 assert (fSchema1->outputs() == fSchema2->inputs());
00144
00145 const int N = fSchema1->outputs();
00146 double dx = 0;
00147 double mx = 0;
00148 int dir =-1;
00149
00150 if (orientation() == kLeftRight) {
00151
00152 for (int i=0; i<N; i++) {
00153 point src = fSchema1->outputPoint(i);
00154 point dst = fSchema2->inputPoint(i);
00155 int d = direction(src,dst);
00156 if (d != dir) {
00157
00158 switch (d) {
00159 case kUpDir : mx = 0; dx = dWire; break;
00160 case kDownDir : mx = fHorzGap; dx = -dWire; break;
00161 default : mx = 0; dx = 0; break;
00162 }
00163 dir = d;
00164 } else {
00165
00166 mx = mx +dx;
00167 }
00168 if (src.y == dst.y) {
00169
00170 dev.trait(src.x, src.y, dst.x, dst.y);
00171 } else {
00172
00173 dev.trait(src.x, src.y, src.x+mx, src.y);
00174 dev.trait(src.x+mx, src.y, src.x+mx, dst.y);
00175 dev.trait(src.x+mx, dst.y, dst.x, dst.y);
00176 }
00177 }
00178 } else {
00179
00180 for (int i=0; i<N; i++) {
00181 point src = fSchema1->outputPoint(i);
00182 point dst = fSchema2->inputPoint(i);
00183 int d = direction(src,dst);
00184 if (d != dir) {
00185
00186 switch (d) {
00187 case kUpDir : mx = -fHorzGap; dx = dWire; break;
00188 case kDownDir : mx = 0; dx = -dWire; break;
00189 default : mx = 0; dx = 0; break;
00190 }
00191 dir = d;
00192 } else {
00193
00194 mx = mx +dx;
00195 }
00196 if (src.y == dst.y) {
00197
00198 dev.trait(src.x, src.y, dst.x, dst.y);
00199 } else {
00200
00201 dev.trait(src.x, src.y, src.x+mx, src.y);
00202 dev.trait(src.x+mx, src.y, src.x+mx, dst.y);
00203 dev.trait(src.x+mx, dst.y, dst.x, dst.y);
00204 }
00205 }
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00218 static int direction(const point& a, const point& b)
00219 {
00220 if (a.y > b.y) return kUpDir;
00221 if (a.y < b.y) return kDownDir;
00222 return kHorDir;
00223 }
00224
00230 static double computeHorzGap(schema* a, schema* b)
00231 {
00232 assert(a->outputs() == b->inputs());
00233
00234 if (a->outputs() == 0) {
00235 return 0;
00236 } else {
00237
00238 int MaxGroupSize[3]; for(int i=0; i<3; i++) MaxGroupSize[i]=0;
00239
00240
00241 double ya = max(0.0, 0.5*(b->height() - a->height()));
00242 double yb = max(0.0, 0.5*(a->height() - b->height()));
00243 a->place(0,ya,kLeftRight);
00244 b->place(0,yb,kLeftRight);
00245
00246
00247 int gdir = direction(a->outputPoint(0), b->inputPoint(0));
00248 int gsize = 1;
00249
00250
00251 for (unsigned int i=1; i<a->outputs(); i++) {
00252 int d = direction(a->outputPoint(i), b->inputPoint(i));
00253 if (d == gdir) {
00254 gsize++;
00255 } else {
00256 if (gsize > MaxGroupSize[gdir]) MaxGroupSize[gdir]=gsize;
00257 gsize = 1;
00258 gdir = d;
00259 }
00260 }
00261
00262
00263 if (gsize > MaxGroupSize[gdir]) MaxGroupSize[gdir]=gsize;
00264
00265
00266 return dWire * max(MaxGroupSize[kUpDir],MaxGroupSize[kDownDir]);
00267 }
00268 }