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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [tools/] [src/] [librw11/] [Rw11Cpu.cpp] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 wfjm
// $Id: Rw11Cpu.cpp 576 2014-08-02 12:24:28Z mueller $
2 19 wfjm
//
3 25 wfjm
// Copyright 2013-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 19 wfjm
//
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 25 wfjm
// 2014-08-02   576   1.0.2  adopt rename of LastExpect->SetLastExpect
17 20 wfjm
// 2013-04-14   506   1.0.1  add AddLalh(),AddRMem(),AddWMem()
18 19 wfjm
// 2013-04-12   504   1.0    Initial version
19
// 2013-01-27   478   0.1    First draft
20
// ---------------------------------------------------------------------------
21
 
22
/*!
23
  \file
24 25 wfjm
  \version $Id: Rw11Cpu.cpp 576 2014-08-02 12:24:28Z mueller $
25 19 wfjm
  \brief   Implemenation of Rw11Cpu.
26
*/
27
#include <stdlib.h>
28
#include <fcntl.h>
29
#include <errno.h>
30
 
31
#include <vector>
32
#include <map>
33
#include <algorithm>
34
 
35
#include "boost/date_time/posix_time/posix_time_types.hpp"
36
 
37
#include "librtools/Rexception.hpp"
38
#include "librtools/RlogMsg.hpp"
39
#include "librtools/RosFill.hpp"
40
#include "librtools/RosPrintf.hpp"
41
#include "librtools/RosPrintBvi.hpp"
42
#include "Rw11Cntl.hpp"
43
 
44
#include "Rw11Cpu.hpp"
45
 
46
using namespace std;
47
 
48
/*!
49
  \class Retro::Rw11Cpu
50
  \brief FIXME_docs
51
*/
52
 
