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

Subversion Repositories w11

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 34 wfjm
// $Id: Rw11Cpu.cpp 719 2015-12-27 09:45:43Z mueller $
2 19 wfjm
//
3 30 wfjm
// Copyright 2013-2015 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 34 wfjm
// 2015-12-26   719   1.2.5  BUGFIX: IM* correct register offset definitions
17
// 2015-07-12   700   1.2.5  use ..CpuAct instead ..CpuGo (new active based lam);
18
//                           add probe and map setup for optional cpu components
19 31 wfjm
// 2015-05-15   682   1.2.4  BUGFIX: Boot(): extract unit number properly
20
//                           Boot(): stop cpu before load, check unit number
21 30 wfjm
// 2015-05-08   675   1.2.3  w11a start/stop/suspend overhaul
22
// 2015-04-25   668   1.2.2  add AddRbibr(), AddWbibr()
23
// 2015-04-03   661   1.2.1  add kStat_M_* defs
24
// 2015-03-21   659   1.2    add RAddrMap
25 28 wfjm
// 2015-01-01   626   1.1    Adopt for rlink v4 and 4k ibus window
26
// 2014-12-21   617   1.0.3  use kStat_M_RbTout for rbus timeout
27 25 wfjm
// 2014-08-02   576   1.0.2  adopt rename of LastExpect->SetLastExpect
28 20 wfjm
// 2013-04-14   506   1.0.1  add AddLalh(),AddRMem(),AddWMem()
29 19 wfjm
// 2013-04-12   504   1.0    Initial version
30
// 2013-01-27   478   0.1    First draft
31
// ---------------------------------------------------------------------------
32
 
33
/*!
34
  \file
35 34 wfjm
  \version $Id: Rw11Cpu.cpp 719 2015-12-27 09:45:43Z mueller $
36 19 wfjm
  \brief   Implemenation of Rw11Cpu.
37
*/
38
#include <stdlib.h>
39
#include <fcntl.h>
40
#include <errno.h>
41
 
42
#include <vector>
43
#include <map>
44
#include <algorithm>
45
 
46
#include "boost/date_time/posix_time/posix_time_types.hpp"
47
 
48
#include "librtools/Rexception.hpp"
49
#include "librtools/RlogMsg.hpp"
50
#include "librtools/RosFill.hpp"
51
#include "librtools/RosPrintf.hpp"
52
#include "librtools/RosPrintBvi.hpp"
53
#include "Rw11Cntl.hpp"
54
 
55
#include "Rw11Cpu.hpp"
56
 
57
using namespace std;
58
 
59
/*!
60
  \class Retro::Rw11Cpu
61
  \brief FIXME_docs
62
*/
63
 
