class ModuleTracePort(JinjaTempl): def __init__(self, scfg: StructureConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) probes = scfg.digital_probes + scfg.analog_probes + [scfg.time_probe] + [scfg.dec_cmp] ##################################################### # Define module ios ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="trace_port_gen") # Add probe signals module.add_inputs(probes) # Add master clk module.add_input(scfg.emu_clk) module.generate_header() ##################################################### # CPU sim control section - add dump statements ##################################################### self.probe_dumps = SVAPI() self.probe_dumps.indent() self.probe_dumps.writeln(f'initial begin') self.probe_dumps.indent() self.probe_dumps.writeln('#0;') for probe in probes: self.probe_dumps.writeln(f'$dumpvars(0, {probe.name});') self.probe_dumps.dedent() self.probe_dumps.writeln(f'end') ##################################################### # FPGA sim control section - Instantiate ila core ##################################################### # Instantiate ila core self.ila_wiz_inst = SVAPI() ila_wiz = ModuleInst(api=self.ila_wiz_inst, name="ila_0") for k, signal in enumerate(probes): # Add probe signals ila_wiz.add_input(DigitalSignal(name=f'probe{k}', abspath=None, width=signal.width), connection=signal) ila_wiz.add_input(DigitalSignal(name='clk', abspath=None, width=1), connection=scfg.emu_clk) # Add master clk ila_wiz.generate_instantiation() TEMPLATE_TEXT = '''
class ModuleEmuClks(JinjaTempl): def __init__(self, scfg: StructureConfig, pcfg: EmuConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) gated_clks = [] ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="gen_emu_clks") module.add_input(scfg.emu_clk_2x) module.add_output(scfg.emu_clk) for derived_clk in scfg.clk_derived: if derived_clk.abspath_gated_clk is not None: gated_clks.append(derived_clk.name) # add IOs for default oscillator if used self.use_default_oscillator = scfg.use_default_oscillator if scfg.use_default_oscillator: module.add_input( DigitalSignal(name=f'clk_val_default_osc', width=1, abspath='')) module.add_output( DigitalSignal(name=f'clk_default_osc', width=1, abspath='')) for gated_clk in gated_clks: module.add_input( DigitalSignal(name=f'clk_val_{gated_clk}', width=1, abspath='')) module.add_output( DigitalSignal(name=f'clk_{gated_clk}', width=1, abspath='')) module.generate_header() ##################################################### # Generate other clks ##################################################### self.generated_clks = SVAPI() if gated_clks: for gated_clk in gated_clks: self.generated_clks.gen_signal(DigitalSignal( name=f'clk_unbuf_{gated_clk}', width=1, abspath=''), default_value=0) self.generated_clks.writeln(f'always @(posedge emu_clk_2x) begin') self.generated_clks.indent() for gated_clk in gated_clks: self.generated_clks.writeln( f"if (emu_clk_unbuf == 1'b0) begin") self.generated_clks.indent() self.generated_clks.writeln( f'clk_unbuf_{gated_clk} <= clk_val_{gated_clk};') self.generated_clks.dedent() self.generated_clks.writeln(f'end else begin') self.generated_clks.indent() self.generated_clks.writeln( f"clk_unbuf_{gated_clk} <= clk_unbuf_{gated_clk};") self.generated_clks.dedent() self.generated_clks.writeln(f'end') self.generated_clks.dedent() self.generated_clks.writeln(f'end') self.generated_clks.writeln(f'') self.generated_clks.writeln(f'`ifndef SIMULATION_MODE_MSDSL') self.generated_clks.indent() for k, gated_clk in enumerate(gated_clks): self.generated_clks.writeln( f'BUFG buf_{k} (.I(clk_unbuf_{gated_clk}), .O(clk_{gated_clk}));' ) self.generated_clks.dedent() self.generated_clks.writeln(f'`else') self.generated_clks.indent() for gated_clk in gated_clks: self.generated_clks.writeln( f'assign clk_{gated_clk} = clk_unbuf_{gated_clk};') self.generated_clks.dedent() self.generated_clks.writeln(f'`endif') TEMPLATE_TEXT = '''
class ModuleTimeManager(JinjaTempl): def __init__(self, scfg: StructureConfig, pcfg: EmuConfig, plugin_includes: list): super().__init__(trim_blocks=True, lstrip_blocks=True) self.num_dt_reqs = scfg.num_dt_reqs self.dt_value = pcfg.cfg.dt ##################################################### # Add plugin specific includes ##################################################### self.plugin_includes = SVAPI() for plugin in plugin_includes: for include_statement in plugin.include_statements: self.plugin_includes.writeln(f'{include_statement}') ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="gen_time_manager") module.add_input(scfg.emu_clk) module.add_input(scfg.reset_ctrl) module.add_output(scfg.time_probe) module.add_output( DigitalSignal(name=f'emu_dt', abspath='', width=pcfg.cfg.dt_width, signed=False)) # add inputs for external timestep requests dt_reqs = [] for derived_clk in scfg.clk_derived: if derived_clk.abspath_dt_req is not None: dt_req = DigitalSignal(name=f'dt_req_{derived_clk.name}', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) # add input for anasymod control dt request signal dt_req = DigitalSignal(name=f'dt_req_stall', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) # add input for dt request signal, in case a default oscillator is used if scfg.use_default_oscillator: dt_req = DigitalSignal(name=f'dt_req_default_osc', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) module.generate_header() # generate a bit of code to take the minimum of the timestep requests self.codegen = SVAPI() self.codegen.indent() # take minimum of the timestep requests if len(dt_reqs) == 0: # Convert dt value to integer considering dt_scale dt_as_int = int(float(pcfg.cfg.dt) / float(pcfg.cfg.dt_scale)) # Represent as binary and expand to dt_width dt_as_bin = bin(dt_as_int).replace('b', '').zfill(pcfg.cfg.dt_width) # assign to the emulator timestep output self.codegen.writeln( f"assign emu_dt = {pcfg.cfg.dt_width}'b{dt_as_bin};") else: prev_min = None for k, curr_sig in enumerate(dt_reqs): if k == 0: prev_min = curr_sig.name else: # create a signal to hold temporary min result curr_min = f'__dt_req_min_{k - 1}' self.codegen.writeln( f'(* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] {curr_min};' ) # take the minimum of the previous minimum and the current signal curr_min_val = self.vlog_min(curr_sig.name, prev_min) self.codegen.writeln( f'assign {curr_min} = {curr_min_val};') # mark the current minimum as the previous minimum for the next # iteration of the loop prev_min = curr_min # assign to the emulator timestep output self.codegen.writeln(f'assign emu_dt = {prev_min};') @staticmethod def vlog_min(a, b): return f'((({a}) < ({b})) ? ({a}) : ({b}))' TEMPLATE_TEXT = '''\
class ModuleRegMapSimCtrl(JinjaTempl): def __init__(self, scfg): super().__init__(trim_blocks=True, lstrip_blocks=True) crtl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs ##################################################### # Define module ios ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="reg_map") # Add clock clk = DigitalSignal(name='clk', width=1, abspath=None) module.add_input(io_obj=clk) o_ctrl = DigitalSignal(name='o_ctrl', width=32, abspath=None) module.add_input(io_obj=o_ctrl) o_data = DigitalSignal(name='o_data', width=32, abspath=None) module.add_output(io_obj=o_data) i_ctrl = DigitalSignal(name='i_ctrl', width=32, abspath=None) module.add_input(io_obj=i_ctrl) i_data = DigitalSignal(name='i_data', width=32, abspath=None) module.add_input(io_obj=i_data) # Add I/Os to Design (probes and Conrol Parameters) module.add_outputs(io_objs=crtl_inputs, connections=crtl_inputs) module.add_inputs(io_objs=ctrl_outputs, connections=ctrl_outputs) module.generate_header() ##################################################### # Initialize Default Values for ControlInfrastructure Parameters ##################################################### self.init_ctrlios = SVAPI() for parameter in crtl_inputs: default_signal = deepcopy(parameter) default_signal.name = str(default_signal.name) + '_def' self.init_ctrlios.gen_signal(io_obj=default_signal) self.init_ctrlios.assign_to(io_obj=default_signal, exp=default_signal.init_value) ##################################################### # Combo mux for Probes section ##################################################### # instantiation of register map module self.probes_combomux_cases = SVAPI() self.probes_combomux_cases.indent(quantity=3) for probe in ctrl_outputs: if probe.o_addr is not None: self.probes_combomux_cases.writeln(f"'d{probe.o_addr}: o_data_reg = {probe.name};") ##################################################### # Combo mux for Probes section ##################################################### # instantiation of register map module self.params_regmap = SVAPI() for param in crtl_inputs: # create a reg signal reg_signal = deepcopy(param) reg_signal.name = f'{param.name}_reg' self.params_regmap.gen_signal(reg_signal) # assign to the reg signal self.params_regmap.writeln(f'assign {param.name} = {param.name}_reg;') # update the reg signal self.params_regmap.writeln(f'''\ always @(posedge clk) begin if (i_rst == 'b1) begin {param.name}_reg <= {param.name}_def; // use VIO defaults end else if ((i_valid == 1'b1) && (i_addr == 'd{param.i_addr})) begin {param.name}_reg <= i_data; end else begin {param.name}_reg <= {param.name}_reg; end end''') TEMPLATE_TEXT = '''