53
// all method definitions in namespace Retro
54
namespace Retro {
55
 
56
//------------------------------------------+-----------------------------------
57
// constants definitions
58
 
59
const uint16_t  Rw11Cpu::kCp_addr_conf;
60
const uint16_t  Rw11Cpu::kCp_addr_cntl;
61
const uint16_t  Rw11Cpu::kCp_addr_stat;
62
const uint16_t  Rw11Cpu::kCp_addr_psw;
63
const uint16_t  Rw11Cpu::kCp_addr_al;
64
const uint16_t  Rw11Cpu::kCp_addr_ah;
65
const uint16_t  Rw11Cpu::kCp_addr_mem;
66
const uint16_t  Rw11Cpu::kCp_addr_memi;
67
const uint16_t  Rw11Cpu::kCp_addr_r0;
68
const uint16_t  Rw11Cpu::kCp_addr_pc;
69
const uint16_t  Rw11Cpu::kCp_addr_ibrb;
70
const uint16_t  Rw11Cpu::kCp_addr_ibr;
71
 
72
const uint16_t  Rw11Cpu::kCp_func_noop;
73
const uint16_t  Rw11Cpu::kCp_func_start;
74
const uint16_t  Rw11Cpu::kCp_func_stop;
75
const uint16_t  Rw11Cpu::kCp_func_cont;
76
const uint16_t  Rw11Cpu::kCp_func_step;
77
const uint16_t  Rw11Cpu::kCp_func_reset;
78
 
79
const uint16_t  Rw11Cpu::kCp_stat_m_cpurust;
80
const uint16_t  Rw11Cpu::kCp_stat_v_cpurust;
81
const uint16_t  Rw11Cpu::kCp_stat_b_cpurust;
82
const uint16_t  Rw11Cpu::kCp_stat_m_cpuhalt;
83
const uint16_t  Rw11Cpu::kCp_stat_m_cpugo;
84
const uint16_t  Rw11Cpu::kCp_stat_m_cmdmerr;
85
const uint16_t  Rw11Cpu::kCp_stat_m_cmderr;
86
 
87
const uint16_t  Rw11Cpu::kCp_cpurust_init;
88
const uint16_t  Rw11Cpu::kCp_cpurust_halt;
89
const uint16_t  Rw11Cpu::kCp_cpurust_reset;
90
const uint16_t  Rw11Cpu::kCp_cpurust_stop;
91
const uint16_t  Rw11Cpu::kCp_cpurust_step;
92
const uint16_t  Rw11Cpu::kCp_cpurust_susp;
93
const uint16_t  Rw11Cpu::kCp_cpurust_runs;
94
const uint16_t  Rw11Cpu::kCp_cpurust_vecfet;
95
const uint16_t  Rw11Cpu::kCp_cpurust_recrsv;
96
const uint16_t  Rw11Cpu::kCp_cpurust_sfail;
97
const uint16_t  Rw11Cpu::kCp_cpurust_vfail;
98
 
99 20 wfjm
const uint16_t  Rw11Cpu::kCp_ah_m_addr;
100
const uint16_t  Rw11Cpu::kCp_ah_m_22bit;
101
const uint16_t  Rw11Cpu::kCp_ah_m_ubmap;
102
 
103 19 wfjm
//------------------------------------------+-----------------------------------
104
//! Constructor
105
 
106
Rw11Cpu::Rw11Cpu(const std::string& type)
107
  : fpW11(0),
108
    fType(type),
109
    fIndex(0),
110
    fBase(0),
111
    fCpuGo(0),
112
    fCpuStat(0),
113
    fCpuGoMutex(),
114
    fCpuGoCond(),
115
    fCntlMap(),
116
    fStats()
117
{}
118
 
119
//------------------------------------------+-----------------------------------
120
//! Destructor
121
 
122
Rw11Cpu::~Rw11Cpu()
123
{}
124
 
125
//------------------------------------------+-----------------------------------
126
//! FIXME_docs
127
 
128
void Rw11Cpu::Setup(Rw11* pw11)
129
{
130
  fpW11 = pw11;
131
  // command base: 'cn.', where n is cpu index
132
  string cbase = "c";
133
  cbase += '0'+Index();
134
  cbase += '.';
135
  Connect().AddrMapInsert(cbase+"conf", Base()+kCp_addr_conf);
136
  Connect().AddrMapInsert(cbase+"cntl", Base()+kCp_addr_cntl);
137
  Connect().AddrMapInsert(cbase+"stat", Base()+kCp_addr_stat);
138
  Connect().AddrMapInsert(cbase+"psw" , Base()+kCp_addr_psw);
139
  Connect().AddrMapInsert(cbase+"al"  , Base()+kCp_addr_al);
140
  Connect().AddrMapInsert(cbase+"ah"  , Base()+kCp_addr_ah);
141
  Connect().AddrMapInsert(cbase+"mem" , Base()+kCp_addr_mem);
142
  Connect().AddrMapInsert(cbase+"memi", Base()+kCp_addr_memi);
143
  Connect().AddrMapInsert(cbase+"r0"  , Base()+kCp_addr_r0);
144
  Connect().AddrMapInsert(cbase+"r1"  , Base()+kCp_addr_r0+1);
145
  Connect().AddrMapInsert(cbase+"r2"  , Base()+kCp_addr_r0+2);
146
  Connect().AddrMapInsert(cbase+"r3"  , Base()+kCp_addr_r0+3);
147
  Connect().AddrMapInsert(cbase+"r4"  , Base()+kCp_addr_r0+4);
148
  Connect().AddrMapInsert(cbase+"r5"  , Base()+kCp_addr_r0+5);
149
  Connect().AddrMapInsert(cbase+"sp"  , Base()+kCp_addr_r0+6);
150
  Connect().AddrMapInsert(cbase+"pc"  , Base()+kCp_addr_r0+7);
151
  Connect().AddrMapInsert(cbase+"ibrb", Base()+kCp_addr_ibrb);
152
  // create names for ib window, line c0.ib00, c0.ib02,.., c0.ib76
153
  for (int i=0; i<32; i++) {
154
    string rname = cbase + "ib";
155
    rname += '0' + ((i>>2)&07);
156
    rname += '0' + ((i<<1)&07);
157
    Connect().AddrMapInsert(rname , Base()+kCp_addr_ibr+i);
158
  }
159
  return;
160
}
161
 
162
//------------------------------------------+-----------------------------------
163
//! FIXME_docs
164
 
165
void Rw11Cpu::AddCntl(const boost::shared_ptr<Rw11Cntl>& spcntl)
166
{
167
  if (!spcntl)
168
    throw Rexception("Rw11Cpu::AddCntl","Bad args: spcntl == 0");
169
 
170
  string name(spcntl->Name());
171
  if (fCntlMap.find(name) != fCntlMap.end())
172
    throw Rexception("Rw11Cpu::AddCntl",
173
                     "Bad state: duplicate controller name");;
174
 
175
  fCntlMap.insert(cmap_val_t(name, spcntl));
176
  spcntl->SetCpu(this);
177
  return;
178
}
179
 
180
//------------------------------------------+-----------------------------------
181
//! FIXME_docs
182
 
183
bool Rw11Cpu::TestCntl(const std::string& name) const
184
{
185
  return fCntlMap.find(name) != fCntlMap.end();
186
}
187
 
188
//------------------------------------------+-----------------------------------
189
//! FIXME_docs
190
 
191
void Rw11Cpu::ListCntl(std::vector<std::string>& list) const
192
{
193
  list.clear();
194
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
195
    list.push_back((it->second)->Name());
196
  }
197
  return;
198
}
199
 
