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