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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [tools/] [src/] [librwxxtpp/] [RtclRw11Cpu.cpp] - Blame information for rev 19

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

Line No. Rev Author Line
1 19 wfjm
// $Id: RtclRw11Cpu.cpp 504 2013-04-13 15:37:24Z mueller $
2
//
3
// Copyright 2013- 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
// 2013-04-02   502   1.0    Initial version
17
// 2013-02-02   480   0.1    First draft
18
// ---------------------------------------------------------------------------
19
 
20
/*!
21
  \file
22
  \version $Id: RtclRw11Cpu.cpp 504 2013-04-13 15:37:24Z mueller $
23
  \brief   Implemenation of RtclRw11Cpu.
24
*/
25
 
26
#include <unistd.h>
27
#include <errno.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <sys/wait.h>
31
 
32
#include <vector>
33
#include <memory>
34
#include <sstream>
35
 
36
#include "boost/bind.hpp"
37
 
38
#include "librtools/RerrMsg.hpp"
39
#include "librtools/RlogMsg.hpp"
40
#include "librtools/RosPrintf.hpp"
41
#include "librtools/RosPrintBvi.hpp"
42
#include "librtcltools/Rtcl.hpp"
43
#include "librtcltools/RtclStats.hpp"
44
#include "librtcltools/RtclOPtr.hpp"
45
#include "librtcltools/RtclNameSet.hpp"
46
#include "librlink/RlinkCommandList.hpp"
47
 
48
#include "RtclRw11.hpp"
49
 
50
#include "RtclRw11CntlFactory.hpp"
51
#include "librw11/Rw11Cntl.hpp"
52
 
53
#include "RtclRw11Cpu.hpp"
54
 
55
using namespace std;
56
 
57
/*!
58
  \class Retro::RtclRw11Cpu
59
  \brief FIXME_docs
60
*/
61
 
