OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [tools/] [src/] [librlink/] [RlinkConnect.cpp] - Blame information for rev 10

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 wfjm
// $Id: RlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
2
//
3
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16
// 2011-04-02   375   1.0    Initial version
17
// 2011-01-15   356   0.1    First draft
18
// ---------------------------------------------------------------------------
19
 
20
/*!
21
  \file
22
  \version $Id: RlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
23
  \brief   Implemenation of RlinkConnect.
24
*/
25
 
26
#include <iostream>
27
 
28
#include <stdexcept>
29
 
30
#include "RlinkConnect.hpp"
31
#include "RlinkPortFactory.hpp"
32
 
33
#include "librtools/RosFill.hpp"
34
#include "librtools/RosPrintf.hpp"
35
#include "librtools/RosPrintBvi.hpp"
36
 
37
using namespace std;
38
using namespace Retro;
39
 
40
/*!
41
  \class Retro::RlinkConnect
42
  \brief FIXME_docs
43
*/
44
 
45
//------------------------------------------+-----------------------------------
46
//! Default constructor
47
 
48
RlinkConnect::RlinkConnect()
49
  : fpPort(0),
50
    fTxPkt(),
51
    fRxPkt(),
52
    fAddrMap(),
53
    fStats(),
54
    fLogOpts(),
55
    fLogFile(&cout)
56
{
57
  for (size_t i=0; i<8; i++) fSeqNumber[i] = 0;
58
 
59
  fStats.Define(kStatNExec,     "NExec",     "Exec() calls");
60
  fStats.Define(kStatNSplitVol, "NSplitVol", "clist splits: Volatile");
61
  fStats.Define(kStatNExecPart, "NExecPart", "ExecPart() calls");
62
  fStats.Define(kStatNCmd,      "NCmd",      "commands executed");
63
  fStats.Define(kStatNRreg,     "NRreg",     "rreg commands");
64
  fStats.Define(kStatNRblk,     "NRblk",     "rblk commands");
65
  fStats.Define(kStatNWreg,     "NWreg",     "wreg commands");
66
  fStats.Define(kStatNWblk,     "NWblk",     "wblk commands");
67
  fStats.Define(kStatNStat,     "NStat",     "stat commands");
68
  fStats.Define(kStatNAttn,     "NAttn",     "attn commands");
69
  fStats.Define(kStatNInit,     "NInit",     "init commands");
70
  fStats.Define(kStatNRblkWord, "NRblkWord", "words rcvd with rblk");
71
  fStats.Define(kStatNWblkWord, "NWblkWord", "words send with wblk");
72
  fStats.Define(kStatNTxPktByt, "NTxPktByt", "Tx packet bytes send");
73
  fStats.Define(kStatNTxEsc,    "NTxEsc",    "Tx escapes");
74
  fStats.Define(kStatNRxPktByt, "NRxPktByt", "Rx packet bytes rcvd");
75
  fStats.Define(kStatNRxEsc,    "NRxEsc",    "Rx escapes");
76
  fStats.Define(kStatNRxAttn,   "NRxAttn",   "Rx ATTN commas seen");
77
  fStats.Define(kStatNRxIdle,   "NRxIdle",   "Rx IDLE commas seen");
78
  fStats.Define(kStatNRxDrop,   "NRxDrop",   "Rx bytes droped");
79
  fStats.Define(kStatNExpData,  "NExpData",  "Expect() for data defined");
80
  fStats.Define(kStatNExpStat,  "NExpStat",  "Expect() for stat defined");
81
  fStats.Define(kStatNChkData,  "NChkData",  "expect data failed");
82
  fStats.Define(kStatNChkStat,  "NChkStat",  "expect stat failed");
83
  fStats.Define(kStatNSndOob,   "NSndOob",   "SndOob() calls");
84
}
85
 
86
//------------------------------------------+-----------------------------------
87
//! Destructor
88
 
89
RlinkConnect::~RlinkConnect()
90
{
91
  delete fpPort;
92
}
93
 
94
//------------------------------------------+-----------------------------------
95
//! FIXME_docs
96
 
97
bool RlinkConnect::Open(const std::string& name, RerrMsg& emsg)
98
{
99
  if (fpPort) Close();
100
 
101
  fpPort = RlinkPortFactory::Open(name, emsg);
102
  if (!fpPort) return false;
103
 
104
  fpPort->SetLogFile(&fLogFile);
105
  fpPort->SetTraceLevel(fLogOpts.tracelevel);
106
  return true;
107
}
108
 