200
//------------------------------------------+-----------------------------------
201
//! FIXME_docs
202
 
203
Rw11Cntl& Rw11Cpu::Cntl(const std::string& name) const
204
{
205
  cmap_cit_t it=fCntlMap.find(name);
206
  if (it == fCntlMap.end())
207
    throw Rexception("Rw11Cpu::Cntl()",
208
                     "Bad args: controller name '" + name + "' unknown");
209
  return *(it->second);
210
}
211
 
212
//------------------------------------------+-----------------------------------
213
//! FIXME_docs
214
 
215
void Rw11Cpu::Start()
216
{
217
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
218
    Rw11Cntl& cntl(*(it->second));
219
    cntl.Probe();
220
    if (cntl.ProbeStatus().Found() && cntl.Enable()) {
221
      cntl.Start();
222
    }
223
  }
224
  return;
225
}
226
 
227
 
228
//------------------------------------------+-----------------------------------
229
//! FIXME_docs
230
 
231
std::string Rw11Cpu::NextCntlName(const std::string& base) const
232
{
233
  for (char let='a'; let<='z'; let++) {
234
    string name = base + let;
235
    if (fCntlMap.find(name) == fCntlMap.end()) return name;
236
  }
237
  throw Rexception("Rw11Cpu::NextCntlName",
238
                   "Bad args: all controller letters used for '" + base + "'");
239
  return "";
240
}
241
 
242
//------------------------------------------+-----------------------------------
243
//! FIXME_docs
244
 
245
int Rw11Cpu::AddIbrb(RlinkCommandList& clist, uint16_t ibaddr)
246
{
247
  return clist.AddWreg(fBase+kCp_addr_ibrb, ibaddr & ~(077));
248
}
249
 
250
//------------------------------------------+-----------------------------------
251
//! FIXME_docs
252
 
253
int Rw11Cpu::AddRibr(RlinkCommandList& clist, uint16_t ibaddr)
254
{
255
  uint16_t ibroff = (ibaddr & 077)/2;
256
  return clist.AddRreg(fBase+kCp_addr_ibr + ibroff);
257
}
258
 
259
//------------------------------------------+-----------------------------------
260
//! FIXME_docs
261
 
262
int Rw11Cpu::AddWibr(RlinkCommandList& clist, uint16_t ibaddr, uint16_t data)
263
{
264
  uint16_t ibroff = (ibaddr & 077)/2;
265
  return clist.AddWreg(fBase+kCp_addr_ibr + ibroff, data);
266
}
267
 
268
//------------------------------------------+-----------------------------------
269
//! FIXME_docs
270
 
271 20 wfjm
int Rw11Cpu::AddLalh(RlinkCommandList& clist, uint32_t addr, uint16_t mode)
272
{
273
  uint16_t al = uint16_t(addr);
274
  uint16_t ah = uint16_t(addr>>16) & kCp_ah_m_addr;
275
  ah |= mode & (kCp_ah_m_22bit|kCp_ah_m_ubmap);
276
  int ind = clist.AddWreg(fBase+kCp_addr_al, al);
277
  clist.AddWreg(fBase+kCp_addr_ah, ah);
278
  return ind;
279
}
280
 