62
// all method definitions in namespace Retro
63
namespace Retro {
64
 
65
//------------------------------------------+-----------------------------------
66
//! Default constructor
67
 
68
RtclRw11Cpu::RtclRw11Cpu(const std::string& type)
69
  : RtclProxyBase(type),
70
    fGets()
71
{
72
  AddMeth("add",      boost::bind(&RtclRw11Cpu::M_add,     this, _1));
73
  AddMeth("cp",       boost::bind(&RtclRw11Cpu::M_cp,      this, _1));
74
  AddMeth("wtcpu",    boost::bind(&RtclRw11Cpu::M_wtcpu,   this, _1));
75
  AddMeth("deposit",  boost::bind(&RtclRw11Cpu::M_deposit, this, _1));
76
  AddMeth("examine",  boost::bind(&RtclRw11Cpu::M_examine, this, _1));
77
  AddMeth("lsmem",    boost::bind(&RtclRw11Cpu::M_lsmem,   this, _1));
78
  AddMeth("ldabs",    boost::bind(&RtclRw11Cpu::M_ldabs,   this, _1));
79
  AddMeth("ldasm",    boost::bind(&RtclRw11Cpu::M_ldasm,   this, _1));
80
  AddMeth("boot",     boost::bind(&RtclRw11Cpu::M_boot,    this, _1));
81
  AddMeth("get",      boost::bind(&RtclRw11Cpu::M_get,     this, _1));
82
  AddMeth("set",      boost::bind(&RtclRw11Cpu::M_set,     this, _1));
83
  AddMeth("stats",    boost::bind(&RtclRw11Cpu::M_stats,   this, _1));
84
  AddMeth("dump",     boost::bind(&RtclRw11Cpu::M_dump,    this, _1));
85
  AddMeth("$default", boost::bind(&RtclRw11Cpu::M_default, this, _1));
86
}
87
 
88
//------------------------------------------+-----------------------------------
89
//! Destructor
90
 
91
RtclRw11Cpu::~RtclRw11Cpu()
92
{}
93
 
94
//------------------------------------------+-----------------------------------
95
//! FIXME_docs
96
 
97
int RtclRw11Cpu::M_add(RtclArgs& args)
98
{
99
  return RtclRw11CntlFactory(args, *this);
100
}
101
 
102
//------------------------------------------+-----------------------------------
103
//! FIXME_docs
104
 
105
int RtclRw11Cpu::M_cp(RtclArgs& args)
106
{
107
  static RtclNameSet optset("-rr|-rr0|-rr1|-rr2|-rr3|-rr4|-rr5|-rr6|-rr7|"
108
                            "-wr|-wr0|-wr1|-wr2|-wr3|-wr4|-wr5|-wr6|-wr7|"
109
                            "-rsp|-rpc|-wsp|-wpc|"
110
                            "-rps|-wps|"
111
                            "-wal|-wah|-rm|-rmi|-wm|-wmi|-brm|-bwm|"
112
                            "-stapc|-start|-stop|-continue|-step|-reset|"
113
                            "-ribrb|-wibrb|-wibrbbe|-ribr|-wibr|"
114
                            "-rconf|-rstat|"
115
                            "-edata|-estat|-estatdef"
116
                            );
117
 
118
  Tcl_Interp* interp = args.Interp();
119
 
120
  RlinkCommandList clist;
121
  string opt;
122
  uint16_t base = Obj().Base();
123
 
124
  vector<string> vardata;
125
  vector<string> varstat;
126
 
127
  uint8_t estatdef_val = 0x00;
128
  uint8_t estatdef_msk = 0xff;
129
 
130
  bool setcpugo = false;
131
 
132
  while (args.NextOpt(opt, optset)) {
133
    size_t lsize = clist.Size();
134
 
135
    // map register read/write
136
    if (opt == "-rsp") opt = "-rr6";
137
    if (opt == "-rpc") opt = "-rr7";
138
    if (opt == "-wsp") opt = "-wr6";
139
    if (opt == "-wpc") opt = "-wr7";
140
 
141
    int regnum = 0;
142
    if (opt.substr(0,3) == "-rr" || opt.substr(0,3) == "-wr" ) {
143
      if (opt.length() == 3) {
144
        if (!args.GetArg("regnum", regnum, 0, 7)) return kERR;
145
      } else {
146
        regnum = opt[3] - '0';
147
        regnum &= 0x7;                      // to be sure...
148
      }
149
      opt = opt.substr(0,3);
150
    }
151
 
152
    if        (opt == "-rr") {              // -rr* ?varData ?varStat --------
153
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
154
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
155
      clist.AddRreg(base + Rw11Cpu::kCp_addr_r0 + regnum);
156
 
157
    } else if (opt == "-wr") {              // -wr* data ?varStat ------------
158
      uint16_t data;
159
      if (!args.GetArg("data", data)) return kERR;
160
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
161
      clist.AddWreg(base + Rw11Cpu::kCp_addr_r0 + regnum, data);
162
 
163
    } else if (opt == "-rps") {             // -rps ?varData ?varStat --------
164
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
165
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
166
      clist.AddRreg(base + Rw11Cpu::kCp_addr_psw);
167
 
168
    } else if (opt == "-wps") {             // -wps data ?varStat ------------
169
      uint16_t data;
170
      if (!args.GetArg("data", data)) return kERR;
171
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
172
      clist.AddWreg(base + Rw11Cpu::kCp_addr_psw, data);
173
 
174
    } else if (opt == "-wal") {             // -wal data ?varStat ------------
175
      uint16_t data;
176
      if (!args.GetArg("al", data)) return kERR;
177
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
178
      clist.AddWreg(base + Rw11Cpu::kCp_addr_al, data);
179
 
180
    } else if (opt == "-wah") {             // -wah data ?varStat ------------
181
      uint16_t data;
182
      if (!args.GetArg("ah", data)) return kERR;
183
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
184
      clist.AddWreg(base + Rw11Cpu::kCp_addr_ah, data);
185
 
186
    } else if (opt == "-rm" ||              // -rm(i) ?varData ?varStat ------
187
               opt == "-rmi") {
188
      uint16_t addr = opt=="-rm" ? Rw11Cpu::kCp_addr_mem : Rw11Cpu::kCp_addr_memi;
189
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
190
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
191
      clist.AddRreg(base + addr);
192
 
193
    } else if (opt == "-wm" ||              // -wm(i) data ?varStat -
194
               opt == "-wmi") {
195
      uint16_t addr = opt=="-wm" ? Rw11Cpu::kCp_addr_mem :
196
                                   Rw11Cpu::kCp_addr_memi;
197
      uint16_t data;
198
      if (!args.GetArg("data", data)) return kERR;
199
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
200
      clist.AddWreg(base + addr, data);
201
 
202
    } else if (opt == "-brm") {             // -brm size ?varData ?varStat ---
203
      int32_t bsize;
204
      if (!args.GetArg("bsize", bsize, 1, 256)) return kERR;
205
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
206
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
207
      clist.AddRblk(base + Rw11Cpu::kCp_addr_memi, (size_t) bsize);
208
 
209
    } else if (opt == "-bwm") {             // -bwm block ?varStat -----------
210
      vector<uint16_t> block;
211
      if (!args.GetArg("data", block, 1, 256)) return kERR;
212
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
213
      clist.AddWblk(base + Rw11Cpu::kCp_addr_memi, block);
214
 
215
    } else if (opt == "-stapc") {           // -stapc addr ?varStat ----------
216
      uint16_t data;
217
      if (!args.GetArg("data", data)) return kERR;
218
      if (!GetVarName(args, "??varStat", lsize+1, varstat)) return kERR;
219
      clist.AddWreg(base + Rw11Cpu::kCp_addr_pc, data);
220
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_start);
221
      setcpugo = true;
222
 
223
    } else if (opt == "-start") {           // -start ?varStat ---------------
224
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
225
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_start);
226
      setcpugo = true;
227
 
228
    } else if (opt == "-stop") {            // -stop ?varStat ----------------
229
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
230
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_stop);
231
 
232
    } else if (opt == "-continue") {        // -continue ?varStat ------------
233
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
234
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_cont);
235
      setcpugo = true;