109
//------------------------------------------+-----------------------------------
110
//! FIXME_docs
111
 
112
void RlinkConnect::Close()
113
{
114
  if (!fpPort)
115
    throw logic_error("RlinkConnect::PortClose(): no port connected");
116
 
117
  if (fpPort->UrlFindOpt("keep")) {
118
    RerrMsg emsg;
119
    fTxPkt.SndKeep(fpPort, emsg);
120
  }
121
 
122
  delete fpPort;
123
  fpPort = 0;
124
 
125
  return;
126
}
127
 
128
//------------------------------------------+-----------------------------------
129
//! FIXME_docs
130
 
131
bool RlinkConnect::Exec(RlinkCommandList& clist, RerrMsg& emsg)
132
{
133
  if (clist.Size() == 0)
134
    throw invalid_argument("RlinkConnect::Exec(): clist empty");
135
  if (! IsOpen())
136
    throw logic_error("RlinkConnect::Exec(): port not open");
137
 
138
  fStats.Inc(kStatNExec);
139
 
140
  size_t ibeg = 0;
141
  size_t size = clist.Size();
142
 
143
  for (size_t i=0; i<size; i++) {
144
    RlinkCommand& cmd = clist[i];
145
   if (!cmd.TestFlagAny(RlinkCommand::kFlagInit))
146
      throw invalid_argument("RlinkConnect::Exec(): command not initialized");
147
    if (cmd.Command() > RlinkCommand::kCmdInit)
148
      throw invalid_argument("RlinkConnect::Exec(): invalid command code");
149
    cmd.ClearFlagBit(RlinkCommand::kFlagSend   | RlinkCommand::kFlagDone |
150
                     RlinkCommand::kFlagPktBeg | RlinkCommand::kFlagPktEnd |
151
                     RlinkCommand::kFlagRecov  | RlinkCommand::kFlagResend |
152
                     RlinkCommand::kFlagErrNak | RlinkCommand::kFlagErrMiss |
153
                     RlinkCommand::kFlagErrCmd | RlinkCommand::kFlagErrCrc);
154
  }
155
 
156
  while (ibeg < size) {
157
    size_t iend = ibeg;
158
    for (size_t i=ibeg; i<size; i++) {
159
      iend = i;
160
      if (clist[i].TestFlagAll(RlinkCommand::kFlagVol)) {
161
        fStats.Inc(kStatNSplitVol);
162
        break;
163
      }
164
    }
165
    bool rc = ExecPart(clist, ibeg, iend, emsg);
166
    if (!rc) return rc;
167
    ibeg = iend+1;
168
  }
169
 
170
  bool checkseen = false;
171
  bool errorseen = false;
172
 
173
  for (size_t i=0; i<size; i++) {
174
    RlinkCommand& cmd = clist[i];
175
 
176
    checkseen |= cmd.TestFlagAny(RlinkCommand::kFlagChkStat |
177
                                 RlinkCommand::kFlagChkData);
178
    errorseen |= cmd.TestFlagAny(RlinkCommand::kFlagErrNak |
179
                                 RlinkCommand::kFlagErrMiss |
180
                                 RlinkCommand::kFlagErrCmd |
181
                                 RlinkCommand::kFlagErrCrc);
182
  }
183
 
184
  size_t loglevel = 3;
185
  if (checkseen) loglevel = 2;
186
  if (errorseen) loglevel = 1;
187
  if (loglevel <= fLogOpts.printlevel)
188
    clist.Print(fLogFile(), &AddrMap(), fLogOpts.baseaddr, fLogOpts.basedata,
189
                fLogOpts.basestat);
190
  if (loglevel <= fLogOpts.dumplevel)
191
    clist.Dump(fLogFile(), 0);
192
 
193
  return true;
194
}
195
 
196
//------------------------------------------+-----------------------------------
197
//! FIXME_docs
198
 
199
bool RlinkConnect::ExecPart(RlinkCommandList& clist, size_t ibeg, size_t iend,
200
                            RerrMsg& emsg)