64
// all method definitions in namespace Retro
65
namespace Retro {
66
 
67
//------------------------------------------+-----------------------------------
68
// constants definitions
69
 
70 30 wfjm
const uint16_t  Rw11Cpu::kCPCONF;
71
const uint16_t  Rw11Cpu::kCPCNTL;
72
const uint16_t  Rw11Cpu::kCPSTAT;
73
const uint16_t  Rw11Cpu::kCPPSW;
74
const uint16_t  Rw11Cpu::kCPAL;
75
const uint16_t  Rw11Cpu::kCPAH;
76
const uint16_t  Rw11Cpu::kCPMEM;
77
const uint16_t  Rw11Cpu::kCPMEMI;
78
const uint16_t  Rw11Cpu::kCPR0;
79
const uint16_t  Rw11Cpu::kCPPC;
80
const uint16_t  Rw11Cpu::kCPMEMBE;
81 19 wfjm
 
82 30 wfjm
const uint16_t  Rw11Cpu::kCPFUNC_NOOP;
83
const uint16_t  Rw11Cpu::kCPFUNC_START;
84
const uint16_t  Rw11Cpu::kCPFUNC_STOP;
85
const uint16_t  Rw11Cpu::kCPFUNC_STEP;
86
const uint16_t  Rw11Cpu::kCPFUNC_CRESET;
87
const uint16_t  Rw11Cpu::kCPFUNC_BRESET;
88
const uint16_t  Rw11Cpu::kCPFUNC_SUSPEND;
89
const uint16_t  Rw11Cpu::kCPFUNC_RESUME;
90 19 wfjm
 
91 30 wfjm
const uint16_t  Rw11Cpu::kCPSTAT_M_SuspExt;
92
const uint16_t  Rw11Cpu::kCPSTAT_M_SuspInt;
93
const uint16_t  Rw11Cpu::kCPSTAT_M_CpuRust;
94
const uint16_t  Rw11Cpu::kCPSTAT_V_CpuRust;
95
const uint16_t  Rw11Cpu::kCPSTAT_B_CpuRust;
96
const uint16_t  Rw11Cpu::kCPSTAT_M_CpuSusp;
97
const uint16_t  Rw11Cpu::kCPSTAT_M_CpuGo;
98
const uint16_t  Rw11Cpu::kCPSTAT_M_CmdMErr;
99
const uint16_t  Rw11Cpu::kCPSTAT_M_CmdErr;
100 19 wfjm
 
101 30 wfjm
const uint16_t  Rw11Cpu::kCPURUST_INIT;
102
const uint16_t  Rw11Cpu::kCPURUST_HALT;
103
const uint16_t  Rw11Cpu::kCPURUST_RESET;
104
const uint16_t  Rw11Cpu::kCPURUST_STOP;
105
const uint16_t  Rw11Cpu::kCPURUST_STEP;
106
const uint16_t  Rw11Cpu::kCPURUST_SUSP;
107 34 wfjm
const uint16_t  Rw11Cpu::kCPURUST_HBPT;
108 30 wfjm
const uint16_t  Rw11Cpu::kCPURUST_RUNS;
109
const uint16_t  Rw11Cpu::kCPURUST_VECFET;
110
const uint16_t  Rw11Cpu::kCPURUST_RECRSV;
111
const uint16_t  Rw11Cpu::kCPURUST_SFAIL;
112
const uint16_t  Rw11Cpu::kCPURUST_VFAIL;
113 19 wfjm
 
114 30 wfjm
const uint16_t  Rw11Cpu::kCPAH_M_ADDR;
115
const uint16_t  Rw11Cpu::kCPAH_M_22BIT;
116
const uint16_t  Rw11Cpu::kCPAH_M_UBMAP;
117 20 wfjm
 
118 30 wfjm
const uint16_t  Rw11Cpu::kCPMEMBE_M_STICK;
119
const uint16_t  Rw11Cpu::kCPMEMBE_M_BE;
120 28 wfjm
 
121 30 wfjm
const uint8_t   Rw11Cpu::kStat_M_CmdErr;
122
const uint8_t   Rw11Cpu::kStat_M_CmdMErr;
123 34 wfjm
const uint8_t   Rw11Cpu::kStat_M_CpuSusp;
124 30 wfjm
const uint8_t   Rw11Cpu::kStat_M_CpuGo;
125
 
126 34 wfjm
const uint16_t  Rw11Cpu::kSCBASE;
127
const uint16_t  Rw11Cpu::kSCCNTL;
128
const uint16_t  Rw11Cpu::kSCADDR;
129
const uint16_t  Rw11Cpu::kSCDATA;
130
 
131
const uint16_t  Rw11Cpu::kCMBASE;
132
const uint16_t  Rw11Cpu::kCMCNTL;
133
const uint16_t  Rw11Cpu::kCMSTAT;
134
const uint16_t  Rw11Cpu::kCMADDR;
135
const uint16_t  Rw11Cpu::kCMDATA;
136
const uint16_t  Rw11Cpu::kCMIADDR;
137
const uint16_t  Rw11Cpu::kCMIPC;
138
const uint16_t  Rw11Cpu::kCMIREG;
139
const uint16_t  Rw11Cpu::kCMIMAL;
140
 
141
const uint16_t  Rw11Cpu::kHBBASE;
142
const uint16_t  Rw11Cpu::kHBSIZE;
143
const uint16_t  Rw11Cpu::kHBNMAX;
144
const uint16_t  Rw11Cpu::kHBCNTL;
145
const uint16_t  Rw11Cpu::kHBSTAT;
146
const uint16_t  Rw11Cpu::kHBHILIM;
147
const uint16_t  Rw11Cpu::kHBLOLIM;
148
 
149
const uint16_t  Rw11Cpu::kIMBASE;
150
const uint16_t  Rw11Cpu::kIMCNTL;
151
const uint16_t  Rw11Cpu::kIMSTAT;
152
const uint16_t  Rw11Cpu::kIMHILIM;
153
const uint16_t  Rw11Cpu::kIMLOLIM;
154
const uint16_t  Rw11Cpu::kIMADDR;
155
const uint16_t  Rw11Cpu::kIMDATA;
156
 
157 19 wfjm
//------------------------------------------+-----------------------------------
158
//! Constructor
159
 
160
Rw11Cpu::Rw11Cpu(const std::string& type)
161 29 wfjm
  : fpW11(nullptr),
162 19 wfjm
    fType(type),
163
    fIndex(0),
164
    fBase(0),
165 28 wfjm
    fIBase(0x4000),
166 34 wfjm
    fHasScnt(false),
167
    fHasCmon(false),
168
    fHasHbpt(0),
169
    fHasIbmon(false),
170
    fCpuAct(0),
171 19 wfjm
    fCpuStat(0),
172 34 wfjm
    fCpuActMutex(),
173
    fCpuActCond(),
174 19 wfjm
    fCntlMap(),
175 28 wfjm
    fIAddrMap(),
176 30 wfjm
    fRAddrMap(),
177 19 wfjm
    fStats()
178
{}
179
 
180
//------------------------------------------+-----------------------------------
181
//! Destructor
182
 
183
Rw11Cpu::~Rw11Cpu()
184
{}
185
 
186
//------------------------------------------+-----------------------------------
187
//! FIXME_docs
188
 
189
void Rw11Cpu::Setup(Rw11* pw11)
190
{
191
  fpW11 = pw11;
192 34 wfjm
  SetupStd();
193
  SetupOpt();
194 19 wfjm
  return;
195
}
196
 
197
//------------------------------------------+-----------------------------------
198
//! FIXME_docs
199
 
200
void Rw11Cpu::AddCntl(const boost::shared_ptr<Rw11Cntl>& spcntl)
201
{
202
  if (!spcntl)
203
    throw Rexception("Rw11Cpu::AddCntl","Bad args: spcntl == 0");
204
 
205
  string name(spcntl->Name());
206
  if (fCntlMap.find(name) != fCntlMap.end())
207
    throw Rexception("Rw11Cpu::AddCntl",
208
                     "Bad state: duplicate controller name");;
209
 
210
  fCntlMap.insert(cmap_val_t(name, spcntl));
211
  spcntl->SetCpu(this);
212
  return;
213
}
214
 
215
//------------------------------------------+-----------------------------------
216
//! FIXME_docs
217
 
218
bool Rw11Cpu::TestCntl(const std::string& name) const
219
{
220
  return fCntlMap.find(name) != fCntlMap.end();
221
}
222
 
223
//------------------------------------------+-----------------------------------
224
//! FIXME_docs
225
 
226
void Rw11Cpu::ListCntl(std::vector<std::string>& list) const
227
{
228
  list.clear();
229
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
230
    list.push_back((it->second)->Name());
231
  }
232
  return;
233
}
234
 