236
 
237
    } else if (opt == "-step") {            // -step ?varStat ----------------
238
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
239
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_step);
240
 
241
    } else if (opt == "-reset") {           // -reset ?varStat ---------------
242
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
243
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_reset);
244
 
245
    } else if (opt == "-ribrb") {           // -ribrb ?varData ?varStat ------
246
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
247
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
248
      clist.AddRreg(base + Rw11Cpu::kCp_addr_ibrb);
249
 
250
    } else if (opt == "-wibrb") {           // -wibrb base ?varStat ----------
251
      uint16_t data;
252
      if (!args.GetArg("base", data)) return kERR;
253
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
254
      data &= 0177700;                        // clear byte enables 
255
      clist.AddWreg(base + Rw11Cpu::kCp_addr_ibrb, data);
256
 
257
    } else if (opt == "-wibrbbe") {         // -wibrbbe base be ?varStat -----
258
      uint16_t data;
259
      uint16_t be;
260
      if (!args.GetArg("base", data)) return kERR;
261
      if (!args.GetArg("be", be, 0x3)) return kERR;
262
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
263
      data &= 0177700;                        // clear byte enables from base
264
      if (be == 0) be = 0x3;                  // map be 0 -> be 3
265
      data |= be;                             // set byte enables 
266
      clist.AddWreg(base + Rw11Cpu::kCp_addr_ibrb, data);
267
 
268
    } else if (opt == "-ribr") {           // -ribr off ?varData ?varStat ----
269
      uint16_t off;
270
      if (!args.GetArg("off",  off, 63)) return kERR;
271
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
272
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
273
      clist.AddRreg(base + Rw11Cpu::kCp_addr_ibr + off/2);
274
 
275
    } else if (opt == "-wibr") {           // -wibrb off data ?varStat --------
276
      uint16_t off;
277
      uint16_t data;
278
      if (!args.GetArg("off",  off, 63)) return kERR;
279
      if (!args.GetArg("data", data)) return kERR;
280
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
281
      clist.AddWreg(base + Rw11Cpu::kCp_addr_ibr + off/2, data);
282
 
283
    } else if (opt == "-rconf") {           // -rconf ?varData ?varStat ------
284
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
285
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
286
      clist.AddRreg(base + Rw11Cpu::kCp_addr_conf);
287
 
288
    } else if (opt == "-rstat") {           // -rstat ?varData ?varStat ------
289
      if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
290
      if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
291
      clist.AddRreg(base + Rw11Cpu::kCp_addr_stat);
292
 
293
    } else if (opt == "-edata") {           // -edata data ?mask --------------
294
      if (lsize == 0)
295
        return args.Quit("-E: -edata not allowed on empty command list");
296
      if (clist[lsize-1].Expect()==0) {
297
        clist.LastExpect(new RlinkCommandExpect());
298
      }
299
      if (clist[lsize-1].Command() == RlinkCommand::kCmdRblk) {
300
        vector<uint16_t> data;
301
        vector<uint16_t> mask;
302
        size_t bsize = clist[lsize-1].BlockSize();
303
        if (!args.GetArg("data", data, 0, bsize)) return kERR;
304
        if (!args.GetArg("??mask", mask, 0, bsize)) return kERR;
305
        clist[lsize-1].Expect()->SetBlock(data, mask);
306
      } else {
307
        uint16_t data=0;
308
        uint16_t mask=0;
309
        if (!args.GetArg("data", data)) return kERR;
310
        if (!args.GetArg("??mask", mask)) return kERR;
311
        clist[lsize-1].Expect()->SetData(data, mask);
312
      }
313
 
314
    } else if (opt == "-estat") {           // -estat ?stat ?mask -------------
315
      if (lsize == 0)
316
        return args.Quit("-E: -estat not allowed on empty command list");
317
      uint8_t stat=0;
318
      uint8_t mask=0;
319
      if (!args.GetArg("??stat", stat)) return kERR;
320
      if (!args.GetArg("??mask", mask)) return kERR;
321
      if (args.NOptMiss() == 2)  mask = 0xff;
322
      if (clist[lsize-1].Expect()==0) {
323
        clist.LastExpect(new RlinkCommandExpect());
324
      }
325
      clist[lsize-1].Expect()->SetStatus(stat, mask);
326
 
327
    } else if (opt == "-estatdef") {        // -estatdef ?stat ?mask -----------
328
      uint8_t stat=0;
329
      uint8_t mask=0;
330
      if (!args.GetArg("??stat", stat)) return kERR;
331
      if (!args.GetArg("??mask", mask)) return kERR;
332
      if (args.NOptMiss() == 2)  mask = 0xff;
333
      estatdef_val = stat;
334
      estatdef_msk = mask;
335
 
336
    }