201
{
202
  if (ibeg<0 || ibeg>iend || iend>=clist.Size())
203
    throw invalid_argument("RlinkConnect::ExecPart(): ibeg or iend invalid");
204
  if (!IsOpen())
205
    throw logic_error("RlinkConnect::ExecPart(): port not open");
206
 
207
  fStats.Inc(kStatNExecPart);
208
 
209
  size_t nrcvtot = 0;
210
  fTxPkt.Init();
211
 
212
  for (size_t i=ibeg; i<=iend; i++) {
213
    RlinkCommand& cmd = clist[i];
214
    uint8_t   ccode = cmd.Command();
215
    size_t    ndata = cmd.BlockSize();
216
    uint16_t* pdata = cmd.BlockPointer();
217
 
218
    fStats.Inc(kStatNCmd);
219
 
220
    cmd.SetSeqNumber(fSeqNumber[ccode]++);
221
    cmd.ClearFlagBit(RlinkCommand::kFlagPktBeg | RlinkCommand::kFlagPktEnd);
222
 
223
    fTxPkt.PutWithCrc(cmd.Request());
224
 
225
    switch(ccode) {
226
      case RlinkCommand::kCmdRreg:
227
        fStats.Inc(kStatNRreg);
228
        cmd.SetRcvSize(1+2+1+1);            // rcv: cmd+data+stat+crc
229
        fTxPkt.PutWithCrc((uint8_t)cmd.Address());
230
        break;
231
 
232
      case RlinkCommand::kCmdRblk:
233
        fStats.Inc(kStatNRblk);
234
        fStats.Inc(kStatNRblkWord, (double) ndata);
235
        cmd.SetRcvSize(1+1+2*ndata+1+1);    // rcv: cmd+nblk+n*data+stat+crc
236
        fTxPkt.PutWithCrc((uint8_t)cmd.Address());
237
        fTxPkt.PutWithCrc((uint8_t)(ndata-1));
238
        break;
239
 
240
      case RlinkCommand::kCmdWreg:
241
        fStats.Inc(kStatNWreg);
242
        cmd.SetRcvSize(1+1+1);              // rcv: cmd+stat+crc
243
        fTxPkt.PutWithCrc((uint8_t)cmd.Address());
244
        fTxPkt.PutWithCrc(cmd.Data());
245
        break;
246
 
247
      case RlinkCommand::kCmdWblk:
248
        fStats.Inc(kStatNWblk);
249
        fStats.Inc(kStatNWblkWord, (double) ndata);
250
        cmd.SetRcvSize(1+1+1);              // rcv: cmd+stat+crc
251
        fTxPkt.PutWithCrc((uint8_t)cmd.Address());
252
        fTxPkt.PutWithCrc((uint8_t)(ndata-1));
253
        fTxPkt.PutCrc();
254
        for (size_t j=0; j<ndata; j++) fTxPkt.PutWithCrc(*pdata++);
255
        break;
256
 
257
      case RlinkCommand::kCmdStat:
258
        fStats.Inc(kStatNStat);
259
        cmd.SetRcvSize(1+1+2+1+1);          // rcv: cmd+ccmd+data+stat+crc
260
        break;
261
      case RlinkCommand::kCmdAttn:
262
        fStats.Inc(kStatNAttn);
263
        cmd.SetRcvSize(1+2+1+1);            // rcv: cmd+data+stat+crc
264
        break;
265
 
266
      case RlinkCommand::kCmdInit:
267
        fStats.Inc(kStatNInit);
268
        cmd.SetRcvSize(1+1+1);              // rcv: cmd+stat+crc
269
        fTxPkt.PutWithCrc((uint8_t)cmd.Address());
270
        fTxPkt.PutWithCrc(cmd.Data());
271
        break;
272
 
273
      default:
274
        throw logic_error("RlinkConnect::Exec(): invalid command");
275
    }
276
 
277
    fTxPkt.PutCrc();
278
    cmd.SetFlagBit(RlinkCommand::kFlagSend);
279
    nrcvtot += cmd.RcvSize();
280
  }
281
 
282
  clist[ibeg].SetFlagBit(RlinkCommand::kFlagPktBeg);
283
  clist[iend].SetFlagBit(RlinkCommand::kFlagPktEnd);
284
 
285
  // FIXME_code: handle send fail properly;
286
  if (!fTxPkt.SndPacket(fpPort, emsg)) return false;
287
  fStats.Inc(kStatNTxPktByt, double(fTxPkt.PktSize()));
288
  fStats.Inc(kStatNTxEsc   , double(fTxPkt.Nesc()));
289
 
290
  fRxPkt.Init();
291
  // FIXME_code: handle timeout properly; parametrize timeout
292
  if (!fRxPkt.RcvPacket(fpPort, nrcvtot, 1.0, emsg)) return false;
293
  fStats.Inc(kStatNRxPktByt, double(fRxPkt.PktSize()));
294
  fStats.Inc(kStatNRxEsc   , double(fRxPkt.Nesc()));
295
  fStats.Inc(kStatNRxAttn  , double(fRxPkt.Nattn()));
296
  fStats.Inc(kStatNRxIdle  , double(fRxPkt.Nidle()));
297
  fStats.Inc(kStatNRxDrop  , double(fRxPkt.Ndrop()));
298
 
299
  size_t ncmd = 0;
300
 
301
  for (size_t i=ibeg; i<=iend; i++) {
302
    RlinkCommand& cmd = clist[i];
303
    uint8_t   ccode = cmd.Command();
304
    size_t    ndata = cmd.BlockSize();
305
    uint16_t* pdata = cmd.BlockPointer();
306
 
307
    if (!fRxPkt.CheckSize(cmd.RcvSize())) {   // not enough data for cmd
308
      cmd.SetFlagBit(RlinkCommand::kFlagErrMiss);
309
      break;
310
    }
311
 
312
    if (fRxPkt.Get8WithCrc() != cmd.Request()) { // command mismatch
313
      cmd.SetFlagBit(RlinkCommand::kFlagErrCmd);
314
      break;
315
    }
316
 
317
    // check length mismatch in rblk here (simpler than multi-level break)
318
    if (ccode == RlinkCommand::kCmdRblk) {
319
      if (fRxPkt.Get8WithCrc() != (uint8_t)(ndata-1)) {  // length mismatch
320
        cmd.SetFlagBit(RlinkCommand::kFlagErrCmd);
321
        break;
322
      }
323
    }
324
 
325
    switch(ccode) {
326
      case RlinkCommand::kCmdRreg:
327
        cmd.SetData(fRxPkt.Get16WithCrc());
328
        break;
329
 
330
      case RlinkCommand::kCmdRblk:
331
        // length was consumed and tested already before switch()..
332
        for (size_t j=0; j<ndata; j++) *pdata++ = fRxPkt.Get16WithCrc();
333
        break;
334
 
335
      case RlinkCommand::kCmdWreg:
336
      case RlinkCommand::kCmdWblk:
337
        break;
338
 
339
      case RlinkCommand::kCmdStat:
340
        cmd.SetStatRequest(fRxPkt.Get8WithCrc());
341
        cmd.SetData(fRxPkt.Get16WithCrc());
342
        break;
343
 
344
      case RlinkCommand::kCmdAttn:
345
        cmd.SetData(fRxPkt.Get16WithCrc());
346
        break;
347
 
348
      case RlinkCommand::kCmdInit:
349
        break;
350
    }
351
 
352
    cmd.SetStatus(fRxPkt.Get8WithCrc());
353
    if (!fRxPkt.CheckCrc()) {                 // crc mismatch
354
      cmd.SetFlagBit(RlinkCommand::kFlagErrCrc);
355
      //fStats.Inc(kStatNRxCcrc);
356
      break;
357
    }
358
 
359
    // FIXME_code: proper wblk dcrc handling...
360
    if (ccode == RlinkCommand::kCmdWblk) {
361
      // FIXME_code: check for dcrc flag...
362
      if (false) {
363
        //fStats.Inc(kStatNRxDcrc);
364
        break;
365
      }
366
    }
367
 
368
    cmd.SetFlagBit(RlinkCommand::kFlagDone);
369
    ncmd += 1;
370
 
371
    if (cmd.Expect()) {
372
      RlinkCommandExpect& expect = *cmd.Expect();
373
      if (expect.DataIsChecked() ||
374
          expect.BlockValue().size()>0) fStats.Inc(kStatNExpData);
375
      if (expect.StatusIsChecked())     fStats.Inc(kStatNExpStat);
376
 
377
      if (ccode==RlinkCommand::kCmdRreg || ccode==RlinkCommand::kCmdStat ||
378
          ccode==RlinkCommand::kCmdAttn) {
379
        if (!expect.DataCheck(cmd.Data())) {
380
          fStats.Inc(kStatNChkData);
381
          cmd.SetFlagBit(RlinkCommand::kFlagChkData);
382
        }
383
      } else if (ccode==RlinkCommand::kCmdRblk) {
384
        size_t nerr = expect.BlockCheck(cmd.BlockPointer(), cmd.BlockSize());
385
        if (nerr != 0) {
386
          fStats.Inc(kStatNChkData);
387
          cmd.SetFlagBit(RlinkCommand::kFlagChkData);
388
        }
389
      }
390
      if (!expect.StatusCheck(cmd.Status())) {
391
        fStats.Inc(kStatNChkStat);
392
        cmd.SetFlagBit(RlinkCommand::kFlagChkStat);
393
      }
394
    }
395
 
396
  }
397
 
398
  // FIXME_code: add proper error handling...
399
  if (ncmd != iend-ibeg+1) {
400
    return false;
401
  }
402
 
403
  return true;
404
}
405
 
