AFHBA404
AFHBA404 connects ACQ2106 to PCI-Express
AcqSys.cpp
Go to the documentation of this file.
1 
10 #include "AcqSys.h"
11 #include <iostream>
12 #include <iomanip>
13 #include <fstream>
14 #include <sstream>
15 #include "nlohmann/json.hpp"
16 #include <string.h>
17 
18 #include <stdio.h> // because sprintf()
19 
20 #include <assert.h>
21 
22 
23 
25 
26 VI::VI() {
27  memset(this, 0, sizeof(VI));
28 }
29 
30 int VI::len(void) const {
31  return AI16*2 + AI32*4 + DI32*4 + SP32*4;
32 }
33 VI& VI::operator += (const VI& right) {
34  this->AI16 += right.AI16;
35  this->AI32 += right.AI32;
36  this->DI32 += right.DI32;
37  this->SP32 += right.SP32;
38  return *this;
39 }
40 
41 VI VI::offsets(void) const
42 {
43  VI viff;
44  viff.AI16 = 0;
45  viff.AI32 = 0;
46  assert(!(AI16 != 0 && AI32 != 0));
47  assert(sizeof(int) == 4);
48  viff.DI32 = AI16*sizeof(short) + AI32*sizeof(int);
49  viff.SP32 = viff.DI32 + DI32*sizeof(int);
50  return viff;
51 }
52 
53 VO::VO() {
54  memset(this, 0, sizeof(VO));
55 }
56 VO& VO::operator += (const VO& right) {
57  this->AO16 += right.AO16;
58  this->DO32 += right.DO32;
59  this->PW32 += right.PW32;
60  this->CC32 += right.CC32;
61  return *this;
62 }
63 
64 VO VO::offsets(void) const
65 {
66  VO voff;
67  voff.AO16 = 0;
68  voff.DO32 = AO16*sizeof(short);
69  voff.PW32 = voff.DO32 + DO32*sizeof(unsigned);
70  voff.CC32 = voff.PW32 + PW32*sizeof(PW32V);
71  return voff;
72 }
73 
74 
75 int VO::hwlen(void) const {
76  return AO16*2 + DO32*4 + PW32*sizeof(PW32V);
77 }
78 
79 int VO::len(void) const {
80  return hwlen() + CC32*4;
81 }
82 
83 
84 
85 IO::IO(string _name, VI _vi, VO _vo): name(_name), vi(_vi), vo(_vo), _string(0)
86 {
87 
88 }
89 
91 {
92  if (_string) delete _string;
93 }
94 
95 string IO::toString(void)
96 {
97  return name + " VI:" + to_string(vi.len()) + " VO:" + to_string(vo.len());
98 }
99 
101 {
102  cerr << toString() << endl;
103  int port = 0;
104  for (auto uut: uuts){
105  cerr << "\t" << "[" << port << "] " << uut->toString() <<endl;
106  ++port;
107  }
108 }
109 
110 void HBA::dump_data(const char* basename)
111 {
112  cerr << "dump_data" <<endl;
113 }
114 
115 
116 ACQ::ACQ(int _devnum, string _name, VI _vi, VO _vo, VI _vi_offsets, VO _vo_offsets, VI& sys_vi_cursor, VO& sys_vo_cursor) :
117  IO(_name, _vi, _vo),
118  devnum(_devnum),
119  vi_offsets(_vi_offsets), vo_offsets(_vo_offsets),
120  vi_cursor(sys_vi_cursor), vo_cursor(sys_vo_cursor),
121  nowait(false), wd_mask(0), pollcount(0)
122 {
123  // @@todo hook the device driver.
124  sys_vi_cursor += vi;
125  sys_vo_cursor += vo;
126 }
127 
129 
130 }
131 string ACQ::toString() {
132  char wd[80] = {};
133  if (wd_mask){
134  sprintf(wd, " WD mask: 0x%08x", wd_mask);
135  }
136  return "dev:" + to_string(devnum) + " " + IO::toString() + " Offset of SPAD IN VI :" + to_string(vi_offsets.SP32) + "\n"
137  " System Interface Indices " + to_string(vi_cursor.AI16)+ "," + to_string(vi_cursor.SP32) + wd;
138 }
139 bool ACQ::newSample(int sample)
140 {
141  cerr << " new sample: " << sample << " " << getName() << endl;
142  return true;
143 }
144 
145 unsigned ACQ::tlatch(void)
146 {
147  return 0;
148 }
149 
151 {
152  cerr << "placeholder: ARM unit " << getName() << " now" <<endl;
153 }
154 
155 int get_int(json j, int default_value = 0)
156 {
157  try {
158  return j.get<int>();
159  } catch (std::exception& e){
160  return default_value;
161  }
162 }
163 
164 HBA::HBA(vector <ACQ*> _uuts, VI _vi, VO _vo):
165  devnum(_uuts[0]->devnum&~0x3),
166  IO("HBA"+to_string(devnum), _vi, _vo),
167  uuts(_uuts), vi(_vi), vo(_vo)
168 {
169  for (auto uut: uuts){
170  devs.push_back(uut->devnum);
171  }
172 }
173 
175  for (auto uut : uuts){
176  delete uut;
177  }
178 }
179 extern "C" {
180  extern int sched_fifo_priority;
181 }
182 
183 
184 void HBA::processSample(SystemInterface& systemInterface, int sample)
185 {
186  for (auto uut : uuts){
187  while(!uut->newSample(sample)){
188  sched_fifo_priority>1 || sched_yield();
189  ++uut->pollcount;
190  if (G::maxpoll && sample && uut->pollcount > G::maxpoll){
191  fprintf(stderr, "ERROR: poll timeout on uut %s at sample %d\n", uut->getName().c_str(), sample);
192  throw -22;
193  }
194  }
195  }
196  for (auto uut : uuts){
197  uut->action(systemInterface);
198  }
199  systemInterface.ringDoorbell(sample);
200  for (auto uut : uuts){
201  uut->action2(systemInterface);
202  }
203 }
204 
206 {
207  string dev_str = "devs=";
208  int idev = 0;
209  for (auto dev: devs){
210  if (idev++ != 0){
211  dev_str += ",";
212  }
213  dev_str += to_string(dev);
214  }
215  return IO::toString() + " " + dev_str;
216 }
217 
218 typedef pair<std::string, int> KVP;
219 typedef std::map <std::string, int> KVM;
221 typedef pair<std::string, string> KVPS;
222 typedef std::map <std::string, string> KVMS;
224 //#define COM(comment) KVPS("__comment__", comment)
225 
226 #define COM(i) "__comment" #i "__"
227 
228 #define INSERT_IF(map, vx, vxo, field) \
229  if (uut->vx.field){ \
230  map.insert(KVP(#field, uut->vxo.field)); \
231  }
232 
233 void add_comments(json& jsys, string& fname)
234 {
235  jsys[COM(1)] = "created from " + fname;
236  jsys[COM(2)] = "LOCAL VI_OFFSETS: field offset VI in bytes";
237  jsys[COM(3)] = "LOCAL VO_OFFSETS: field offset VO in bytes";
238  jsys[COM(4)] = "LOCAL VX_LEN: length of VI|VO in bytes";
239  jsys[COM(5)] = "GLOBAL_LEN: total length of each type in SystemInterface";
240  jsys[COM(6)] = "GLOBAL_INDICES: index of field in type-specific array in SI";
241  jsys[COM(7)] = "SPIX: Scratch Pad Index, index of field in SP32";
242 
243 
244  KVM spix_map;
245  spix_map.insert(KVP("TLATCH", SPIX::TLATCH));
246  spix_map.insert(KVP("USECS", SPIX::USECS));
247  spix_map.insert(KVP("POLLCOUNT", SPIX::POLLCOUNT));
248  jsys["SPIX"] = spix_map;
249 }
250 void add_si_lengths(json& jsys, HBA& hba)
251 {
252  SystemInterface si(hba);
253  json &jgl = jsys["GLOBAL_LEN"];
254  json &jlen_vi = jgl["VI"];
255  jlen_vi = {
256  { "AI16", si.AI16_count() },
257  { "AI32", si.AI32_count() },
258  { "DI32", si.DI32_count() },
259  { "SP32", si.SP32_count() }
260  };
261  json &jlen_vo = jgl["VO"];
262  jlen_vo = {
263  { "AO16", si.AO16_count() },
264  { "DO32", si.DO32_count() },
265  { "PW32", si.PW32_count() },
266  { "CC32", si.CC32_count() }
267  };
268 
269 }
270 void store_config(json j, string fname, HBA& hba)
271 {
272  json &jsys = j["SYS"];
273  add_comments(jsys, fname);
274  add_si_lengths(jsys, hba);
275 
276  int ii = 0;
277  for (auto uut : hba.uuts){
278  json &jlo = jsys["UUT"]["LOCAL"][ii];
279 
280  jlo["VX_LEN"] = { { "VI", uut->vi.len() }, { "VO", uut->vo.len() } };
281 
282  KVM vi_offsets_map;
283  INSERT_IF(vi_offsets_map, vi, vi_offsets, AI16);
284  INSERT_IF(vi_offsets_map, vi, vi_offsets, AI32);
285  INSERT_IF(vi_offsets_map, vi, vi_offsets, DI32);
286  INSERT_IF(vi_offsets_map, vi, vi_offsets, SP32);
287  jlo["VI_OFFSETS"] = vi_offsets_map;
288 
289  KVM vo_offsets_map;
290  INSERT_IF(vo_offsets_map, vo, vo_offsets, AO16);
291  INSERT_IF(vo_offsets_map, vo, vo_offsets, DO32);
292  INSERT_IF(vo_offsets_map, vo, vo_offsets, PW32);
293  INSERT_IF(vo_offsets_map, vo, vo_offsets, CC32);
294  jlo["VO_OFFSETS"] = vo_offsets_map;
295 
296  json &jix = jsys["UUT"]["GLOBAL_INDICES"][ii++];
297  KVM vi_map;
298  INSERT_IF(vi_map, vi, vi_cursor, AI16);
299  INSERT_IF(vi_map, vi, vi_cursor, AI32);
300  INSERT_IF(vi_map, vi, vi_cursor, DI32);
301  INSERT_IF(vi_map, vi, vi_cursor, SP32);
302  jix["VI"] = vi_map;
303 
304  KVM vo_map;
305  INSERT_IF(vo_map, vo, vo_cursor, AO16);
306  INSERT_IF(vo_map, vo, vo_cursor, DO32);
307  INSERT_IF(vo_map, vo, vo_cursor, PW32);
308  INSERT_IF(vo_map, vo, vo_cursor, CC32);
309  jix["VO"] = vo_map;
310  }
311 
312 
313  std::ofstream o("runtime.json");
314  o << std::setw(4) << j << std::endl;
315 }
316 
317 int HBA::maxsam;
318 
319 HBA* HBA::the_hba;
320 
321 
322 bool strstr(string haystack, string needle)
323 {
324  return haystack.find(needle) != string::npos;
325 }
326 
327 
329 HBA& HBA::create(const char* json_def, int _maxsam)
330 {
331  json j;
332  std::ifstream i(json_def);
333  i >> j;
334 
335  maxsam = _maxsam;
336  struct VI VI_sys;
337  struct VO VO_sys;
338  vector <ACQ*> uuts;
339  int port = 0;
340  int iuut = 0;
341  string first_type;
342 
343  int hba_devnum = get_int(j["AFHBA"]["DEVNUM"]);
344 
345  for (auto uut : j["AFHBA"]["UUT"]) {
346 
347  if (get_int(uut["DEVNUM"], -1) != -1){
348  hba_devnum = get_int(uut["DEVNUM"]);
349  port = 0;
350  }
351 
352  VI vi;
353 
354  vi.AI16 = get_int(uut["VI"]["AI16"]);
355  vi.AI32 = get_int(uut["VI"]["AI32"]);
356  vi.DI32 = get_int(uut["VI"]["DI32"]);
357  vi.SP32 = get_int(uut["VI"]["SP32"]);
358 
359  VO vo;
360  vo.AO16 = get_int(uut["VO"]["AO16"]);
361  vo.DO32 = get_int(uut["VO"]["DO32"]);
362  vo.PW32 = get_int(uut["VO"]["PW32"]);
363  vo.CC32 = get_int(uut["VO"]["CC32"]);
364 
365  ACQ *acq = ACQ::factory(hba_devnum+port, uut["name"], vi, vo, vi.offsets(), vo.offsets(), VI_sys, VO_sys);
366 
367  try {
368  int wd_bit = uut["WD_BIT"].get<int>();
369  if (port == 0){
370  acq->wd_mask = 1 << wd_bit;
371  }else{
372  cerr << "WARNING: " << uut["name"] << " attempted to set WD_BIT when PORT (" << port << ") != 0" <<endl;
373  }
374  } catch (exception& e) {
375  ;
376  }
377  string uut_type = uut["type"];
378  // check unit compatibility
379  if (iuut == 0){
380  first_type = uut_type;
381  }else{
382  if (::strstr(first_type, "pcs") && ::strstr(uut_type, "bolo")){
383  cerr << "NOTICE: port " << port << " is bolo in non-bolo set, set nowait" << endl;
384  acq->nowait = true;
385  }else if (::strstr(first_type, "pcs") && ::strstr(uut_type, "nowait")){
386  cerr << "NOTICE: port " << port << " set nowait" << endl;
387  acq->nowait = true;
388  }else if (::strstr(first_type, "bolo") && !::strstr(uut_type, "bolo")){
389  cerr << "WARNING: port " << port << " is NOT bolo when port0 IS bolo" << endl;
390  }
391  }
392  uuts.push_back(acq);
393  ++port;
394  ++iuut;
395  }
396  the_hba = new HBA(uuts, VI_sys, VO_sys);
397  store_config(j, json_def, *the_hba);
398  return *the_hba;
399 }
400 
401 SystemInterface::SystemInterface(const HBA& _hba) : hba(_hba)
402 /* make a gash SI to allow simulated operation. The real shm is customer specific */
403 {
404  IN.AI16 = new_zarray<short>(AI16_count());
405  IN.AI32 = new_zarray<int>(AI32_count());
406  IN.DI32 = new_zarray<unsigned>(DI32_count()); // needs to be bigger for PWM
407  IN.SP32 = new_zarray<unsigned>(SP32_count());
408 
409  OUT.AO16 = new_zarray<short>(AO16_count());
410  OUT.DO32 = new_zarray<unsigned>(DO32_count());
411  OUT.PW32 = new_zarray<PW32V>(PW32_count());
412  OUT.CC32 = new_zarray<unsigned>(CC32_count());
413 }
415 {
416  delete [] IN.AI16;
417  delete [] IN.AI32;
418  delete [] IN.DI32;
419  delete [] IN.SP32;
420  delete [] OUT.AO16;
421  delete [] OUT.DO32;
422  delete [] OUT.PW32;
423  delete [] OUT.CC32;
424 }
425 
426 
427 
428 
429 
HBA
Models a Host Bus Adapter like AFHBA404.
Definition: AcqSys.h:123
SystemInterface::Outputs::CC32
unsigned * CC32
calc values from PCS .
Definition: AcqSys.h:181
ACQ::~ACQ
virtual ~ACQ()
Definition: AcqSys.cpp:128
ACQ::vi_cursor
const VI vi_cursor
index for each Input type in System Interface
Definition: AcqSys.h:95
add_comments
void add_comments(json &jsys, string &fname)
Definition: AcqSys.cpp:233
KVM
std::map< std::string, int > KVM
Key Value Pair.
Definition: AcqSys.cpp:219
AcqSys.h
acqproc global class interface definition.
VI
Models Vector Input.
Definition: AcqSys.h:24
HBA::create
static HBA & create(const char *json_def, int _maxsam)
HBA::Create() factory function.
Definition: AcqSys.cpp:329
VO::VO
VO()
Definition: AcqSys.cpp:53
ACQ::ACQ
ACQ(int devnum, string _name, VI _vi, VO _vo, VI _vi_offsets, VO _vo_offsets, VI &sys_vi_cursor, VO &sys_vo_cursor)
Definition: AcqSys.cpp:116
USECS
@ USECS
microseconds since trigger
Definition: AcqSys.h:38
HBA::~HBA
virtual ~HBA()
Definition: AcqSys.cpp:174
KVMS
std::map< std::string, string > KVMS
Key Value Pair, COMMENT.
Definition: AcqSys.cpp:222
TLATCH
@ TLATCH
Sample Number.
Definition: AcqSys.h:37
SystemInterface::Outputs::AO16
short * AO16
Definition: AcqSys.h:178
VI::operator+=
VI & operator+=(const VI &right)
Definition: AcqSys.cpp:33
ACQ::newSample
virtual bool newSample(int sample)
Definition: AcqSys.cpp:139
store_config
void store_config(json j, string fname, HBA &hba)
Definition: AcqSys.cpp:270
SystemInterface::AO16_count
unsigned AO16_count() const
Definition: AcqSys.h:210
ACQ::devnum
int devnum
AFHBA404 device numbers 0..N.
Definition: AcqSys.h:91
add_si_lengths
void add_si_lengths(json &jsys, HBA &hba)
Definition: AcqSys.cpp:250
SystemInterface::PW32_count
unsigned PW32_count() const
Definition: AcqSys.h:216
SystemInterface::Outputs::DO32
unsigned * DO32
Definition: AcqSys.h:179
HBA::vi
const VI vi
total system size each Input type.
Definition: AcqSys.h:131
KVPS
pair< std::string, string > KVPS
Key Value Map
Definition: AcqSys.cpp:221
SystemInterface::DI32_count
unsigned DI32_count() const
Definition: AcqSys.h:204
HBA::uuts
vector< ACQ * > uuts
vector of ACQ UUT's
Definition: AcqSys.h:129
IO::IO
IO(string _name, VI _vi, VO _vo)
Definition: AcqSys.cpp:85
COM
#define COM(i)
Key Value Map
Definition: AcqSys.cpp:226
G::maxpoll
int maxpoll
Definition: acqproc.cpp:39
PW32V
unsigned PW32V[PW32LEN]
Definition: AcqSys.h:43
POLLCOUNT
@ POLLCOUNT
pollcount: number of times SW polled for incoming.
Definition: AcqSys.h:39
VI::AI32
int AI32
AI32 values from the HW.
Definition: AcqSys.h:29
HBA::dump_data
void dump_data(const char *basename)
output raw data for each ACQ
Definition: AcqSys.cpp:110
SystemInterface::SP32_count
unsigned SP32_count() const
Definition: AcqSys.h:207
ACQ::wd_mask
unsigned wd_mask
watchdog mask.
Definition: AcqSys.h:89
VO::hwlen
int hwlen(void) const
Definition: AcqSys.cpp:75
VO::PW32
int PW32
PW32 values from the algorithm.
Definition: AcqSys.h:55
VI::SP32
int SP32
SP32 values from the HW.
Definition: AcqSys.h:31
VO::AO16
int AO16
AO16 values from the algorithm.
Definition: AcqSys.h:53
VO::CC32
int CC32
#CALC values from the algorithm.
Definition: AcqSys.h:56
SystemInterface::ringDoorbell
virtual void ringDoorbell(int sample)
Definition: AcqSys.h:188
SystemInterface::SystemInterface
SystemInterface(const HBA &_hba)
Definition: AcqSys.cpp:401
SystemInterface::AI16_count
unsigned AI16_count() const
Definition: AcqSys.h:198
SystemInterface::IN
struct SystemInterface::Inputs IN
HBA::maxsam
static int maxsam
max samples in shot (for raw memory alloc)
Definition: AcqSys.h:133
SystemInterface::Outputs::PW32
PW32V * PW32
32 demand values packed into shorts
Definition: AcqSys.h:180
IO::vi
const VI vi
Definition: AcqSys.h:69
ACQ::factory
static ACQ * factory(int devnum, string _name, VI _vi, VO _vo, VI _vi_offsets, VO _vo_offsets, VI &sys_vi_cursor, VO &sys_vo_cursor)
Definition: AcqHw.cpp:513
VO
Models Vector Output.
Definition: AcqSys.h:48
strstr
bool strstr(string haystack, string needle)
Definition: AcqSys.cpp:322
ACQ
abstract model of an ACQ2106 box.
Definition: AcqSys.h:83
IO
Base Class.
Definition: AcqSys.h:64
SystemInterface::Inputs::AI32
int * AI32
Definition: AcqSys.h:171
VO::len
int len(void) const
Definition: AcqSys.cpp:79
INSERT_IF
#define INSERT_IF(map, vx, vxo, field)
Definition: AcqSys.cpp:228
VO::operator+=
VO & operator+=(const VO &right)
Definition: AcqSys.cpp:56
VO::DO32
int DO32
DO32 values from the algorithm.
Definition: AcqSys.h:54
VI::len
int len(void) const
Definition: AcqSys.cpp:30
ACQ::vi_offsets
const VI vi_offsets
byte offset for each Input type in Local Vector In
Definition: AcqSys.h:93
IO::~IO
virtual ~IO()
Definition: AcqSys.cpp:90
ACQ::arm
virtual void arm(int nsamples)
prepare to run a shot nsamples long, arm the UUT.
Definition: AcqSys.cpp:150
SystemInterface::OUT
struct SystemInterface::Outputs OUT
HBA::processSample
virtual void processSample(SystemInterface &systemInterface, int sample)
core run time function, processSample.
Definition: AcqSys.cpp:184
SystemInterface::CC32_count
unsigned CC32_count() const
Definition: AcqSys.h:219
SystemInterface::Inputs::AI16
short * AI16
Definition: AcqSys.h:170
VI::AI16
int AI16
AI16 values from the HW.
Definition: AcqSys.h:28
SystemInterface
Models interface with external PCS.
Definition: AcqSys.h:161
ACQ::tlatch
virtual unsigned tlatch(void)
returns latest tlatch from lbuf
Definition: AcqSys.cpp:145
SystemInterface::AI32_count
unsigned AI32_count() const
Definition: AcqSys.h:201
ACQ::toString
virtual string toString()
Definition: AcqSys.cpp:131
get_int
int get_int(json j, int default_value=0)
Definition: AcqSys.cpp:155
KVP
pair< std::string, int > KVP
Definition: AcqSys.cpp:218
HBA::devs
vector< int > devs
AFHBA devnum.
Definition: AcqSys.h:130
VI::offsets
VI offsets(void) const
Definition: AcqSys.cpp:41
HBA::vo
const VO vo
total system size each Output type.
Definition: AcqSys.h:132
SystemInterface::DO32_count
unsigned DO32_count() const
Definition: AcqSys.h:213
sched_fifo_priority
int sched_fifo_priority
Definition: afhba-llcontrol.c:136
IO::getName
string getName()
Definition: AcqSys.h:75
assert
#define assert(p)
Definition: acq-fiber-hba.h:55
json
nlohmann::json json
Definition: AcqSys.cpp:24
SystemInterface::Inputs::SP32
unsigned * SP32
Definition: AcqSys.h:173
VI::DI32
int DI32
DI32 values from the HW.
Definition: AcqSys.h:30
HBA::dump_config
void dump_config()
output complete configuration with calculated offsets
Definition: AcqSys.cpp:100
IO::vo
const VO vo
Definition: AcqSys.h:70
SystemInterface::Inputs::DI32
unsigned * DI32
Definition: AcqSys.h:172
HBA::toString
virtual string toString()
Definition: AcqSys.cpp:205
IO::toString
virtual string toString()
Definition: AcqSys.cpp:95
VO::offsets
VO offsets(void) const
Definition: AcqSys.cpp:64
VI::VI
VI()
Definition: AcqSys.cpp:26
G::nsamples
int nsamples
samples to capture (default:2, typ 200000)
Definition: acqproc.cpp:38
SystemInterface::~SystemInterface
virtual ~SystemInterface()
Definition: AcqSys.cpp:414
ACQ::nowait
bool nowait
newSample doesn't block for new Tlatch (eg bolo in set with non bolo uuts).
Definition: AcqSys.h:88