337
 
338
    if (lsize != clist.Size()) {            // cmd added to clist (ind=lsize!)
339
      if (estatdef_msk != 0xff) {           // estatdef defined
340
        if (clist[lsize].Expect()==0) {
341
          clist.LastExpect(new RlinkCommandExpect());
342
        }
343
        clist[lsize].Expect()->SetStatus(estatdef_val, estatdef_msk);
344
      }
345
    }
346
 
347
  }
348
 
349
  if (!args.AllDone()) return kERR;
350
  if (clist.Size() == 0) return kOK;
351
 
352
  // signal cpugo up before clist executed to prevent races
353
  if (setcpugo) Obj().SetCpuGoUp();
354
 
355
  RerrMsg emsg;
356
  // this one intentionally on Connect() to allow mixing of rlc + w11 commands
357
  // FIXME_code: is this a good idea ??
358
  if (!Connect().Exec(clist, emsg)) return args.Quit(emsg);
359
 
360
  for (size_t icmd=0; icmd<clist.Size(); icmd++) {
361
    RlinkCommand& cmd = clist[icmd];
362
 
363
    if (icmd<vardata.size() && !vardata[icmd].empty()) {
364
      RtclOPtr pres;
365
      vector<uint16_t> retstat;
366
      RtclOPtr pele;
367
      switch (cmd.Command()) {
368
        case RlinkCommand::kCmdRreg:
369
          pres = Tcl_NewIntObj((int)cmd.Data());
370
          break;
371
 
372
        case RlinkCommand::kCmdRblk:
373
          pres = Rtcl::NewListIntObj(cmd.Block());
374
          break;
375
      }
376
      if(!Rtcl::SetVar(interp, vardata[icmd], pres)) return kERR;
377
    }
378
 
379
    if (icmd<varstat.size() && !varstat[icmd].empty()) {
380
      RtclOPtr pres = Tcl_NewIntObj((int)cmd.Status());
381
      if (!Rtcl::SetVar(interp, varstat[icmd], pres)) return kERR;
382
    }
383
  }
384
 
385
  return kOK;
386
}
387
 
388
//------------------------------------------+-----------------------------------
389
//! FIXME_docs
390
 
391
int RtclRw11Cpu::M_wtcpu(RtclArgs& args)
392
{
393
  static RtclNameSet optset("-reset");
394
 
395
  string opt;
396
  bool reset = false;
397
  double tout;
398
 
399
  while (args.NextOpt(opt, optset)) {
400
    if (opt == "-reset") reset = true;
401
  }
402
  if (!args.GetArg("tout", tout, 0.001)) return kERR;
403
  if (!args.AllDone()) return kERR;
404
 
405
  double twait = -1;
406
 
407
  if (!Server().IsActive()) {               // server is not active
408
    RerrMsg emsg;
409
    twait = Connect().WaitAttn(tout, emsg);
410
    if (twait == -2.) {                     // wait failed, quit
411
      return args.Quit(emsg);
412
    }
413
    if (twait >= 0.) {                      // wait succeeded
414
      RlinkCommandList clist;                 // get and discard attn pattern 
415
      clist.AddAttn();
416
      if (!Connect().Exec(clist, emsg)) return args.Quit(emsg);
417
    }
418
 
419
  } else {                                  // server is active
420
    twait = Obj().WaitCpuGoDown(tout);
421
  }
422
 
423
  if (twait < 0.) {                         // timeout
424
    if (Connect().GetLogOpts().printlevel >= 1) {
425
      RlogMsg lmsg(Connect().LogFile());
426
      lmsg << "-- wtcpu to=" << RosPrintf(tout, "f", 0,3) << " FAIL timeout";
427
    }
428
    Connect().Context().IncErrorCount();
429
    if (reset) {                            // reset requested 
430
      uint16_t base = Obj().Base();
431
      RlinkCommandList clist;
432
      clist.AddWreg(base + Rw11Cpu::kCp_addr_cntl, Rw11Cpu::kCp_func_stop);
433
      RerrMsg emsg;
434
      if (!Connect().Exec(clist, emsg)) return args.Quit(emsg);
435
    }
436
  } else {                                  // no timeout
437
    if (Connect().GetLogOpts().printlevel >= 3) {
438
      RlogMsg lmsg(Connect().LogFile());
439
      lmsg << "-- wtcpu to=" << RosPrintf(tout, "f", 0,3)
440
           << "  T=" << RosPrintf(twait, "f", 0,3)
441
           << "  OK";
442
    }
443
  }
444
 
445
  args.SetResult(twait);
446
  return kOK;
447
}
448
 