406
//------------------------------------------+-----------------------------------
407
//! FIXME_docs
408
 
409
double RlinkConnect::WaitAttn(double timeout, RerrMsg& emsg)
410
{
411
  double rval = fRxPkt.WaitAttn(fpPort, timeout, emsg);
412
  fStats.Inc(kStatNRxAttn  , double(fRxPkt.Nattn()));
413
  fStats.Inc(kStatNRxIdle  , double(fRxPkt.Nidle()));
414
  fStats.Inc(kStatNRxDrop  , double(fRxPkt.Ndrop()));
415
  return rval;
416
}
417
 
418
//------------------------------------------+-----------------------------------
419
//! FIXME_docs
420
 
421
bool RlinkConnect::SndOob(uint16_t addr, uint16_t data, RerrMsg& emsg)
422
{
423
  fStats.Inc(kStatNSndOob);
424
  return fTxPkt.SndOob(fpPort, addr, data, emsg);
425
}
426
 
427
//------------------------------------------+-----------------------------------
428
//! FIXME_docs
429
 
430
bool RlinkConnect::LogOpen(const std::string& name)
431
{
432
  if (!fLogFile.Open(name)) {
433
    fLogFile.UseStream(&cout);
434
    return false;
435
  }
436
  return true;
437
}
438
 