235
//------------------------------------------+-----------------------------------
236
//! FIXME_docs
237
 
238
Rw11Cntl& Rw11Cpu::Cntl(const std::string& name) const
239
{
240
  cmap_cit_t it=fCntlMap.find(name);
241
  if (it == fCntlMap.end())
242
    throw Rexception("Rw11Cpu::Cntl()",
243
                     "Bad args: controller name '" + name + "' unknown");
244
  return *(it->second);
245
}
246
 
247
//------------------------------------------+-----------------------------------
248
//! FIXME_docs
249
 
250
void Rw11Cpu::Start()
251
{
252
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
253
    Rw11Cntl& cntl(*(it->second));
254
    cntl.Probe();
255
    if (cntl.ProbeStatus().Found() && cntl.Enable()) {
256
      cntl.Start();
257
    }
258
  }
259
  return;
260
}
261
 
262
//------------------------------------------+-----------------------------------
263
//! FIXME_docs
264
 
265
std::string Rw11Cpu::NextCntlName(const std::string& base) const
266
{
267
  for (char let='a'; let<='z'; let++) {
268
    string name = base + let;
269
    if (fCntlMap.find(name) == fCntlMap.end()) return name;
270
  }
271
  throw Rexception("Rw11Cpu::NextCntlName",
272
                   "Bad args: all controller letters used for '" + base + "'");
273
  return "";
274
}
275
 
276
//------------------------------------------+-----------------------------------
277
//! FIXME_docs
278
 
279 28 wfjm
int Rw11Cpu::AddMembe(RlinkCommandList& clist, uint16_t be, bool stick)
280 19 wfjm
{
281 30 wfjm
  uint16_t data = be & kCPMEMBE_M_BE;
282
  if (stick) data |= kCPMEMBE_M_STICK;
283
  return clist.AddWreg(fBase+kCPMEMBE, data);
284 19 wfjm
}
285
 
286
//------------------------------------------+-----------------------------------
287
//! FIXME_docs
288
 
289
int Rw11Cpu::AddRibr(RlinkCommandList& clist, uint16_t ibaddr)
290
{
291 28 wfjm
  if ((ibaddr & 0160001) != 0160000)
292
    throw Rexception("Rw11Cpu::AddRibr", "ibaddr out of IO page or odd");
293
 
294
  return clist.AddRreg(IbusRemoteAddr(ibaddr));
295 19 wfjm
}
296
 
297
//------------------------------------------+-----------------------------------
298
//! FIXME_docs
299
 
300
int Rw11Cpu::AddWibr(RlinkCommandList& clist, uint16_t ibaddr, uint16_t data)
301
{
302 28 wfjm
  if ((ibaddr & 0160001) != 0160000)
303
    throw Rexception("Rw11Cpu::AddWibr", "ibaddr out of IO page or odd");
304
 
305
  return clist.AddWreg(IbusRemoteAddr(ibaddr), data);
306 19 wfjm
}
307
 
308
//------------------------------------------+-----------------------------------
309
//! FIXME_docs
310 30 wfjm
int Rw11Cpu::AddRbibr(RlinkCommandList& clist, uint16_t ibaddr, size_t size)
311
{
312
  if ((ibaddr & 0160001) != 0160000)
313
    throw Rexception("Rw11Cpu::AddRbibr", "ibaddr out of IO page or odd");
314
 
315
  return clist.AddRblk(IbusRemoteAddr(ibaddr), size);
316
}
317
 
318
//------------------------------------------+-----------------------------------
319
//! FIXME_docs
320
int Rw11Cpu::AddWbibr(RlinkCommandList& clist, uint16_t ibaddr,
321
                      std::vector<uint16_t> block)
322
{
323
  if ((ibaddr & 0160001) != 0160000)
324
    throw Rexception("Rw11Cpu::AddWbibr", "ibaddr out of IO page or odd");
325
 
326
  return clist.AddWblk(IbusRemoteAddr(ibaddr), block);
327
}
328
 
329
//------------------------------------------+-----------------------------------
330
//! FIXME_docs
331 19 wfjm
 
332 20 wfjm
int Rw11Cpu::AddLalh(RlinkCommandList& clist, uint32_t addr, uint16_t mode)
333
{
334
  uint16_t al = uint16_t(addr);
335 30 wfjm
  uint16_t ah = uint16_t(addr>>16) & kCPAH_M_ADDR;
336
  ah |= mode & (kCPAH_M_22BIT|kCPAH_M_UBMAP);
337
  int ind = clist.AddWreg(fBase+kCPAL, al);
338
  clist.AddWreg(fBase+kCPAH, ah);
339 20 wfjm
  return ind;
340
}
341
 
342
//------------------------------------------+-----------------------------------
343
//! FIXME_docs
344
 
345 28 wfjm
int Rw11Cpu::AddRMem(RlinkCommandList& clist, uint32_t addr, uint16_t* buf,
346
                     size_t size, uint16_t mode, bool singleblk)
347 20 wfjm
{
348 28 wfjm
  size_t blkmax = Connect().BlockSizeMax();
349
  if (singleblk && size > blkmax)
350
    throw Rexception("Rw11Cpu::AddRMem",
351
                     "Bad args: singleblk==true && size > BlockSizeMax()");
352
 
353 20 wfjm
  int ind = AddLalh(clist, addr, mode);
354
  while (size > 0) {
355 28 wfjm
    size_t bsize = (size>blkmax) ? blkmax : size;
356 30 wfjm
    clist.AddRblk(fBase+kCPMEMI, buf, bsize);
357 20 wfjm
    buf  += bsize;
358
    size -= bsize;
359
  }
360
  return ind;
361
}
362
 