449
//------------------------------------------+-----------------------------------
450
//! FIXME_docs
451
 
452
int RtclRw11Cpu::M_deposit(RtclArgs& args)
453
{
454
  uint16_t  addr;
455
  vector<uint16_t> data;
456
  if (!args.GetArg("addr", addr)) return kERR;
457
  if (!args.GetArg("data", data, 1)) return kERR;
458
  if (!args.AllDone()) return kERR;
459
 
460
  RerrMsg emsg;
461
  // FIXME_code: handle memory read/write error
462
  if (!Obj().MemWrite(addr, data, emsg)) return args.Quit(emsg);
463
 
464
  return kOK;
465
}
466
 
467
//------------------------------------------+-----------------------------------
468
//! FIXME_docs
469
 
470
int RtclRw11Cpu::M_examine(RtclArgs& args)
471
{
472
  uint16_t  addr;
473
  if (!args.GetArg("addr", addr)) return kERR;
474
  if (!args.AllDone()) return kERR;
475
 
476
  RerrMsg emsg;
477
  vector<uint16_t> data;
478
  // FIXME_code: handle memory read/write error
479
  if (!Obj().MemRead(addr, data, 1, emsg)) return args.Quit(emsg);
480
 
481
  args.SetResult(Rtcl::NewListIntObj(data));
482
 
483
  return kOK;
484
}
485
 
486
//------------------------------------------+-----------------------------------
487
//! FIXME_docs
488
 
489
int RtclRw11Cpu::M_lsmem(RtclArgs& args)
490
{
491
  uint16_t  abeg;
492
  if (!args.GetArg("abeg", abeg)) return kERR;
493
  uint16_t  aend = abeg;
494
  if (!args.GetArg("?aend", aend, 0xffff, abeg)) return kERR;
495
  if (!args.AllDone()) return kERR;
496
 
497
  RerrMsg emsg;
498
  vector<uint16_t> data;
499
  size_t nword = 1+(aend-abeg)/2;
500
  // FIXME_code: handle memory read/write error
501
  if (!Obj().MemRead(abeg, data, nword, emsg)) return args.Quit(emsg);
502
 
503
  ostringstream sos;
504
  for (size_t i=0; i<nword; i++) {
505
    sos << RosPrintBvi(uint16_t(abeg+i*2), 8)
506
        << " : " <<  RosPrintBvi(data[i], 8) << endl;
507
  }
508
 
509
  args.SetResult(sos);
510
 
511
  return kOK;
512
}
513
 
514
//------------------------------------------+-----------------------------------
515
//! FIXME_docs
516
 
517
int RtclRw11Cpu::M_ldabs(RtclArgs& args)
518
{
519
  string file;
520
  if (!args.GetArg("file", file)) return kERR;
521
  if (!args.AllDone()) return kERR;
522
  RerrMsg emsg;
523
  // FIXME_code: handle memory read/write error
524
  if (!Obj().LoadAbs(file, emsg, true)) return args.Quit(emsg);
525
  return kOK;
526
}
527
 
528
//------------------------------------------+-----------------------------------
529
//! FIXME_docs
530
 