281
//------------------------------------------+-----------------------------------
282
//! FIXME_docs
283
 
284
int Rw11Cpu::AddRMem(RlinkCommandList& clist, uint32_t addr,
285
                     uint16_t* buf, size_t size, uint16_t mode)
286
{
287
  int ind = AddLalh(clist, addr, mode);
288
  while (size > 0) {
289
    size_t bsize = (size>256) ? 256 : size;
290
    clist.AddRblk(fBase+kCp_addr_memi, buf, bsize);
291
    buf  += bsize;
292
    size -= bsize;
293
  }
294
  return ind;
295
}
296
 
297
//------------------------------------------+-----------------------------------
298
//! FIXME_docs
299
 
300
int Rw11Cpu::AddWMem(RlinkCommandList& clist, uint32_t addr,
301
                     const uint16_t* buf, size_t size, uint16_t mode)
302
{
303
  int ind = AddLalh(clist, addr, mode);
304
  while (size > 0) {
305
    size_t bsize = (size>256) ? 256 : size;
306
    clist.AddWblk(fBase+kCp_addr_memi, buf, bsize);
307
    buf  += bsize;
308
    size -= bsize;
309
  }
310
  return ind;
311
}
312
 
313
//------------------------------------------+-----------------------------------
314
//! FIXME_docs
315
 
316 19 wfjm
bool Rw11Cpu::MemRead(uint16_t addr, std::vector<uint16_t>& data,
317
                      size_t nword, RerrMsg& emsg)
318
{
319
  data.resize(nword);
320
  size_t ndone = 0;
321
  while (nword>ndone) {
322
    size_t nblk = min(size_t(256), nword-ndone);
323
    RlinkCommandList clist;
324
    clist.AddWreg(fBase+kCp_addr_al, addr+2*ndone);
325
    clist.AddRblk(fBase+kCp_addr_memi, data.data()+ndone, nblk);
326
    if (!Server().Exec(clist, emsg)) return false;
327
    ndone += nblk;
328
  }
329
  return true;
330
}
331
 
332
//------------------------------------------+-----------------------------------
333
//! FIXME_docs
334
 
335
bool Rw11Cpu::MemWrite(uint16_t addr, const std::vector<uint16_t>& data,
336
                       RerrMsg& emsg)
337
{
338
  size_t nword = data.size();
339
  size_t ndone = 0;
340
  while (nword>ndone) {
341
    size_t nblk = min(size_t(256), nword-ndone);
342
    RlinkCommandList clist;
343
    clist.AddWreg(fBase+kCp_addr_al, addr+2*ndone);
344
    clist.AddWblk(fBase+kCp_addr_memi, data.data()+ndone, nblk);
345
    if (!Server().Exec(clist, emsg)) return false;
346
    ndone += nblk;
347
  }
348
  return true;
349
}
350
 
351
//------------------------------------------+-----------------------------------
352
//! FIXME_docs
353
 
354
bool Rw11Cpu::ProbeCntl(Rw11Probe& dsc)
355
{
356
  if (!(dsc.fProbeInt | dsc.fProbeRem) || dsc.fAddr == 0)
357
    throw Rexception("Rw11Cpu::Probe",
358
                     "Bad args: fAddr == 0 or fProbeInt|fProbeRem == false");
359
 
360
  if (!dsc.fProbeDone) {
361
    RlinkCommandList clist;
362
    int iib = -1;
363
    int irb = -1;
364
    if (dsc.fProbeInt) {
365
      clist.AddWreg(fBase+kCp_addr_al,  dsc.fAddr);
366
      iib = clist.AddRreg(fBase+kCp_addr_mem);
367 25 wfjm
      clist.SetLastExpect(new RlinkCommandExpect(0,0xff)); // disable stat check
368 19 wfjm
    }
369
    if (dsc.fProbeRem) {
370
      AddIbrb(clist, dsc.fAddr);
371
      irb = AddRibr(clist, dsc.fAddr);
372 25 wfjm
      clist.SetLastExpect(new RlinkCommandExpect(0,0xff)); // disable stat check
373 19 wfjm
    }
374
 
375
    Server().Exec(clist);
376
    // FIXME_code: handle errors
377
 
378
    if (dsc.fProbeInt) {
379
      dsc.fFoundInt = (clist[iib].Status() & (RlinkCommand::kStat_M_RbNak |
380
                                              RlinkCommand::kStat_M_RbErr)) ==0;
381
    }
382
    if (dsc.fProbeRem) {
383
      dsc.fFoundRem = (clist[irb].Status() & (RlinkCommand::kStat_M_RbNak |
384
                                              RlinkCommand::kStat_M_RbErr)) ==0;
385
    }
386
    dsc.fProbeDone = true;
387
  }
388
 
389
  return dsc.Found();
390
}
391
 