363
//------------------------------------------+-----------------------------------
364
//! FIXME_docs
365
 
366
int Rw11Cpu::AddWMem(RlinkCommandList& clist, uint32_t addr,
367 28 wfjm
                     const uint16_t* buf, size_t size,
368
                     uint16_t mode, bool singleblk)
369 20 wfjm
{
370 28 wfjm
  size_t blkmax = Connect().BlockSizeMax();
371
  if (singleblk && size > blkmax)
372
    throw Rexception("Rw11Cpu::AddWMem",
373
                     "Bad args: singleblk==true && size > BlockSizeMax()");
374
 
375 20 wfjm
  int ind = AddLalh(clist, addr, mode);
376
  while (size > 0) {
377 28 wfjm
    size_t bsize = (size>blkmax) ? blkmax : size;
378 30 wfjm
    clist.AddWblk(fBase+kCPMEMI, buf, bsize);
379 20 wfjm
    buf  += bsize;
380
    size -= bsize;
381
  }
382
  return ind;
383
}
384
 
385
//------------------------------------------+-----------------------------------
386
//! FIXME_docs
387
 
388 19 wfjm
bool Rw11Cpu::MemRead(uint16_t addr, std::vector<uint16_t>& data,
389
                      size_t nword, RerrMsg& emsg)
390
{
391 28 wfjm
  size_t blkmax = Connect().BlockSizePrudent();
392 19 wfjm
  data.resize(nword);
393
  size_t ndone = 0;
394
  while (nword>ndone) {
395 28 wfjm
    size_t nblk = min(blkmax, nword-ndone);
396 19 wfjm
    RlinkCommandList clist;
397 30 wfjm
    clist.AddWreg(fBase+kCPAL, addr+2*ndone);
398
    clist.AddRblk(fBase+kCPMEMI, data.data()+ndone, nblk);
399 19 wfjm
    if (!Server().Exec(clist, emsg)) return false;
400
    ndone += nblk;
401
  }
402
  return true;
403
}
404
 
405
//------------------------------------------+-----------------------------------
406
//! FIXME_docs
407
 
408
bool Rw11Cpu::MemWrite(uint16_t addr, const std::vector<uint16_t>& data,
409
                       RerrMsg& emsg)
410
{
411 28 wfjm
  size_t blkmax = Connect().BlockSizePrudent();
412 19 wfjm
  size_t nword = data.size();
413
  size_t ndone = 0;
414
  while (nword>ndone) {
415 28 wfjm
    size_t nblk = min(blkmax, nword-ndone);
416 19 wfjm
    RlinkCommandList clist;
417 30 wfjm
    clist.AddWreg(fBase+kCPAL, addr+2*ndone);
418
    clist.AddWblk(fBase+kCPMEMI, data.data()+ndone, nblk);
419 19 wfjm
    if (!Server().Exec(clist, emsg)) return false;
420
    ndone += nblk;
421
  }
422
  return true;
423
}
424
 
425
//------------------------------------------+-----------------------------------
426
//! FIXME_docs
427
 
428
bool Rw11Cpu::ProbeCntl(Rw11Probe& dsc)
429
{
430
  if (!(dsc.fProbeInt | dsc.fProbeRem) || dsc.fAddr == 0)
431
    throw Rexception("Rw11Cpu::Probe",
432
                     "Bad args: fAddr == 0 or fProbeInt|fProbeRem == false");
433
 
434
  if (!dsc.fProbeDone) {
435
    RlinkCommandList clist;
436
    int iib = -1;
437
    int irb = -1;
438
    if (dsc.fProbeInt) {
439 30 wfjm
      clist.AddWreg(fBase+kCPAL,  dsc.fAddr);
440
      iib = clist.AddRreg(fBase+kCPMEM);
441
      clist.SetLastExpectStatus(0,0);       // disable stat check
442 19 wfjm
    }
443
    if (dsc.fProbeRem) {
444
      irb = AddRibr(clist, dsc.fAddr);
445 30 wfjm
      clist.SetLastExpectStatus(0,0);       // disable stat check
446 19 wfjm
    }
447
 
448
    Server().Exec(clist);
449
 
450
    if (dsc.fProbeInt) {
451 28 wfjm
      dsc.fFoundInt = (clist[iib].Status() &
452
                         (RlinkCommand::kStat_M_RbTout |
453
                          RlinkCommand::kStat_M_RbNak  |
454
                          RlinkCommand::kStat_M_RbErr)) ==0;
455 19 wfjm
    }
456
    if (dsc.fProbeRem) {
457 28 wfjm
      dsc.fFoundRem = (clist[irb].Status() &
458
                         (RlinkCommand::kStat_M_RbTout |
459
                          RlinkCommand::kStat_M_RbNak  |
460
                          RlinkCommand::kStat_M_RbErr)) ==0;
461 19 wfjm
    }
462
    dsc.fProbeDone = true;
463
  }
464
 
465
  return dsc.Found();
466
}
467
 
468
//------------------------------------------+-----------------------------------
469
//! FIXME_docs
470
 
471
// absolute binary format described in notes_ptape.txt
472
 
