CIRCT 23.0.0git
Loading...
Searching...
No Matches
cosim.py
Go to the documentation of this file.
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5from typing import Dict, Tuple, Type
6
7from pycde.signals import BundleSignal
8from pycde.common import AppID, Clock, Input, Output
9from pycde.module import Module, generator
10from pycde.support import get_user_loc
11from pycde.system import System
12from pycde.types import (Bits, Bundle, BundledChannel, Channel,
13 ChannelDirection, StructType, UInt)
14from pycde.constructs import ControlReg, NamedWire, Reg, Wire
15from pycde import esi
16
17from .common import (ChannelEngineService, ChannelHostMem, ChannelMMIO)
18from .dma import OneItemBuffersFromHost, OneItemBuffersToHost
19
20from pycde.circt import ir
21from pycde.circt.dialects import esi as raw_esi
22
23from pathlib import Path
24
25__root_dir__ = Path(__file__).parent.parent
26
27
28def CosimBSP(user_module: Type[Module], emulate_dma: bool = False) -> Module:
29 """Wrap and return a cosimulation 'board support package' containing
30 'user_module'"""
31
32 class ESI_Cosim_UserTopWrapper(Module):
33 """Wrap the user module along with 'standard' service generators so that
34 those generators can issue their own service requests to be picked up by the
35 actual top-level catch-all cosim service generator."""
36
37 clk = Clock()
38 rst = Input(Bits(1))
39
40 mmio = Input(esi.MMIO.read_write.type)
41
42 # If this gets changed, update 'Cosim.cpp' in the runtime.
43 HostMemWidth = 64
44
45 ChannelHostMemModule = ChannelHostMem(read_width=HostMemWidth,
46 write_width=HostMemWidth)
47
48 hostmem_read = ChannelHostMemModule.read
49 hostmem_write = ChannelHostMemModule.write
50
51 @generator
52 def build(ports):
53 user_module(clk=ports.clk, rst=ports.rst)
54 esi.TelemetryMMIO(esi.Telemetry,
55 appid=esi.AppID("__telemetry"),
56 clk=ports.clk,
57 rst=ports.rst)
58
59 if emulate_dma:
60 ChannelEngineService(OneItemBuffersToHost, OneItemBuffersFromHost)(
61 None,
62 appid=esi.AppID("__channel_engines"),
63 clk=ports.clk,
64 rst=ports.rst)
65
66 ChannelMMIO(esi.MMIO,
67 appid=esi.AppID("__cosim_mmio"),
68 clk=ports.clk,
69 rst=ports.rst,
70 cmd=ports.mmio)
71
72 # Instantiate a hostmem service generator which multiplexes requests to a
73 # either a single read or write channel. Get those channels and transform
74 # them into callbacks.
75 hostmem = ESI_Cosim_UserTopWrapper.ChannelHostMemModule(
76 decl=esi.HostMem,
77 appid=esi.AppID("__cosim_hostmem"),
78 clk=ports.clk,
79 rst=ports.rst)
80 ports.hostmem_read = hostmem.read
81 ports.hostmem_write = hostmem.write
82
83 class ESI_Cosim_Top(Module):
84 clk = Clock()
85 rst = Input(Bits(1))
86
87 @generator
88 def build(ports):
89 System.current().platform = "cosim"
90
91 mmio_read_write = esi.FuncService.get(
92 esi.AppID("__cosim_mmio_read_write"), esi.MMIO.read_write.type)
93 wrapper = ESI_Cosim_UserTopWrapper(clk=ports.clk,
94 rst=ports.rst,
95 mmio=mmio_read_write)
96
97 resp_channel = esi.ChannelService.from_host(
98 esi.AppID("__cosim_hostmem_read_resp"),
99 StructType([
100 ("tag", UInt(8)),
101 ("data", Bits(ESI_Cosim_UserTopWrapper.HostMemWidth)),
102 ]))
103 req = wrapper.hostmem_read.unpack(resp=resp_channel)['req']
104 esi.ChannelService.to_host(esi.AppID("__cosim_hostmem_read_req"), req)
105
106 ack_wire = Wire(Channel(UInt(8)))
107 write_req = wrapper.hostmem_write.unpack(ackTag=ack_wire)['req']
108 ack_tag = esi.CallService.call(esi.AppID("__cosim_hostmem_write"),
109 write_req, UInt(8))
110 ack_wire.assign(ack_tag)
111
112 cosim_svc = raw_esi.ServiceInstanceOp(
113 result=[],
114 appID=AppID("cosim")._appid,
115 service_symbol=None,
116 impl_type=ir.StringAttr.get("cosim"),
117 inputs=[ports.clk.value, ports.rst.value],
118 loc=get_user_loc())
119 core_freq = System.current().core_freq
120 if core_freq is not None:
121 cosim_svc.operation.attributes[
122 "esi.core_clock_frequency_hz"] = ir.IntegerAttr.get(
123 ir.IntegerType.get_unsigned(64), core_freq)
124
125 return ESI_Cosim_Top
126
127
128def CosimBSP_DMA(user_module: Type[Module]) -> Module:
129 return CosimBSP(user_module, emulate_dma=True)