def log_to_vcd(cfg): """ Cyclically poll heating and log results to VCD file. """ global SIGINT # set up VCD logging now_utc = datetime.datetime.now(datetime.timezone.utc) vcdwriter = VCDWriter(open('vitopy1.vcd', 'w'), timescale='1s', init_timestamp=now_utc.timestamp()) vcdvars = {} for v in config['datapoints']: if not 'addr' in v: continue if not 'id' in v: v['id'] = 'NOID' if type(v['addr']) is str: v['addr'] = int(v['addr'], 0) # parse non-decimal numbers name = '%s_%s' % (v['id'], v['addr']) if 'uint8' == v['type']: logging.info('Adding variable %s' % v['addr']) vcdvars.update({ v['addr']: vcdwriter.register_var('vitopy', name, 'integer', size=8) }) if 'int8' == v['type']: logging.info('Adding variable %s' % v['addr']) vcdvars.update({ v['addr']: vcdwriter.register_var('vitopy', name, 'integer', size=8) }) if 'uint16' == v['type']: logging.info('Adding variable %s' % v['addr']) vcdvars.update({ v['addr']: vcdwriter.register_var('vitopy', name, 'integer', size=16) }) if 'uint32' == v['type']: logging.info('Adding variable %s' % v['addr']) vcdvars.update({ v['addr']: vcdwriter.register_var('vitopy', name, 'integer', size=32) }) # poll heating o = optolink.OptoLink() o.open_port(args.port) o.init() while True: logging.info('-- start of query --') now_utc = datetime.datetime.now(datetime.timezone.utc) allreadings = retrieve_all_readings_as_per_configuration(o, config) print(allreadings) for k in allreadings.keys(): r = allreadings[k] if k in vcdvars: vcdwriter.change(vcdvars[k], now_utc.timestamp(), r) if args.publishmqtt: mqttc.publish(str(k), r) vcdwriter.flush() for i in range(10): time.sleep(1) if SIGINT: break if SIGINT: break logging.info('-- end of query --') o.deinit() o.close_port() vcdwriter.close() return
_name = _bName + "." + _bID if _I == 0: # _c = COLS.setdefault(_bName, {}) # _v = _c.setdefault(_bID, [0]) # _v[0] +=1 # dump.writerow(["TS", "BUS", "BUS_DESC", "ID", "ID_DESC", "VAL"]) dump.writerow({_k:_v for _k,_v in r.iteritems() if _k in dump.fieldnames}) _fo.flush() _l = BUSES.setdefault(_name, []) if not _l: trace.set_scope_type(r['busID'], 'module') _l.append(trace.register_var(r['busID'], _name,'reg', (8, ) * r['dlc'], (0, ) * r['dlc'])) elif _I == 1: _val = r['data'] _dd = [_l[0], _ts, _val[:]] try: trace.change(*_dd) except: print(_dd) trace.flush(_dd[1]) else: assert False if trace: trace.close()
class VCD(SimExtend): @inject def __init__(self, trace_fn='pygears.vcd', include=Inject('debug/trace'), tlm=False, shmidcat=Inject('sim_extens/vcd/shmidcat'), vcd_fifo=Inject('sim_extens/vcd/vcd_fifo'), sim=Inject('sim/simulator'), outdir=Inject('results-dir')): super().__init__() self.sim = sim self.finished = False self.vcd_fifo = vcd_fifo self.shmidcat = shmidcat self.outdir = outdir self.trace_fn = None self.shmid_proc = None vcd_visitor = VCDHierVisitor(include, tlm) vcd_visitor.visit(find('/')) if not vcd_visitor.vcd_vars: self.deactivate() return self.trace_fn = os.path.abspath(os.path.join(self.outdir, trace_fn)) atexit.register(self.finish) try: subprocess.call(f"rm -f {self.trace_fn}", shell=True) except OSError: pass if self.vcd_fifo: subprocess.call(f"mkfifo {self.trace_fn}", shell=True) else: log.info(f'Main VCD dump to "{self.trace_fn}"') if self.shmidcat: self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}', shell=True, stdout=subprocess.PIPE) # Wait for shmidcat to actually open the pipe, which is necessary # to happen prior to init of the verilator. If shmidcat does not # open the pipe, verilator will get stuck import time time.sleep(0.1) self.vcd_file = open(self.trace_fn, 'w') if self.shmidcat: self.shmid = self.shmid_proc.stdout.readline().decode().strip() log.info(f'Main VCD dump to shared memory at 0x{self.shmid}') self.writer = VCDWriter(self.vcd_file, timescale='1 ns', date='today') reg['VCDWriter'] = self.writer reg['VCD'] = self self.clk_var = self.writer.register_var('', 'clk', 'wire', size=1, init=1) self.timestep_var = self.writer.register_var('', 'timestep', 'integer', init=0) self.handhake = set() self.vcd_vars = { p: register_traces_for_intf(p.dtype, scope, self.writer) for p, scope in vcd_visitor.vcd_vars.items() } self.writer.flush() def before_run(self, sim): vcd_intf_vars = {} for p, v in self.vcd_vars.items(): intf = p.consumer intf.events['put'].append(self.intf_put) intf.events['ack'].append(self.intf_ack) vcd_intf_vars[intf] = v self.vcd_vars = vcd_intf_vars def intf_put(self, intf, val): if intf not in self.vcd_vars: return True v = self.vcd_vars[intf] if typeof(intf.dtype, TLM): self.writer.change(v['data'], timestep() * 10, str(val)) else: visitor = VCDValVisitor(v, self.writer, timestep() * 10) visitor.visit(intf.dtype, 'data', val=val) self.writer.change(v['valid'], timestep() * 10, 1) return True def intf_ack(self, intf): if intf not in self.vcd_vars: return True v = self.vcd_vars[intf] self.writer.change(v['ready'], timestep() * 10, 1) self.handhake.add(intf) return True def before_timestep(self, sim, timestep): self.writer.change(self.clk_var, timestep * 10 + 5, 0) return True def after_timestep(self, sim, timestep): timestep += 1 self.writer.change(self.timestep_var, timestep * 10, timestep) self.writer.change(self.clk_var, timestep * 10, 1) for intf, v in self.vcd_vars.items(): if intf in self.handhake: self.writer.change(v['ready'], timestep * 10, 0) self.writer.change(v['valid'], timestep * 10, 0) self.handhake.remove(intf) self.writer.flush() return True def finish(self): if not self.finished: self.writer.close() self.vcd_file.close() self.finished = True if self.shmid_proc: self.shmid_proc.terminate() def after_cleanup(self, sim): self.finish()
class VCD(SimExtend): @inject def __init__( self, trace_fn='pygears.vcd', include=Inject('debug/trace'), tlm=False, shmidcat=Inject('sim_extens/vcd/shmidcat'), vcd_fifo=Inject('sim_extens/vcd/vcd_fifo'), sim=Inject('sim/simulator'), outdir=Inject('results-dir'), expand_data=Inject('debug/expand_trace_data'), ): super().__init__() self.sim = sim self.expand_data = expand_data self.finished = False self.vcd_fifo = vcd_fifo self.shmidcat = shmidcat self.outdir = outdir self.trace_fn = None self.shmid_proc = None self.include = include self.trace_fn = os.path.abspath(os.path.join(self.outdir, trace_fn)) atexit.register(self.finish) try: subprocess.call(f"rm -f {self.trace_fn}", shell=True) except OSError: pass if self.vcd_fifo: subprocess.call(f"mkfifo {self.trace_fn}", shell=True) else: log.info(f'Main VCD dump to "{self.trace_fn}"') if self.shmidcat: self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}', shell=True, stdout=subprocess.PIPE) # Wait for shmidcat to actually open the pipe, which is necessary # to happen prior to init of the verilator. If shmidcat does not # open the pipe, verilator will get stuck import time time.sleep(0.1) self.vcd_file = open(self.trace_fn, 'w') if self.shmidcat: self.shmid = self.shmid_proc.stdout.readline().decode().strip() log.info(f'Main VCD dump to shared memory at 0x{self.shmid}') self.writer = VCDWriter(self.vcd_file, timescale='1 ns', date='today') reg['VCDWriter'] = self.writer reg['VCD'] = self self.clk_var = self.writer.register_var('', 'clk', 'wire', size=1, init=1) self.timestep_var = self.writer.register_var('', 'timestep', 'integer', init=0) self.handhake = set() def before_run(self, sim): vcd_visitor = VCDHierVisitor(self.include, False) vcd_visitor.visit(find('/')) if not vcd_visitor.vcd_vars: self.deactivate('before_run') return True self.vcd_vars = { p: register_traces_for_intf(p.dtype, scope, self.writer, self.expand_data) for p, scope in vcd_visitor.vcd_vars.items() } self.end_consumers = vcd_visitor.end_consumers self.writer.flush() for intf in self.end_consumers: intf.events['put'].append(self.intf_put) intf.events['ack'].append(self.intf_ack) vcd_intf_vars = {} for p, v in self.vcd_vars.items(): intf.events['put'].append(self.intf_put) intf.events['ack'].append(self.intf_ack) vcd_intf_vars[p] = v self.vcd_vars = vcd_intf_vars self.extend_intfs() def extend_intfs(self): for p, v in self.vcd_vars.items(): v['srcs'] = [self.end_consumers[pp.consumer] for pp in get_consumer_tree(p.consumer)] v['srcs_active'] = [False] * len(v['srcs']) v['p'] = p for vs in v['srcs']: vs['prods'].append(v) reg['graph/consumer_tree'] = {} reg['graph/end_producer'] = {} def var_put(self, v, val): cur_timestep = timestep() * 10 if typeof(v['dtype'], (Any, TLM)): self.writer.change(v['data'], cur_timestep, str(val)) else: try: if self.expand_data: visitor = VCDValVisitor(v, self.writer, cur_timestep, max_level=10) visitor.visit(v['dtype'], 'data', val=val) else: self.writer.change(v['data'], cur_timestep, val.code()) except AttributeError: pass self.writer.change(v['valid'], cur_timestep, 1) def intf_put(self, intf, val): p = intf.producer if p in self.vcd_vars: v = self.vcd_vars[p] self.var_put(v, val) if intf in self.end_consumers: v = self.end_consumers[intf] for vp in v['prods']: if not any(vp['srcs_active']): # TODO: Optimization possibility, don't write the data, only ready/valid signals self.var_put(vp, val) for i, vv in enumerate(vp['srcs']): if vv is v: vp['srcs_active'][i] = True break return True def intf_ack(self, intf): p = intf.producer if p in self.vcd_vars: v = self.vcd_vars[p] self.writer.change(v['ready'], timestep() * 10, 1) self.handhake.add(p) if intf in self.end_consumers: v = self.end_consumers[intf] for vp in v['prods']: for i, vv in enumerate(vp['srcs']): if vv is v: vp['srcs_active'][i] = False break if not any(vp['srcs_active']): self.writer.change(vp['ready'], timestep() * 10, 1) self.handhake.add(vp['p']) return True def before_timestep(self, sim, timestep): self.writer.change(self.clk_var, timestep * 10 + 5, 0) return True def after_timestep(self, sim, timestep): timestep += 1 self.writer.change(self.timestep_var, timestep * 10, timestep) self.writer.change(self.clk_var, timestep * 10, 1) for p, v in self.vcd_vars.items(): if p in self.handhake: self.writer.change(v['ready'], timestep * 10, 0) if not any(v['srcs_active']): self.writer.change(v['valid'], timestep * 10, 0) self.handhake.remove(p) self.writer.flush() return True def finish(self): if not self.finished: self.writer.close() self.vcd_file.close() self.finished = True if self.shmid_proc: self.shmid_proc.terminate() def after_cleanup(self, sim): self.finish()