392
//------------------------------------------+-----------------------------------
393
//! FIXME_docs
394
 
395
// absolute binary format described in notes_ptape.txt
396
 
397
bool Rw11Cpu::LoadAbs(const std::string& fname, RerrMsg& emsg, bool trace)
398
{
399
  int fd = open(fname.c_str(), O_RDONLY);
400
 
401
  if (fd < 0) {
402
    emsg.InitErrno("Rw11Cpu::LoadAbs()", string("open() for '") + fname +
403 21 wfjm
                   "' failed: ", errno);
404 19 wfjm
    return false;
405
  }
406
 
407
  enum states {
408
    s_chr0,
409
    s_chr1,
410
    s_cntlow,
411
    s_cnthgh,
412
    s_adrlow,
413
    s_adrhgh,
414
    s_data,
415
    s_chksum
416
  };
417
 
418
  typedef std::map<uint16_t, uint16_t> obmap_t;
419
  typedef obmap_t::iterator         obmap_it_t;
420
  typedef obmap_t::const_iterator   obmap_cit_t;
421
  typedef obmap_t::value_type       obmap_val_t;
422
 
423
  obmap_t oddbyte;                          // odd byte cache
424
 
425
  vector<uint16_t> data;
426
  data.reserve(256);
427
 
428
  int chrnum = -1;                          // char number in block
429
  int blknum = 0;                           // block number
430
  int bytcnt = 0;                           // byte count
431
  uint16_t ldaddr = 0;                      // load address
432
  uint8_t chksum = 0;                       // check sum
433
  uint16_t addr = 0;                        // current address
434
  uint16_t word = 0;                        // current word
435
 
436
  bool ok = false;
437
  bool go = true;
438
  enum states state = s_chr0;
439
 
440
  while (go) {
441
    uint8_t byte;
442
    int irc = read(fd, &byte, 1);
443
    if (irc == 0) {
444
      if (state == s_chr0) {
445
        ok = true;
446
      } else {
447
        emsg.Init("Rw11Cpu::LoadAbs()", "unexpected EOF");
448
      }
449
      break;
450
    } else if (irc < 0) {
451
      emsg.InitErrno("Rw11Cpu::LoadAbs()", "read() failed: ", errno);
452
      break;
453
    }
454
 
455
    chrnum += 1;
456
    chksum += byte;
457
 
458
    //cout << "+++1 " << blknum << "," << chrnum << " s=" << state << " : " 
459
    //     << RosPrintBvi(byte,8) << endl;
460
 
461
    switch (state) {
462
    case s_chr0:
463
      if (byte == 0) {
464
        chrnum = -1;
465
        state = s_chr0;
466
      } else if (byte == 1) {
467
        state = s_chr1;
468
      } else {
469
        emsg.InitPrintf("Rw11Cpu::LoadAbs()",
470
                        "unexpected start-of-block %3.3o", byte);
471
        go = false;
472
      }
473
      break;
474
 
475
    case s_chr1:
476
      if (byte == 0) {
477
        state = s_cntlow;
478
      } else {
479
        emsg.InitPrintf("Rw11Cpu::LoadAbs()",
480
                        "unexpected 2nd char %3.3o", byte);
481
        go = false;
482
      }
483
      break;
484
 
485
    case s_cntlow:
486
      bytcnt = byte;
487
      state  = s_cnthgh;
488
      break;
489
 
490
    case s_cnthgh:
491
      bytcnt |= uint16_t(byte) << 8;
492
      state  = s_adrlow;
493
      break;
494
 
495
    case s_adrlow:
496
      ldaddr = byte;
497
      state = s_adrhgh;
498
      break;
499
 
500
    case s_adrhgh:
501
      ldaddr |= uint16_t(byte) << 8;
502
      addr = ldaddr;
503
      word = 0;
504
      if ((addr & 0x01) == 1 && bytcnt > 6) {
505
        obmap_cit_t it = oddbyte.find(addr);
506
        if (it != oddbyte.end()) {
507
          word = it->second;
508
        } else {
509
          if (trace) {
510
            RlogMsg lmsg(LogFile());
511
            lmsg << "LoadAbs-W: no low byte data for " << RosPrintBvi(addr,8);
512
          }
513
        }
514
      }
515
 
516
      if (trace) {
517
        RlogMsg lmsg(Connect().LogFile());
518
        lmsg << "LoadAbs-I: block " << RosPrintf(blknum,"d",3)
519
             << ", length " << RosPrintf(bytcnt-6,"d",5)
520
             << " byte, address " << RosPrintBvi(ldaddr,8)
521
             << ":" << RosPrintBvi(uint16_t(ldaddr+(bytcnt-6)-1),8);
522
      }
523
      state = (bytcnt == 6) ? s_chksum : s_data;
524
      break;
525
 
526
    case s_data:
527
      if ((addr & 0x01) == 0) {             // even (low) byte
528
        word = byte;
529
      } else {                              // odd (high) byte
530
        word |= uint16_t(byte) << 8;
531
        data.push_back(word);
532
      }
533
      addr += 1;
534
      if (chrnum == bytcnt-1) state = s_chksum;
535
      break;
536
 
537
    case s_chksum:
538
      if (chksum != 0) {
539
        emsg.InitPrintf("Rw11Cpu::LoadAbs()", "check sum error %3.3o", chksum);
540
        go = false;
541
      } else if (bytcnt == 6) {
542
        if (trace) {
543
          RlogMsg lmsg(Connect().LogFile());
544
          lmsg << "LoadAbs-I: start address " << RosPrintBvi(ldaddr,8);
545
        }
546
        go = false;
547
        ok = true;
548
      } else {
549
        if ((addr & 0x01) == 1) {           // high byte not yet seen
550
          data.push_back(word);             // zero fill high byte
551
          oddbyte.insert(obmap_val_t(addr,word)); // store even byte for later
552
        }
553
 
554
        //cout << "+++2 " << RosPrintBvi(ldaddr,8) 
555
        //     << " " << data.size() << endl;
556
 
557
        if (!MemWrite(ldaddr, data, emsg)) {
558
          go = false;
559
        }
560
        data.clear();
561
      }
562
      chrnum = -1;
563
      blknum += 1;
564
      state = s_chr0;
565
      break;
566
 
567
    } // switch(state)
568
  } // while(go)
569
 
570
  close(fd);
571
 
572
  return ok;
573
}
574
 