531
int RtclRw11Cpu::M_ldasm(RtclArgs& args)
532
{
533
  static RtclNameSet optset("-lst|-sym|-opt|-file");
534
  Tcl_Interp* interp = args.Interp();
535
 
536
  string varlst;
537
  string varsym;
538
  string asmopt;
539
  string file;
540
  string code;
541
 
542
  string opt;
543
  while (args.NextOpt(opt, optset)) {
544
    if (opt == "-lst") {
545
      if (!args.GetArg("??varLst", varlst)) return kERR;
546
    } else if (opt == "-sym") {
547
      if (!args.GetArg("??varSym", varsym)) return kERR;
548
    } else if (opt == "-opt") {
549
      // don't use ?? because the argument will look like an option...
550
      if (!args.GetArg("opts", asmopt)) return kERR;
551
    } else if (opt == "-file") {
552
      if (!args.GetArg("??file", file)) return kERR;
553
    }
554
  }
555
 
556
  if (file.length() == 0) {
557
    if (!args.GetArg("code", code)) return kERR;
558
  }
559
  if (!args.AllDone()) return kERR;
560
 
561
  // delete sym array, otherwise old entries are preserved
562
  if (varsym.length())
563
    Tcl_UnsetVar(interp, varsym.c_str(), 0);
564
 
565
  int pipe_tcl2asm[2];                      // [0] read, [1] write end
566
  int pipe_asm2tcl[2];
567
 
568
  if (::pipe(pipe_tcl2asm) < 0)
569
    return args.Quit(RerrMsg("RtclRw11Cpu::M_ldasm" ,
570
                             "1st pipe() failed: ", errno));
571
  if (::pipe(pipe_asm2tcl) < 0)
572
    return args.Quit(RerrMsg("RtclRw11Cpu::M_ldasm" ,
573
                             "2nd pipe() failed: ", errno));
574
 
575
  pid_t pid = ::fork();
576
  if (pid == (pid_t) 0) {                   // in child here
577
    vector<const char*> argv;
578
    vector<string>      opts;
579
 
580
    argv.push_back("asm-11");
581
    if (varlst.length()>0) argv.push_back("--olst=-");
582
    argv.push_back("--ocof=-");
583
    if (asmopt.length()) {
584
      istringstream optstream(asmopt);
585
      string tok;
586
      while (optstream >> tok) {
587
        opts.push_back(tok);
588
        argv.push_back(opts[opts.size()-1].c_str());
589
      }
590
    }
591
    if (file.length()) {
592
      argv.push_back(file.c_str());
593
    } else {
594
      argv.push_back("-");
595
    }
596
    argv.push_back(NULL);
597
 
598
    ::dup2(pipe_tcl2asm[0], STDIN_FILENO);
599
    ::dup2(pipe_asm2tcl[1], STDOUT_FILENO);
600
    ::dup2(STDOUT_FILENO, STDERR_FILENO);
601
    ::close(pipe_tcl2asm[1]);
602
    ::close(pipe_asm2tcl[0]);
603
    ::execvp("asm-11", (char* const*) argv.data());
604
    ::perror("execvp() for asm-11 failed");
605
    ::exit(EXIT_FAILURE);
606
 
607
  } else {                                  // in parent here
608
    ::close(pipe_tcl2asm[0]);
609
    ::close(pipe_asm2tcl[1]);
610
    if (pid < (pid_t) 0)
611
      return args.Quit(RerrMsg("RtclRw11Cpu::M_ldasm" ,
612
                               "fork() failed: ", errno));
613
  }
614
 
615
  // if first line empty, drop it (created often by using {)
616
  if (code.length() && code[0] == '\n') code = code.substr(1);
617
 
618
  istringstream ostream(code);
619
  string oline;
620
  while (std::getline(ostream, oline)) {
621
    oline += '\n';
622
    //cout << "+++1:" << oline;
623
    if (::write(pipe_tcl2asm[1], oline.data(), oline.length()) < 0) break;
624
  }
625
  ::close(pipe_tcl2asm[1]);
626
 
627
  FILE* fp = ::fdopen(pipe_asm2tcl[0], "r");
628
  if (fp == NULL) {
629
    ::close(pipe_asm2tcl[0]);
630
    return args.Quit(RerrMsg("RtclRw11Cpu::M_ldasm" ,
631
                             "fdopen() failed: ", errno));
632
  }
633
 
634
  vector<string> ilines;
635
  while(true) {
636
    char* pline = NULL;
637
    size_t nchar;
638
    if (::getline(&pline, &nchar, fp) < 0) break;
639
    //cout << "+++2:" << pline;
640
    string line(pline);
641
    if (line.length() && line[line.length()-1] =='\n')
642
      line.resize(line.length()-1);
643
    ilines.push_back(line);
644
    ::free(pline);
645
  }
646
  ::fclose(fp);
647
  ::close(pipe_asm2tcl[0]);
648
 
649
  int wstat;
650
  int wexit = -1;
651
  waitpid(pid, &wstat, 0);
652
  if (WIFEXITED(wstat)) wexit = WEXITSTATUS(wstat);
653
 
654
  bool insym = false;
655
  bool indat = false;
656
  char dtyp = ' ';
657
 
658
  ostringstream los;                        // list stream
659
  ostringstream eos;                        // error stream
660
  bool lstbodyseen = false;
661
 
662
  typedef map<uint16_t, uint16_t>  cmap_t;
663
  typedef cmap_t::iterator         cmap_it_t;
664
  typedef cmap_t::value_type       cmap_val_t;
665
 
666
  cmap_t   cmap;
667
  uint16_t dot = 0;
668
 
669
  for (size_t i=0; i<ilines.size(); i++) {
670
    string& line = ilines[i];
671
    if (line == "sym {") {
672
      insym = true;
673
      continue;
674
    } else if (line == "dat {") {
675
      indat = true;
676
      continue;
677
    } else if (dtyp == ' ' && line == "}") {
678
      insym = false;
679
      indat = false;
680
      continue;
681
    }
682
 
683
    // handle symbol table
684
    if (insym) {
685
      if (varsym.length() == 0) continue;
686
      size_t dpos = line.find(" => ");
687
      if (dpos != std::string::npos) {
688
        string key = line.substr(0,dpos);
689
        string val= line.substr(dpos+4);
690
        if (!Tcl_SetVar2Ex(interp, varsym.c_str(), key.c_str(),
691
                           Tcl_NewIntObj((int)strtol(val.c_str(),NULL,8)),
692
                           TCL_LEAVE_ERR_MSG)) return kERR;
693
      } else {
694
        return args.Quit(string("bad sym spec: ") + line);
695
      }
696
 
697
    // handle data part
698
    } else if (indat) {
699
      if (dtyp == ' ') {
700
        if (line.length() != 10)
701
          return args.Quit(string("bad dat spec: ") + line);
702
        dtyp = line[0];
703
        dot  = (uint16_t)strtol(line.c_str()+2,NULL,8);
704
      } else if (line[0] == '}') {
705
        dtyp = ' ';
706
      } else {
707
        istringstream datstream(line);
708
        string dat;
709
        while (datstream >> dat) {
710
          //cout << "+++1 " << dtyp << ":" << dat << endl;
711
          uint16_t val = (uint16_t)strtol(dat.c_str(),NULL,8);
712
          if (dtyp == 'w') {
713
            cmap[dot] = val;
714
            dot += 2;
715
          } else {
716
            uint16_t tmp = cmap[dot&0xfffe];
717
            if (dot & 01) {
718
              tmp = (val&0xff)<<8 | (tmp&0xff); // odd (high) byte
719
            } else {
720
              tmp = (tmp&0xff00)  | (val&0xff); // even (low) byte
721
            }
722
            cmap[dot&0xfffe] = tmp;
723
            dot += 1;
724
          }
725
        }
726
      }
727
 
728
    // handle listing part (everything not sym{} or dat{}
729
    } else {
730
      los << line << endl;
731
      // put lines into error stream if
732
      //  1. before 'Input file list:' and not starting with '--'
733
      //  2. after  'Input file list:' and starting with uppercase letter
734
      if (line == "; Input file list:") lstbodyseen = true;
735
      bool etake = false;
736
      if (lstbodyseen) {
737
        if (line.length() && (line[0]>'A' && line[0]<'Z')) etake = true;
738
      } else {
739
        if (line.substr(0,2) != "--") etake = true;
740
      }
741
      if (line.substr(0,6) == "asm-11") etake = true;
742
      if (etake) eos << line << endl;
743
    }
744
  }
745
 
746
  if (varlst.length()) {
747
    if (!Rtcl::SetVar(interp, varlst, Rtcl::NewLinesObj(los))) return kERR;
748
  }
749
 
750
  // now, finally, iterate of cmap and write code to memory
751
 
752
  vector<uint16_t> block;
753
  uint16_t base = 0;
754
  dot = 0;
755
  RerrMsg emsg;
756
 
757
  for (cmap_it_t it=cmap.begin(); it!=cmap.end(); it++) {
758
    //cout << "+++2 mem[" << RosPrintf(it->first, "o0", 6)
759
    //     << "]=" << RosPrintf(it->second, "o0", 6) << endl;
760
    if (dot != it->first || block.size() == 256) {
761
      if (block.size()) {
762
        if (!Obj().MemWrite(base, block, emsg)) return args.Quit(emsg);
763
        block.clear();
764
      }
765
      base = dot = it->first;
766
    }
767
    block.push_back(it->second);
768
    dot += 2;
769
  }
770
 
771
  if (block.size()) {
772
    if (!Obj().MemWrite(base, block, emsg)) return args.Quit(emsg);
773
    block.clear();
774
  }
775
 
776
  if (wexit != 0) {
777
    args.AppendResultLines("asm-11 compilation failed with:");
778
    args.AppendResultLines(eos);
779
    return kERR;
780
  }
781
 
782
  return kOK;
783
}
784
 
