4 bool sv_check_reg(bool intreg
, uint64_t reg
)
17 // XXX raise exception
19 if (r
->active
&& r
->isvec
)
26 /* this is the "remap" function. note that registers can STILL BE REDIRECTED
27 * yet NOT BE MARKED AS A VECTOR.
29 * reg 5 -> active=false, regidx=XX, isvec=XX -> returns 5
30 * reg 5 -> active=true , regidx=35, isvec=false -> returns 35
31 * reg 5 -> active=true , regidx=35, isvec=true -> returns 35 *PLUS LOOP*
33 * so it is possible for example to use the remap system for C instructions
34 * to get access to the *full* range of registers x0..x63 (yes 63 because
35 * SV doubles both the int and fp regfile sizes), by setting
36 * "active=true, isvec=false" for any of x8..x15
38 * where "active=true, isvec=true" this is the "expected" behaviour
39 * of SV. it's "supposed" to "just" be a vectorisation API. it isn't:
40 * it's quite a bit more.
42 uint64_t sv_insn_t::remap(uint64_t reg
, bool intreg
, int &voffs
)
44 // okaay so first determine which map to use. intreg is passed
45 // in (ultimately) from id_regs.py's examination of the use of
46 // FRS1/RS1, WRITE_FRD/WRITE_RD, which in turn gets passed
47 // in from sv_insn_t::fimap...
57 // next we check if this entry is active. if not, the register
58 // is not being "redirected", so just return the actual reg.
61 return reg
; // not active: return as-is
64 // next we go through the lookup table. *THIS* is why the
65 // sv_reg_entry table is 32 entries (5-bit) *NOT* 6 bits
66 // the *KEY* (reg) is 5-bit, the *VALUE* (actual target reg) is 6-bit
67 // XXX TODO: must actually double NXPR and NXFR in processor.h to cope!!
70 // now we determine if this is a scalar/vector: if it's scalar
71 // we return the re-mapped register...
72 if (!r
->isvec
) // scalar
74 return reg
; // ... remapped at this point...
77 // aaand now, as it's a "vector", FINALLY we can add on the loop-offset
78 // which was passed in to the sv_insn_t constructor (by reference)
79 // and, at last, we have "parallelism" a la contiguous registers.
80 reg
+= voffs
; // wheww :)
82 // however... before returning, we increment the loop-offset for
83 // this particular register, so that on the next loop the next
84 // contiguous register will be used.
89 /* gets the predication value (if active). returns all-1s if not active
90 * also returns whether zeroing is enabled/disabled for this register.
92 * uses the same sort of lookup logic as remap:
94 * - first thing to note is, there is one CSR table for FP and one for INT
95 * (so, FP regs can be predicated separately from INT ones)
96 * - redirection occurs if the CSR entry for the register is "active".
97 * - inversion of the predication can be set (so it's possible to have
98 * the same actual register value be unchanged yet be referred to by
99 * *TWO* redirections, one with inversion, one with not).
101 * note that this function *actually* returns the value of the (integer)
102 * register file, hence why processor_t has to be passed in
104 * note also that *even scalar* ops will be predicated (i.e. if a register
105 * has been set active=true and isvec=false in sv_int_tb or sv_fp_tb).
106 * the way to ensure that scalar ops are not predicated is: set VLEN=0,
107 * set active=false in sv_int_tb/sv_fp_tb for that register, or switch off
108 * the predication for that register (sv_pred_int_tb/sv_pred_fb_tb).
110 * note also that the hard limit on SV maximum vector length is actually
111 * down to the number of bits in the predication i.e. the bitwidth of integer
112 * registers (i.e. XLEN bits).
114 reg_t
sv_insn_t::predicate(processor_t
*p
, uint64_t reg
,
115 bool intreg
, bool &zeroing
)
120 r
= &sv_pred_int_tb
[reg
];
124 r
= &sv_pred_fp_tb
[reg
];
128 return ~0x0; // not active: return all-1s (unconditional "on")
132 reg_t predicate
= READ_REG(reg
); // macros go through processor_t state