import json
class SimConfig():
- def __init__(self, default_clk=None):
+ def __init__(self, default_clk=None, timebase_ps=1):
self.modules = []
self.default_clk = default_clk
+ self.timebase = timebase_ps
if default_clk:
self.add_clocker(default_clk)
new.append(obj)
return new
+ def _format_timebase(self):
+ return {"timebase": int(self.timebase)}
+
def add_clocker(self, clk):
self.add_module("clocker", [], clocks=clk, tickfirst=True)
return False
def get_json(self):
- return json.dumps(self.modules, indent=4)
+ config = self.modules + [self._format_timebase()]
+ return json.dumps(config, indent=4)
#ifndef __MODULE_H_
#define __MODULE_H_
+#include <stdint.h>
#include "pads.h"
struct interface_s {
struct ext_module_list_s *next;
};
-int litex_sim_file_to_module_list(char *filename, struct module_s **mod);
+int litex_sim_file_parse(char *filename, struct module_s **mod, uint64_t *timebase);
int litex_sim_load_ext_modules(struct ext_module_list_s **mlist);
int litex_sim_find_ext_module(struct ext_module_list_s *first, char *name , struct ext_module_list_s **found);
for(i = 0; i < n; i++)
{
tobj = json_object_array_get_idx(obj, i);
+
if(!json_object_object_get_ex(tobj, "module", &name))
{
- ret=RC_JSERROR;
- eprintf("expected \"module\" in object (%s)\n", json_object_to_json_string(tobj));
- goto out;
+ continue;
}
if(!json_object_object_get_ex(tobj, "interface", &interface))
m->tickfirst = json_object_get_boolean(tickfirst);
}
}
+
+ if (!m)
+ {
+ ret = RC_JSERROR;
+ eprintf("No modules found in config file:\n%s\n", json_object_to_json_string(obj));
+ goto out;
+ }
+
*mod = first;
first=NULL;
return ret;
}
-int litex_sim_file_to_module_list(char *filename, struct module_s **mod)
+static int json_get_timebase(json_object *obj, uint64_t *timebase)
+{
+ json_object *tobj;
+ int ret=RC_OK;
+ int i, n;
+ uint64_t _timebase = 0;
+ json_object *json_timebase;
+
+ if(!obj || !timebase)
+ {
+ ret = RC_INVARG;
+ eprintf("Wrong arguments\n");
+ goto out;
+ }
+
+ if(!json_object_is_type(obj, json_type_array))
+ {
+ ret=RC_JSERROR;
+ eprintf("Config file must be an array\n");
+ goto out;
+ }
+
+ n = json_object_array_length(obj);
+ for(i = 0; i < n; i++)
+ {
+ tobj = json_object_array_get_idx(obj, i);
+
+ if(!json_object_object_get_ex(tobj, "timebase", &json_timebase))
+ {
+ continue;
+ }
+
+ if (_timebase != 0)
+ {
+ ret=RC_JSERROR;
+ eprintf("\"timebase\" found multiple times: in object (%s)\n", json_object_to_json_string(tobj));
+ goto out;
+ }
+
+ _timebase = json_object_get_uint64(json_timebase);
+ if (_timebase == 0)
+ {
+ ret=RC_JSERROR;
+ eprintf("\"timebase\" cannot be zero: in object (%s)\n", json_object_to_json_string(tobj));
+ goto out;
+ }
+ }
+
+ if (_timebase == 0)
+ {
+ ret=RC_JSERROR;
+ eprintf("No \"timebase\" found in config:\n%s\n", json_object_to_json_string(obj));
+ goto out;
+ }
+ *timebase = _timebase;
+
+out:
+ return ret;
+}
+
+
+int litex_sim_file_parse(char *filename, struct module_s **mod, uint64_t *timebase)
{
struct module_s *m=NULL;
json_object *obj=NULL;
goto out;
}
+ ret = json_get_timebase(obj, timebase);
+ if(RC_OK != ret)
+ {
+ goto out;
+ }
+
ret = json_to_module_list(obj, &m);
if(RC_OK != ret)
{
struct session_list_s *next;
};
+uint64_t timebase_ps = 1;
struct session_list_s *sesslist=NULL;
struct event_base *base=NULL;
}
/* Load configuration */
- ret = litex_sim_file_to_module_list("sim_config.js", &ml);
+ ret = litex_sim_file_parse("sim_config.js", &ml, &timebase_ps);
if(RC_OK != ret)
{
goto out;
s->module->tick(s->session);
}
+ litex_sim_increment_time(timebase_ps);
+
if (litex_sim_got_finish()) {
event_base_loopbreak(base);
break;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#include "Vsim.h"
#include "verilated.h"
#ifdef TRACE_FST
#else
VerilatedVcdC* tfp;
#endif
-long tfp_start;
-long tfp_end;
+uint64_t tfp_start;
+uint64_t tfp_end;
+uint64_t main_time = 0;
extern "C" void litex_sim_eval(void *vsim)
{
sim->eval();
}
+extern "C" void litex_sim_increment_time(unsigned long dt_ps) {
+ main_time += dt_ps;
+}
+
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[])
{
Verilated::commandArgs(argc, argv);
{
Vsim *sim = (Vsim*)vsim;
tfp_start = start;
- tfp_end = end;
+ tfp_end = end >= 0 ? end : UINT64_MAX;
Verilated::traceEverOn(true);
#ifdef TRACE_FST
tfp = new VerilatedFstC;
sim->trace(tfp, 99);
tfp->open("sim.vcd");
#endif
+ tfp->set_time_unit("1ps");
+ tfp->set_time_resolution("1ps");
}
extern "C" void litex_sim_tracer_dump()
{
- static unsigned int ticks=0;
- int dump = 1;
- if (ticks < tfp_start)
- dump = 0;
- if (tfp_end != -1)
- if (ticks > tfp_end)
- dump = 0;
- if (dump)
- tfp->dump(ticks);
- ticks++;
+ if (tfp_start <= main_time && main_time <= tfp_end) {
+ tfp->dump(main_time);
+ }
}
extern "C" int litex_sim_got_finish()
}
#endif
-vluint64_t main_time = 0;
double sc_time_stamp()
{
return main_time;
#ifdef __cplusplus
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[]);
extern "C" void litex_sim_eval(void *vsim);
+extern "C" void litex_sim_increment_time(unsigned long dt_ps);
extern "C" void litex_sim_init_tracer(void *vsim, long start, long end)
extern "C" void litex_sim_tracer_dump();
extern "C" int litex_sim_got_finish();
#endif
#else
void litex_sim_eval(void *vsim);
+void litex_sim_increment_time(unsigned long dt_ps);
void litex_sim_init_tracer(void *vsim);
void litex_sim_tracer_dump();
int litex_sim_got_finish();
soc_kwargs = soc_sdram_argdict(args)
builder_kwargs = builder_argdict(args)
- sim_config = SimConfig(default_clk="sys_clk")
+ # timebase is half of the period of main simulation clock
+ sys_clk_freq = int(1e6)
+ sim_config = SimConfig(default_clk="sys_clk", timebase_ps=(1/sys_clk_freq / 2) * 1e12)
# Configuration --------------------------------------------------------------------------------