1 # This file is Copyright (c) 2017 Pierre-Olivier Vauboin <po@lambdaconcept>
2 # This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
9 def __init__(self
, timebase_ps
=None):
11 self
.timebase_ps
= timebase_ps
13 def _format_interfaces(self
, interfaces
):
14 if not isinstance(interfaces
, list):
15 interfaces
= [interfaces
]
19 if isinstance(it
, tuple):
21 obj
= {"name": name
, "index": index
}
25 def _format_timebase(self
):
26 timebase_ps
= self
.timebase_ps
27 if timebase_ps
is None:
28 timebase_ps
= self
._get
_timebase
_ps
()
29 return {"timebase": int(timebase_ps
)}
31 def _get_timebase_ps(self
):
32 clockers
= [m
for m
in self
.modules
if m
["module"] == "clocker"]
33 periods_ps
= [1e12
/ m
["args"]["freq_hz"] for m
in clockers
]
34 # timebase is half of the shortest period
36 assert round(p
/2) == int(p
//2), "Period cannot be represented: {}".format(p
)
37 half_period
= [int(p
//2) for p
in periods_ps
]
38 # find greatest common denominator
40 for p
in half_period
[1:]:
41 gcd
= math
.gcd(gcd
, p
)
45 def add_clocker(self
, clk
, freq_hz
, phase_deg
=0):
46 args
= {"freq_hz": freq_hz
, "phase_deg": phase_deg
}
47 self
.add_module("clocker", [], clocks
=clk
, tickfirst
=True, args
=args
)
49 def add_module(self
, name
, interfaces
, clocks
="sys_clk", args
=None, tickfirst
=False):
50 interfaces
= self
._format
_interfaces
(interfaces
)
51 interfaces
+= self
._format
_interfaces
(clocks
)
54 "interface": interfaces
,
57 newmod
.update({"args": args
})
59 newmod
.update({"tickfirst": tickfirst
})
60 self
.modules
.append(newmod
)
62 def has_module(self
, name
):
63 for module
in self
.modules
:
64 if module
["module"] == name
:
69 assert "clocker" in (m
["module"] for m
in self
.modules
), \
70 "No simulation clocker found! Use sim_config.add_clocker() to define one or more clockers."
71 config
= self
.modules
+ [self
._format
_timebase
()]
72 return json
.dumps(config
, indent
=4)