473
bool Rw11Cpu::LoadAbs(const std::string& fname, RerrMsg& emsg, bool trace)
474
{
475
  int fd = open(fname.c_str(), O_RDONLY);
476
 
477
  if (fd < 0) {
478
    emsg.InitErrno("Rw11Cpu::LoadAbs()", string("open() for '") + fname +
479 21 wfjm
                   "' failed: ", errno);
480 19 wfjm
    return false;
481
  }
482
 
483
  enum states {
484
    s_chr0,
485
    s_chr1,
486
    s_cntlow,
487
    s_cnthgh,
488
    s_adrlow,
489
    s_adrhgh,
490
    s_data,
491
    s_chksum
492
  };
493
 
494
  typedef std::map<uint16_t, uint16_t> obmap_t;
495 27 wfjm
  //typedef obmap_t::iterator         obmap_it_t;
496 19 wfjm
  typedef obmap_t::const_iterator   obmap_cit_t;
497
  typedef obmap_t::value_type       obmap_val_t;
498
 
499
  obmap_t oddbyte;                          // odd byte cache
500
 
501
  vector<uint16_t> data;
502
  data.reserve(256);
503
 
504
  int chrnum = -1;                          // char number in block
505
  int blknum = 0;                           // block number
506
  int bytcnt = 0;                           // byte count
507
  uint16_t ldaddr = 0;                      // load address
508
  uint8_t chksum = 0;                       // check sum
509
  uint16_t addr = 0;                        // current address
510
  uint16_t word = 0;                        // current word
511
 
512
  bool ok = false;
513
  bool go = true;
514
  enum states state = s_chr0;
515
 
516
  while (go) {
517
    uint8_t byte;
518
    int irc = read(fd, &byte, 1);
519
    if (irc == 0) {
520
      if (state == s_chr0) {
521
        ok = true;
522
      } else {
523
        emsg.Init("Rw11Cpu::LoadAbs()", "unexpected EOF");
524
      }
525
      break;
526
    } else if (irc < 0) {
527
      emsg.InitErrno("Rw11Cpu::LoadAbs()", "read() failed: ", errno);
528
      break;
529
    }
530
 
531
    chrnum += 1;
532
    chksum += byte;
533
 
534
    //cout << "+++1 " << blknum << "," << chrnum << " s=" << state << " : " 
535
    //     << RosPrintBvi(byte,8) << endl;
536
 
537
    switch (state) {
538
    case s_chr0:
539
      if (byte == 0) {
540
        chrnum = -1;
541
        state = s_chr0;
542
      } else if (byte == 1) {
543
        state = s_chr1;
544
      } else {
545
        emsg.InitPrintf("Rw11Cpu::LoadAbs()",
546
                        "unexpected start-of-block %3.3o", byte);
547
        go = false;
548
      }
549
      break;
550
 
551
    case s_chr1:
552
      if (byte == 0) {
553
        state = s_cntlow;
554
      } else {
555
        emsg.InitPrintf("Rw11Cpu::LoadAbs()",
556
                        "unexpected 2nd char %3.3o", byte);
557
        go = false;
558
      }
559
      break;
560
 
561
    case s_cntlow:
562
      bytcnt = byte;
563
      state  = s_cnthgh;
564
      break;
565
 
566
    case s_cnthgh:
567
      bytcnt |= uint16_t(byte) << 8;
568
      state  = s_adrlow;
569
      break;
570
 
571
    case s_adrlow:
572
      ldaddr = byte;
573
      state = s_adrhgh;
574
      break;
575
 
576
    case s_adrhgh:
577
      ldaddr |= uint16_t(byte) << 8;
578
      addr = ldaddr;
579
      word = 0;
580
      if ((addr & 0x01) == 1 && bytcnt > 6) {
581
        obmap_cit_t it = oddbyte.find(addr);
582
        if (it != oddbyte.end()) {
583
          word = it->second;
584
        } else {
585
          if (trace) {
586
            RlogMsg lmsg(LogFile());
587
            lmsg << "LoadAbs-W: no low byte data for " << RosPrintBvi(addr,8);
588
          }
589
        }
590
      }
591
 
592
      if (trace) {
593
        RlogMsg lmsg(Connect().LogFile());
594
        lmsg << "LoadAbs-I: block " << RosPrintf(blknum,"d",3)
595
             << ", length " << RosPrintf(bytcnt-6,"d",5)
596
             << " byte, address " << RosPrintBvi(ldaddr,8)
597
             << ":" << RosPrintBvi(uint16_t(ldaddr+(bytcnt-6)-1),8);
598
      }
599
      state = (bytcnt == 6) ? s_chksum : s_data;
600
      break;
601
 
602
    case s_data:
603
      if ((addr & 0x01) == 0) {             // even (low) byte
604
        word = byte;
605
      } else {                              // odd (high) byte
606
        word |= uint16_t(byte) << 8;
607
        data.push_back(word);
608
      }
609
      addr += 1;
610
      if (chrnum == bytcnt-1) state = s_chksum;
611
      break;
612
 
613
    case s_chksum:
614
      if (chksum != 0) {
615
        emsg.InitPrintf("Rw11Cpu::LoadAbs()", "check sum error %3.3o", chksum);
616
        go = false;
617
      } else if (bytcnt == 6) {
618
        if (trace) {
619
          RlogMsg lmsg(Connect().LogFile());
620
          lmsg << "LoadAbs-I: start address " << RosPrintBvi(ldaddr,8);
621
        }
622
        go = false;
623
        ok = true;
624
      } else {
625
        if ((addr & 0x01) == 1) {           // high byte not yet seen
626
          data.push_back(word);             // zero fill high byte
627
          oddbyte.insert(obmap_val_t(addr,word)); // store even byte for later
628
        }
629
 
630
        //cout << "+++2 " << RosPrintBvi(ldaddr,8) 
631
        //     << " " << data.size() << endl;
632
 
633
        if (!MemWrite(ldaddr, data, emsg)) {
634
          go = false;
635
        }
636
        data.clear();
637
      }
638
      chrnum = -1;
639
      blknum += 1;
640
      state = s_chr0;
641
      break;
642
 
643
    } // switch(state)
644
  } // while(go)
645
 
646
  close(fd);
647
 
648
  return ok;
649
}
650
 