575
//------------------------------------------+-----------------------------------
576
//! FIXME_docs
577
 
578
bool Rw11Cpu::Boot(const std::string& uname, RerrMsg& emsg)
579
{
580
  string cname;
581
  size_t uind=0;
582
  for (size_t i=0; i<uname.length(); i++) {
583
    char c = uname[i];
584
    if (c >= '0' && c <= '9') {
585
      string unum = cname.substr(i);
586 22 wfjm
      uind = ::atoi(unum.c_str());
587 19 wfjm
      break;
588
    } else {
589
      cname.push_back(c);
590
    }
591
  }
592
 
593
  if (!TestCntl(cname)) {
594 21 wfjm
    emsg.Init("Rw11Cpu::Boot", string("controller '") + cname + "' not known");
595 19 wfjm
    return false;
596
  }
597
 
598
  // FIXME_code: unit number not checked. Cntl doesn't even know about ...
599
 
600
  Rw11Cntl& cntl = Cntl(cname);
601
 
602
  vector<uint16_t> code;
603
  uint16_t aload = 0;
604
  uint16_t astart = 0;
605
 
606
  if (!cntl.BootCode(uind, code, aload, astart) || code.size()==0) {
607
    emsg.Init("Rw11Cpu::Boot", string("boot not supported for controller '")
608 21 wfjm
              + cname + "'");
609 19 wfjm
    return false;
610
  }
611
 
612
  if (!MemWrite(aload, code, emsg)) return false;
613
 
614
  RlinkCommandList clist;
615
  clist.AddWreg(fBase+kCp_addr_pc, astart);
616
  clist.AddWreg(fBase+kCp_addr_cntl, kCp_func_start);
617
  SetCpuGoUp();
618
  if (!Server().Exec(clist, emsg)) return false;
619
 
620
  return true;
621
}
622
 
