aboutsummaryrefslogtreecommitdiff
path: root/riscv/jtag_dtm.h
blob: e425c8e976cbb51858339b61f779c304e2e06577 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef JTAG_DTM_H
#define JTAG_DTM_H

#include <stdint.h>

typedef enum {
  TEST_LOGIC_RESET,
  RUN_TEST_IDLE,
  SELECT_DR_SCAN,
  CAPTURE_DR,
  SHIFT_DR,
  EXIT1_DR,
  PAUSE_DR,
  EXIT2_DR,
  UPDATE_DR,
  SELECT_IR_SCAN,
  CAPTURE_IR,
  SHIFT_IR,
  EXIT1_IR,
  PAUSE_IR,
  EXIT2_IR,
  UPDATE_IR
} jtag_state_t;

class jtag_dtm_t
{
  static const unsigned idcode_ir = 1;
  static const unsigned idcode_dr = 0xdeadbeef;
  static const unsigned dtmcontrol_ir = 0x10;

  public:
    jtag_dtm_t() :
      dtmcontrol(
          (6 << 4) |        // abits
          1                 // version
          ),
      state(TEST_LOGIC_RESET) {}

    void reset() {
      state = TEST_LOGIC_RESET;
    }

    void set_pins(bool tck, bool tms, bool tdi);

    bool tdo() const { return _tdo; }

  private:
    bool _tck, _tms, _tdi, _tdo;
    uint32_t ir;
    const unsigned ir_length = 5;
    uint64_t dr;
    unsigned dr_length;

    uint32_t dtmcontrol;

    jtag_state_t state;

    void capture_dr();
    void update_dr();

    const jtag_state_t next[16][2] = {
      /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
      /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
      /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
      /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
      /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
      /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
      /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
      /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
      /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
      /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
      /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
      /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
      /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
      /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
      /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
      /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
    };
};

#endif