785
//------------------------------------------+-----------------------------------
786
//! FIXME_docs
787
 
788
int RtclRw11Cpu::M_boot(RtclArgs& args)
789
{
790
  string uname;
791
  if (!args.GetArg("uname", uname)) return kERR;
792
  if (!args.AllDone()) return kERR;
793
  RerrMsg emsg;
794
  if (!Obj().Boot(uname, emsg)) return args.Quit(emsg);
795
  return kOK;
796
}
797
 
798
//------------------------------------------+-----------------------------------
799
//! FIXME_docs
800
 
801
int RtclRw11Cpu::M_get(RtclArgs& args)
802
{
803
  // synchronize with server thread
804
  boost::lock_guard<RlinkConnect> lock(Obj().Connect());
805
  return fGets.M_get(args);
806
}
807
 
808
//------------------------------------------+-----------------------------------
809
//! FIXME_docs
810
 
811
int RtclRw11Cpu::M_set(RtclArgs& args)
812
{
813
  // synchronize with server thread
814
  boost::lock_guard<RlinkConnect> lock(Obj().Connect());
815
  return fSets.M_set(args);
816
}
817
 
818
//------------------------------------------+-----------------------------------
819
//! FIXME_docs
820
 
821
int RtclRw11Cpu::M_stats(RtclArgs& args)
822
{
823
  RtclStats::Context cntx;
824
  if (!RtclStats::GetArgs(args, cntx)) return kERR;
825
  if (!RtclStats::Collect(args, cntx, Obj().Stats())) return kERR;
826
  return kOK;
827
}
828
 