651
//------------------------------------------+-----------------------------------
652
//! FIXME_docs
653
 
654
bool Rw11Cpu::Boot(const std::string& uname, RerrMsg& emsg)
655
{
656
  string cname;
657
  size_t uind=0;
658
  for (size_t i=0; i<uname.length(); i++) {
659
    char c = uname[i];
660
    if (c >= '0' && c <= '9') {
661 31 wfjm
      string unum = uname.substr(i);
662 22 wfjm
      uind = ::atoi(unum.c_str());
663 19 wfjm
      break;
664
    } else {
665
      cname.push_back(c);
666
    }
667
  }
668
 
669
  if (!TestCntl(cname)) {
670 21 wfjm
    emsg.Init("Rw11Cpu::Boot", string("controller '") + cname + "' not known");
671 19 wfjm
    return false;
672
  }
673
 
674
  Rw11Cntl& cntl = Cntl(cname);
675 31 wfjm
  if (uind >= cntl.NUnit()) {
676
    emsg.Init("Rw11Cpu::Boot", string("unit number '") + uname + "' invalid");
677
    return false;
678
  }
679 19 wfjm
 
680
  vector<uint16_t> code;
681
  uint16_t aload = 0;
682
  uint16_t astart = 0;
683
 
684
  if (!cntl.BootCode(uind, code, aload, astart) || code.size()==0) {
685
    emsg.Init("Rw11Cpu::Boot", string("boot not supported for controller '")
686 21 wfjm
              + cname + "'");
687 19 wfjm
    return false;
688
  }
689
 
690 31 wfjm
  // stop and reset cpu, just in case
691
  RlinkCommandList clist;
692
  clist.AddWreg(fBase+kCPCNTL, kCPFUNC_STOP);   // stop cpu
693
  clist.AddWreg(fBase+kCPCNTL, kCPFUNC_CRESET); // init cpu and bus
694
  if (!Server().Exec(clist, emsg)) return false;
695
 
696
  // load boot code
697 19 wfjm
  if (!MemWrite(aload, code, emsg)) return false;
698
 
699 31 wfjm
  // and start cpu at boot loader start address
700
  clist.Clear();
701 30 wfjm
  clist.AddWreg(fBase+kCPPC, astart);           // load PC
702
  clist.AddWreg(fBase+kCPCNTL, kCPFUNC_START);  // and start
703 34 wfjm
  SetCpuActUp();
704 19 wfjm
  if (!Server().Exec(clist, emsg)) return false;
705
 
706
  return true;
707
}
708
 
709
//------------------------------------------+-----------------------------------
710
//! FIXME_docs
711
 
712 34 wfjm
void Rw11Cpu::SetCpuActUp()
713 19 wfjm
{
714 34 wfjm
  boost::lock_guard<boost::mutex> lock(fCpuActMutex);
715
  fCpuAct  = true;
716 19 wfjm
  fCpuStat = 0;
717 34 wfjm
  fCpuActCond.notify_all();
718 19 wfjm
  return;
719
}
720
 
721
//------------------------------------------+-----------------------------------
722
//! FIXME_docs
723
 
724 34 wfjm
void Rw11Cpu::SetCpuActDown(uint16_t stat)
725 19 wfjm
{
726 34 wfjm
  if ((stat & kCPSTAT_M_CpuGo) == 0 || (stat & kCPSTAT_M_CpuSusp) != 0 ) {
727
    boost::lock_guard<boost::mutex> lock(fCpuActMutex);
728
    fCpuAct  = false;
729 19 wfjm
    fCpuStat = stat;
730 34 wfjm
    fCpuActCond.notify_all();
731 19 wfjm
  }
732
  return;
733
}
734
 
735
//------------------------------------------+-----------------------------------
736
//! FIXME_docs
737
 
738 34 wfjm
double Rw11Cpu::WaitCpuActDown(double tout)
739 19 wfjm
{
740
  boost::system_time t0(boost::get_system_time());
741
  boost::system_time timeout(boost::posix_time::max_date_time);
742
  if (tout > 0.)
743
    timeout = t0 + boost::posix_time::microseconds((long)1E6 * tout);
744 34 wfjm
  boost::unique_lock<boost::mutex> lock(fCpuActMutex);
745
  while (fCpuAct) {
746
    if (!fCpuActCond.timed_wait(lock, timeout)) return -1.;
747 19 wfjm
  }
748
  boost::posix_time::time_duration dt = boost::get_system_time() - t0;
749
  return double(dt.ticks()) / dt.ticks_per_second();
750
}
751
 
752
//------------------------------------------+-----------------------------------
753
//! FIXME_docs
754
 
755 30 wfjm
void Rw11Cpu::AllIAddrMapInsert(const std::string& name, uint16_t ibaddr)
756 28 wfjm
{
757
  IAddrMapInsert(name, ibaddr);
758 30 wfjm
  uint16_t rbaddr = IbusRemoteAddr(ibaddr);
759
  RAddrMapInsert(name, rbaddr);
760
 
761
  // add ix. to name in common Connect AddrMap to keep name unique
762
  string cname = "i";
763
  cname += '0'+Index();
764
  cname += '.';
765
  cname += name;
766
  Connect().AddrMapInsert(cname, rbaddr);
767
 
768 28 wfjm
  return;
769
}
770
 
771
//------------------------------------------+-----------------------------------
772
//! FIXME_docs
773
 
