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

Subversion Repositories w11

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

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

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

powered by: WebSVN 2.1.0

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