829
//------------------------------------------+-----------------------------------
830
//! FIXME_docs
831
 
832
int RtclRw11Cpu::M_dump(RtclArgs& args)
833
{
834
  if (!args.AllDone()) return kERR;
835
 
836
  ostringstream sos;
837
  Obj().Dump(sos, 0);
838
  args.SetResult(sos);
839
  return kOK;
840
}
841
 
842
//------------------------------------------+-----------------------------------
843
//! FIXME_docs
844
 
845
int RtclRw11Cpu::M_default(RtclArgs& args)
846
{
847
  if (!args.AllDone()) return kERR;
848
  ostringstream sos;
849
 
850
  vector<string> cntlnames;
851
  Obj().ListCntl(cntlnames);
852
 
853
  sos << "name type ibbase lam" << endl;
854
 
855
  for (size_t i=0; i<cntlnames.size(); i++) {
856
    Rw11Cntl& cntl(Obj().Cntl(cntlnames[i]));
857
    sos << RosPrintf(cntl.Name().c_str(),"-s",4)
858
        << " " << RosPrintf(cntl.Type().c_str(),"-s",4)
859
        << " " << RosPrintf(cntl.Base(),"o",6)
860
        << " " << RosPrintf(cntl.Lam(),"d",3)
861
        << endl;
862
  }
863
 
864
  args.AppendResultLines(sos);
865
  return kOK;
866
}
867
 
868
//------------------------------------------+-----------------------------------
869
//! FIXME_docs
870
 
871
void RtclRw11Cpu::SetupGetSet()
872
{
873
  Rw11Cpu* pobj = &Obj();
874
  fGets.Add<const string&>("type",  boost::bind(&Rw11Cpu::Type, pobj));
875
  fGets.Add<size_t>       ("index", boost::bind(&Rw11Cpu::Index, pobj));
876
  fGets.Add<uint16_t>     ("base",  boost::bind(&Rw11Cpu::Base, pobj));
877
  return;
878
}
879
 
880
//------------------------------------------+-----------------------------------
881
//! FIXME_docs
882
 
883
bool RtclRw11Cpu::GetVarName(RtclArgs& args, const char* argname,
884
                             size_t nind,
885
                             std::vector<std::string>& varname)
886
{
887
  while (varname.size() < nind+1) varname.push_back(string());
888
  string name;
889
  if (!args.GetArg(argname, name)) return false;
890
  if (name.length()) {                      // if variable defined
891
    char c = name[0];
892
    if (isdigit(c) || c=='+' || c=='-' ) {  // check for mistaken number
893
      args.AppendResult("-E: invalid variable name '", name.c_str(),
894
                        "': looks like a number", NULL);
895
      return false;
896
    }
897
  }
898
 
899
  varname[nind] = name;
900
  return true;
901
}
902
 
903
} // end namespace Retro

powered by: WebSVN 2.1.0

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