439
//------------------------------------------+-----------------------------------
440
//! FIXME_docs
441
 
442
void RlinkConnect::LogUseStream(std::ostream* pstr)
443
{
444
  fLogFile.UseStream(pstr);
445
  return;
446
}
447
 
448
//------------------------------------------+-----------------------------------
449
//! FIXME_docs
450
 
451
void RlinkConnect::SetLogOpts(const LogOpts& opts)
452
{
453
  if (opts.baseaddr!=2 && opts.baseaddr!=8 && opts.baseaddr!=16)
454
    throw invalid_argument("RlinkConnect::SetLogOpts(): baseaddr != 2,8,16");
455
  if (opts.basedata!=2 && opts.basedata!=8 && opts.basedata!=16)
456
    throw invalid_argument("RlinkConnect::SetLogOpts(): basedata != 2,8,16");
457
  if (opts.basestat!=2 && opts.basestat!=8 && opts.basestat!=16)
458
    throw invalid_argument("RlinkConnect::SetLogOpts(): basestat != 2,8,16");
459
 
460
  fLogOpts = opts;
461
  if (fpPort) fpPort->SetTraceLevel(opts.tracelevel);
462
  return;
463
}
464
 
465
//------------------------------------------+-----------------------------------
466
//! FIXME_docs
467
 
468
void RlinkConnect::Print(std::ostream& os) const
469
{
470
  os << "RlinkConnect::Print(std::ostream& os)" << endl;
471
  return;
472
}
473
 
474
//------------------------------------------+-----------------------------------
475
//! FIXME_docs
476
 
477
void RlinkConnect::Dump(std::ostream& os, int ind, const char* text) const
478
{
479
  RosFill bl(ind);
480
  os << bl << (text?text:"--") << "RlinkConnect @ " << this << endl;
481
 
482
  if (fpPort) {
483
    fpPort->Dump(os, ind+2, "fpPort: ");
484
  } else {
485
    os << bl << "  fpPort:          " <<  fpPort << endl;
486
  }
487
 
488
  os << bl << "  fSeqNumber:      ";
489
  for (size_t i=0; i<8; i++) os << RosPrintBvi(fSeqNumber[i],16) << " ";
490
  os << endl;
491
 
492
  fTxPkt.Dump(os, ind+2, "fTxPkt: ");
493
  fRxPkt.Dump(os, ind+2, "fRxPkt: ");
494
  fAddrMap.Dump(os, ind+2, "fAddrMap: ");
495
  fStats.Dump(os, ind+2, "fStats: ");
496
  return;
497
}
498
 
499
//------------------------------------------+-----------------------------------
500
#if (defined(Retro_NoInline) || defined(Retro_RlinkConnect_NoInline))
501
#define inline
502
#include "RlinkConnect.ipp"
503
#undef  inline
504
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.