774 30 wfjm
void Rw11Cpu::AllRAddrMapInsert(const std::string& name, uint16_t rbaddr)
775
{
776
  RAddrMapInsert(name, rbaddr);
777
 
778
  // add cx. to name in common Connect AddrMap to keep name unique
779
  string cname = "c";
780
  cname += '0'+Index();
781
  cname += '.';
782
  cname += name;
783
  Connect().AddrMapInsert(cname, rbaddr);
784
 
785
  return;
786
}
787
 
788
//------------------------------------------+-----------------------------------
789
//! FIXME_docs
790
 
791 19 wfjm
void Rw11Cpu::W11AttnHandler()
792
{
793
  RlinkCommandList clist;
794 30 wfjm
  clist.AddRreg(fBase+kCPSTAT);
795 29 wfjm
  Server().Exec(clist);
796 34 wfjm
  SetCpuActDown(clist[0].Data());
797 19 wfjm
  return;
798
}
799
 
800
//------------------------------------------+-----------------------------------
801
//! FIXME_docs
802
 
803
void Rw11Cpu::Dump(std::ostream& os, int ind, const char* text) const
804
{
805
  RosFill bl(ind);
806
  os << bl << (text?text:"--") << "Rw11Cpu @ " << this << endl;
807
 
808
  os << bl << "  fpW11:           " << fpW11 << endl;
809
  os << bl << "  fType:           " << fType << endl;
810
  os << bl << "  fIndex:          " << fIndex << endl;
811
  os << bl << "  fBase:           " << RosPrintf(fBase,"$x0",4) << endl;
812 28 wfjm
  os << bl << "  fIBase:          " << RosPrintf(fIBase,"$x0",4) << endl;
813 34 wfjm
  os << bl << "  fHasScnt:        " << fHasScnt << endl;
814
  os << bl << "  fHasCmon:        " << fHasCmon << endl;
815
  os << bl << "  fHasHbpt:        " << fHasHbpt << endl;
816
  os << bl << "  fHasIbmon:       " << fHasIbmon << endl;
817
  os << bl << "  fCpuAct:         " << fCpuAct << endl;
818 19 wfjm
  os << bl << "  fCpuStat:        " << RosPrintf(fCpuStat,"$x0",4) << endl;
819
  os << bl << "  fCntlMap:        " << endl;
820
  for (cmap_cit_t it=fCntlMap.begin(); it!=fCntlMap.end(); it++) {
821
    os << bl << "    " << RosPrintf((it->first).c_str(), "-s",8)
822
       << " : " << it->second << endl;
823
  }
824 28 wfjm
  fIAddrMap.Dump(os, ind+2, "fIAddrMap: ");
825 30 wfjm
  fRAddrMap.Dump(os, ind+2, "fRAddrMap: ");
826 19 wfjm
  fStats.Dump(os, ind+2, "fStats: ");
827
  return;
828
}
829
 
830 34 wfjm
//------------------------------------------+-----------------------------------
831
//! FIXME_docs
832
 
833
void Rw11Cpu::SetupStd()
834
{
835
  // add control port address rbus mappings
836
  AllRAddrMapInsert("conf" , Base()+kCPCONF);
837
  AllRAddrMapInsert("cntl" , Base()+kCPCNTL);
838
  AllRAddrMapInsert("stat" , Base()+kCPSTAT);
839
  AllRAddrMapInsert("psw"  , Base()+kCPPSW);
840
  AllRAddrMapInsert("al"   , Base()+kCPAL);
841
  AllRAddrMapInsert("ah"   , Base()+kCPAH);
842
  AllRAddrMapInsert("mem"  , Base()+kCPMEM);
843
  AllRAddrMapInsert("memi" , Base()+kCPMEMI);
844
  AllRAddrMapInsert("r0"   , Base()+kCPR0);
845
  AllRAddrMapInsert("r1"   , Base()+kCPR0+1);
846
  AllRAddrMapInsert("r2"   , Base()+kCPR0+2);
847
  AllRAddrMapInsert("r3"   , Base()+kCPR0+3);
848
  AllRAddrMapInsert("r4"   , Base()+kCPR0+4);
849
  AllRAddrMapInsert("r5"   , Base()+kCPR0+5);
850
  AllRAddrMapInsert("sp"   , Base()+kCPR0+6);
851
  AllRAddrMapInsert("pc"   , Base()+kCPR0+7);
852
  AllRAddrMapInsert("membe", Base()+kCPMEMBE);
853
 
854
  // add cpu register address ibus and rbus mappings
855
  AllIAddrMapInsert("psw"    , 0177776);
856
  AllIAddrMapInsert("stklim" , 0177774);
857
  AllIAddrMapInsert("pirq"   , 0177772);
858
  AllIAddrMapInsert("mbrk"   , 0177770);
859
  AllIAddrMapInsert("cpuerr" , 0177766);
860
  AllIAddrMapInsert("sysid"  , 0177764);
861
  AllIAddrMapInsert("hisize" , 0177762);
862
  AllIAddrMapInsert("losize" , 0177760);
863
 
864
  AllIAddrMapInsert("hm"     , 0177752);
865
  AllIAddrMapInsert("maint"  , 0177750);
866
  AllIAddrMapInsert("cntrl"  , 0177746);
867
  AllIAddrMapInsert("syserr" , 0177744);
868
  AllIAddrMapInsert("hiaddr" , 0177742);
869
  AllIAddrMapInsert("loaddr" , 0177740);
870
 
871
  AllIAddrMapInsert("ssr2"   , 0177576);
872
  AllIAddrMapInsert("ssr1"   , 0177574);
873
  AllIAddrMapInsert("ssr0"   , 0177572);
874
 
875
  AllIAddrMapInsert("sdreg"  , 0177570);
876
 
877
  AllIAddrMapInsert("ssr3"   , 0172516);
878
 
879
  // add mmu segment register files
880
  string sdr = "sdr";
881
  string sar = "sar";
882
  for (char i=0; i<8; i++) {
883
    char ichar = '0'+i;
884
    AllIAddrMapInsert(sdr+"ki."+ichar, 0172300+2*i);
885
    AllIAddrMapInsert(sdr+"kd."+ichar, 0172320+2*i);
886
    AllIAddrMapInsert(sar+"ki."+ichar, 0172340+2*i);
887
    AllIAddrMapInsert(sar+"kd."+ichar, 0172360+2*i);
888
    AllIAddrMapInsert(sdr+"si."+ichar, 0172200+2*i);
889
    AllIAddrMapInsert(sdr+"sd."+ichar, 0172220+2*i);
890
    AllIAddrMapInsert(sar+"si."+ichar, 0172240+2*i);
891
    AllIAddrMapInsert(sar+"sd."+ichar, 0172260+2*i);
892
    AllIAddrMapInsert(sdr+"ui."+ichar, 0177600+2*i);
893
    AllIAddrMapInsert(sdr+"ud."+ichar, 0177620+2*i);
894
    AllIAddrMapInsert(sar+"ui."+ichar, 0177640+2*i);
895
    AllIAddrMapInsert(sar+"ud."+ichar, 0177660+2*i);
896
  }
897
 
898
  return;
899
}
900
 