623
//------------------------------------------+-----------------------------------
624
//! FIXME_docs
625
 
626
void Rw11Cpu::SetCpuGoUp()
627
{
628
  boost::lock_guard<boost::mutex> lock(fCpuGoMutex);
629
  fCpuGo   = true;
630
  fCpuStat = 0;
631
  fCpuGoCond.notify_all();
632
  return;
633
}
634
 
635
//------------------------------------------+-----------------------------------
636
//! FIXME_docs
637
 
638
void Rw11Cpu::SetCpuGoDown(uint16_t stat)
639
{
640
  if ((stat & kCp_stat_m_cpugo) == 0) {
641
    boost::lock_guard<boost::mutex> lock(fCpuGoMutex);
642
    fCpuGo   = false;
643
    fCpuStat = stat;
644
    fCpuGoCond.notify_all();
645
  }
646
  return;
647
}
648
 
649
//------------------------------------------+-----------------------------------
650
//! FIXME_docs
651
 
652
double Rw11Cpu::WaitCpuGoDown(double tout)
653
{
654
  boost::system_time t0(boost::get_system_time());
655
  boost::system_time timeout(boost::posix_time::max_date_time);
656
  if (tout > 0.)
657
    timeout = t0 + boost::posix_time::microseconds((long)1E6 * tout);
658
  boost::unique_lock<boost::mutex> lock(fCpuGoMutex);
659
  while (fCpuGo) {
660
    if (!fCpuGoCond.timed_wait(lock, timeout)) return -1.;
661
  }
662
  boost::posix_time::time_duration dt = boost::get_system_time() - t0;
663
  return double(dt.ticks()) / dt.ticks_per_second();
664
}
665
 
666
//------------------------------------------+-----------------------------------
667
//! FIXME_docs
668
 
669
void Rw11Cpu::W11AttnHandler()
670
{
671
  RlinkCommandList clist;
672
  clist.AddRreg(fBase+kCp_addr_stat);
673
  if (Server().Exec(clist))
674
    SetCpuGoDown(clist[0].Data());
675
  return;
676
}
677
 
678
//------------------------------------------+-----------------------------------
679
//! FIXME_docs
680
 
681
void Rw11Cpu::Dump(std::ostream& os, int ind, const char* text) const
682
{
683
  RosFill bl(ind);
684
  os << bl << (text?text:"--") << "Rw11Cpu @ " << this << endl;
685
 
686
  os << bl << "  fpW11:           " << fpW11 << endl;
687
  os << bl << "  fType:           " << fType << endl;
688
  os << bl << "  fIndex:          " << fIndex << endl;
689
  os << bl << "  fBase:           " << RosPrintf(fBase,"$x0",4) << endl;
690
  os << bl << "  fCpuGo:          " << fCpuGo << endl;
691
  os << bl << "  fCpuStat:        " << RosPrintf(fCpuStat,"$x0",4) << endl;
692
  os << bl << "  fCntlMap:        " << endl;
693
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
694
    os << bl << "    " << RosPrintf((it->first).c_str(), "-s",8)
695
       << " : " << it->second << endl;
696
  }
697
  fStats.Dump(os, ind+2, "fStats: ");
698
  return;
699
}
700
 
701
} // end namespace Retro

powered by: WebSVN 2.1.0

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