901
//------------------------------------------+-----------------------------------
902
//! FIXME_docs
903
 
904
void Rw11Cpu::SetupOpt()
905
{
906
  // probe optional components: dmscnt, dmcmon, dmhbpt and ibmon
907
  RlinkCommandList clist;
908
 
909
  int isc =  clist.AddRreg(Base()+kSCBASE+kSCCNTL);
910
  clist.SetLastExpectStatus(0,0);        // disable stat check
911
 
912
  int icm =  clist.AddRreg(Base()+kCMBASE+kCMCNTL);
913
  clist.SetLastExpectStatus(0,0);
914
 
915
  int ihb[kHBNMAX];
916
  for (int i=0; i<kHBNMAX; i++) {
917
    ihb[i] =  clist.AddRreg(Base()+kHBBASE+i*kHBSIZE+kHBCNTL);
918
    clist.SetLastExpectStatus(0,0);
919
  }
920
  int iim = AddRibr(clist, kIMBASE+kIMCNTL);
921
  clist.SetLastExpectStatus(0,0);
922
 
923
  Connect().Exec(clist);
924
 
925
  uint8_t statmsk = RlinkCommand::kStat_M_RbTout |
926
                    RlinkCommand::kStat_M_RbNak  |
927
                    RlinkCommand::kStat_M_RbErr;
928
 
929
  fHasScnt = (clist[isc].Status() & statmsk) == 0;
930
  if (fHasScnt) {
931
    uint16_t base = Base() + kSCBASE;
932
    AllRAddrMapInsert("sc.cntl" , base + kSCCNTL);
933
    AllRAddrMapInsert("sc.addr" , base + kSCADDR);
934
    AllRAddrMapInsert("sc.data" , base + kSCDATA);
935
  }
936
 
937
  fHasCmon = (clist[icm].Status() & statmsk) == 0;
938
  if (fHasCmon) {
939
    uint16_t base = Base() + kCMBASE;
940
    AllRAddrMapInsert("cm.cntl"  , base + kCMCNTL);
941
    AllRAddrMapInsert("cm.stat"  , base + kCMSTAT);
942
    AllRAddrMapInsert("cm.addr"  , base + kCMADDR);
943
    AllRAddrMapInsert("cm.data"  , base + kCMDATA);
944
    AllRAddrMapInsert("cm.iaddr" , base + kCMIADDR);
945
    AllRAddrMapInsert("cm.ipc"   , base + kCMIPC);
946
    AllRAddrMapInsert("cm.ireg"  , base + kCMIREG);
947
    AllRAddrMapInsert("cm.imal"  , base + kCMIMAL);
948
  }
949
 
950
  fHasHbpt = 0;
951
  for (int i=0; i<kHBNMAX; i++) {
952
    if ((clist[ihb[i]].Status() & statmsk) != 0) break;
953
    fHasHbpt += 1;
954
    uint16_t base = Base() + kHBBASE + i*kHBSIZE;
955
    std::string pref = "hb";
956
    pref += '0'+i;
957
    AllRAddrMapInsert(pref+".cntl"  , base + kHBCNTL);
958
    AllRAddrMapInsert(pref+".stat"  , base + kHBSTAT);
959
    AllRAddrMapInsert(pref+".hilim" , base + kHBHILIM);
960
    AllRAddrMapInsert(pref+".lolim" , base + kHBLOLIM);
961
  }
962
 
963
  fHasIbmon = (clist[iim].Status() & statmsk) == 0;
964
  if (fHasIbmon) {
965
    AllIAddrMapInsert("im.cntl",  kIMBASE + kIMCNTL);
966
    AllIAddrMapInsert("im.stat",  kIMBASE + kIMSTAT);
967
    AllIAddrMapInsert("im.hilim", kIMBASE + kIMHILIM);
968
    AllIAddrMapInsert("im.lolim", kIMBASE + kIMLOLIM);
969
    AllIAddrMapInsert("im.addr",  kIMBASE + kIMADDR);
970
    AllIAddrMapInsert("im.data",  kIMBASE + kIMDATA);
971
  }
972
 
973
  return;
974
}
975
 
976
 
977 19 wfjm
} // end namespace Retro

powered by: WebSVN 2.1.0

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