Skip to content

Commit deadbcd

Browse files
committed
wip -nearly working
1 parent bf07d9f commit deadbcd

File tree

5 files changed

+70
-28
lines changed

5 files changed

+70
-28
lines changed

chipflow_lib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def _ensure_chipflow_root():
4444

4545
if os.environ["CHIPFLOW_ROOT"] not in sys.path:
4646
sys.path.append(os.environ["CHIPFLOW_ROOT"])
47-
_ensure_chipflow_root.root = os.environ["CHIPFLOW_ROOT"]
47+
_ensure_chipflow_root.root = Path(os.environ["CHIPFLOW_ROOT"]).absolute()
4848
return _ensure_chipflow_root.root
4949

5050

chipflow_lib/platforms/silicon.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def pins(self):
139139
def invert(self):
140140
return self._invert
141141

142+
142143
def __len__(self):
143144
if self._direction is io.Direction.Input:
144145
return len(self._i)

chipflow_lib/platforms/sim.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,20 @@ def instantiate_ports(self, m: Module):
110110
for name, port in v.items():
111111
self._ports[port.port_name] = SiliconPlatformPort(component, name, port)
112112

113-
for clock, name in self._config["chipflow"]["clocks"].items():
114-
if name not in pinlock.package.clocks:
115-
raise ChipFlowError("Unable to find clock {name} in pinlock")
113+
#for clock, name in self._config["chipflow"]["clocks"].items():
114+
# if name not in pinlock.package.clocks:
115+
# raise ChipFlowError("Unable to find clock {name} in pinlock")
116116

117-
port_data = pinlock.package.clocks[name]
118-
port = SiliconPlatformPort(component, name, port_data, invert=True)
119-
self._ports[name] = port
117+
# port_data = pinlock.package.clocks[name]
118+
# port = io.SimulationPort(component, name, port_data, invert=True)
119+
# self._ports[name] = port
120120

121-
if clock == 'default':
122-
clock = 'sync'
123-
setattr(m.domains, clock, ClockDomain(name=clock))
124-
clk_buffer = io.Buffer("i", port)
125-
setattr(m.submodules, "clk_buffer_" + clock, clk_buffer)
126-
m.d.comb += ClockSignal().eq(clk_buffer.i)
121+
# if clock == 'default':
122+
# clock = 'sync'
123+
# setattr(m.domains, clock, ClockDomain(name=clock))
124+
# clk_buffer = io.Buffer("i", port)
125+
# setattr(m.submodules, "clk_buffer_" + clock, clk_buffer)
126+
# m.d.comb += ClockSignal().eq(clk_buffer.i)
127127

128128
for reset, name in self._config["chipflow"]["resets"].items():
129129
port_data = pinlock.package.resets[name]
@@ -142,14 +142,15 @@ def instantiate_ports(self, m: Module):
142142
"OUTPUT_DIR": "./build/sim",
143143
"ZIG_CXX": f"{sys.executable} -m ziglang c++",
144144
"CXXFLAGS": "-O3 -g -std=c++17 -Wno-array-bounds -Wno-shift-count-overflow -fbracket-depth=1024",
145+
"DEFINES": "-DPROJECT_ROOT=\\\"{PROJECT_ROOT}\\\" -DBUILD_DIR=\\\"{BUILD_DIR}\\\"",
145146
"INCLUDES": "-I {OUTPUT_DIR} -I {COMMON_DIR} -I {COMMON_DIR}/vendor -I {RUNTIME_DIR}",
146147
}
147148
DOIT_CONFIG = {'action_string_formatting': 'both'}
148149

149150
BUILD_SIM = {
150151
"name": "build_sim",
151152
"actions": [
152-
"{ZIG_CXX} {CXXFLAGS} {INCLUDES} -o {OUTPUT_DIR}/sim_soc{EXE} "
153+
"{ZIG_CXX} {CXXFLAGS} {INCLUDES} {DEFINES} -o {OUTPUT_DIR}/sim_soc{EXE} "
153154
"{OUTPUT_DIR}/sim_soc.cc {SOURCE_DIR}/main.cc {COMMON_DIR}/models.cc"
154155
],
155156
"targets": [

chipflow_lib/platforms/utils.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pydantic
77

88
from collections import OrderedDict, deque
9-
from collections.abc import MutableMapping
9+
from collections.abc import MutableMapping, Iterable
1010
from pprint import pformat
1111
from typing import Set, List, Dict, Optional, Union, Literal
1212

@@ -73,11 +73,16 @@ class IOSignature(wiring.Signature):
7373
7474
:param direction: Input, Output or Bidir
7575
:param width: width of port, default is 1
76-
:param all_have_oe: controls whether each output wire is associated with an individual Output Enable bit or a single OE bit will be used for entire port, the default value is False, indicating that a single OE bit controls the entire port.
76+
:param invert: Polarity inversion. If the value is a simple :class:`bool`, it specifies inversion for
77+
the entire port. If the value is an iterable of :class:`bool`, the iterable must have the
78+
same length as the width of :py:`io`, and the inversion is specified for individual wires.
79+
:param all_have_oe: controls whether each output wire is associated with an individual Output Enable bit
80+
or a single OE bit will be used for entire port, the default value is False, indicating that a
81+
single OE bit controls the entire port.
7782
:param init: a :ref:`const-castable object <lang-constcasting>` for the initial values of the port
7883
"""
7984

80-
def __init__(self, direction: io.Direction, width: int = 1, all_have_oe: bool = False, init = None):
85+
def __init__(self, direction: io.Direction, width: int = 1, invert: Union[bool,Iterable[bool]] = False, all_have_oe: bool = False, init = None):
8186
self._direction = direction
8287
self._width = width
8388
self._init = init
@@ -98,6 +103,17 @@ def __init__(self, direction: io.Direction, width: int = 1, all_have_oe: bool =
98103
"all_have_oe": all_have_oe,
99104
"init": init,
100105
}
106+
match invert:
107+
case bool():
108+
self._invert = (invert,) * self._width
109+
case Iterable():
110+
self._invert = tuple(invert)
111+
if len(self._invert) != self._width:
112+
raise ValueError(f"Length of 'invert' ({len(self._invert)}) doesn't match "
113+
f"length of 'io' ({len(self._io)})")
114+
case _:
115+
raise TypeError(f"'invert' must be a bool or iterable of bool, not {invert!r}")
116+
101117

102118
super().__init__(sig)
103119

@@ -110,6 +126,10 @@ def width(self) -> int:
110126
"The width of the IO port, in wires"
111127
return self._width
112128

129+
def invert(self) -> int:
130+
"A tuple as wide as the IO port, with a bool for the polarity inversion for each wire"
131+
return self._invert
132+
113133
def options(self) -> dict:
114134
"""
115135
Options set on the io port at construction
@@ -356,6 +376,7 @@ class Port(pydantic.BaseModel):
356376
pins: List[str]
357377
port_name: str
358378
direction: Optional[str] = None
379+
invert: Union[bool, Iterable[bool]] = False
359380
options: Optional[dict] = None
360381

361382
@property

chipflow_lib/steps/sim.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212

1313
from amaranth import *
1414
from amaranth.lib import wiring, io
15+
from amaranth.lib.cdc import FFSynchronizer
1516
from amaranth.back import rtlil
17+
from amaranth.hdl._ir import PortDirection
1618

17-
from .. import ChipFlowError
19+
from .. import ChipFlowError, _ensure_chipflow_root
1820
from . import StepBase
1921
from ..platforms import SiliconPlatform, top_interfaces, load_pinlock
20-
from ..platforms.silicon import SiliconPlatformPort, FFSynchronizer
2122
from ..platforms.utils import IOSignature, load_pinlock, Port
2223
from ..platforms.sim import VARIABLES, TASKS, DOIT_CONFIG
2324

@@ -35,10 +36,11 @@ def common():
3536

3637
@contextmanager
3738
def source():
38-
sourcedir = importlib.resources.files("mcu_soc")
39-
sim_src = sourcedir.joinpath('design','sim')
40-
with importlib.resources.as_file(sim_src) as f:
41-
yield f
39+
root = _ensure_chipflow_root()
40+
sourcedir = Path(root) / 'design' / 'sim'
41+
#sim_src = sourcedir.joinpath('design','sim')
42+
#with importlib.resources.as_file(sim_src) as f:
43+
yield sourcedir
4244

4345
@contextmanager
4446
def runtime():
@@ -92,7 +94,16 @@ def add_file(self, filename, content):
9294
def build(self, e):
9395
Path(self.build_dir).mkdir(parents=True, exist_ok=True)
9496

95-
output = rtlil.convert(e, name="sim_top", ports=self._ports, platform=self)
97+
ports = []
98+
for port_name, port in self._ports.items():
99+
if port.direction in (io.Direction.Input, io.Direction.Bidir):
100+
ports.append((f"io${port_name}$i", port.i, PortDirection.Input))
101+
if port.direction in (io.Direction.Output, io.Direction.Bidir):
102+
ports.append((f"io${port_name}$o", port.o, PortDirection.Output))
103+
if port.direction is io.Direction.Bidir:
104+
ports.append((f"io${port_name}$oe", port.oe, PortDirection.Output))
105+
106+
output = rtlil.convert(e, name="sim_top", ports=ports, platform=self)
96107

97108
top_rtlil = Path(self.build_dir) / "sim_soc.il"
98109
with open(top_rtlil, "w") as rtlil_file:
@@ -120,14 +131,14 @@ def instantiate_ports(self, m: Module):
120131
for component, iface in pinlock.port_map.items():
121132
for k, v in iface.items():
122133
for name, port in v.items():
123-
self._ports[port.port_name] = SiliconPlatformPort(component, name, port)
134+
self._ports[port.port_name] = io.SimulationPort(port.direction, port.width, invert=port.invert, name=f"{component}-{name}")
124135

125136
for clock, name in self._config["chipflow"]["clocks"].items():
126137
if name not in pinlock.package.clocks:
127138
raise ChipFlowError("Unable to find clock {name} in pinlock")
128139

129140
port_data = pinlock.package.clocks[name]
130-
port = SiliconPlatformPort(component, name, port_data, invert=True)
141+
port = io.SimulationPort(io.Direction.Input, port_data.width, invert=True, name=f"clock-{name}")
131142
self._ports[name] = port
132143

133144
if clock == 'default':
@@ -139,7 +150,7 @@ def instantiate_ports(self, m: Module):
139150

140151
for reset, name in self._config["chipflow"]["resets"].items():
141152
port_data = pinlock.package.resets[name]
142-
port = SiliconPlatformPort(component, name, port_data)
153+
port = io.SimulationPort(io.Direction.Input, port_data.width, invert=port.invert, name=f"clock-{name}", )
143154
self._ports[name] = port
144155
rst_buffer = io.Buffer("i", port)
145156
setattr(m.submodules, reset, rst_buffer)
@@ -177,15 +188,23 @@ def build(self):
177188
iface = getattr(top[component], iface_name)
178189
wire = (iface if isinstance(iface.signature, IOSignature)
179190
else getattr(iface, name))
180-
self._platform._ports[port.port_name].wire(m, wire)
191+
port = self._platform._ports[port.port_name]
192+
if hasattr(wire, 'i'):
193+
m.d.comb += wire.i.eq(port.i)
194+
for d in ['o', 'oe']:
195+
if hasattr(wire, d):
196+
m.d.comb += getattr(port, d).eq(getattr(wire, d))
181197

182198

199+
#FIXME: common source for build dir
183200
self._platform.build(m)
184201
with common() as common_dir, source() as source_dir, runtime() as runtime_dir:
185202
context = {
186203
"COMMON_DIR": common_dir,
187204
"SOURCE_DIR": source_dir,
188205
"RUNTIME_DIR": runtime_dir,
206+
"PROJECT_ROOT": _ensure_chipflow_root(),
207+
"BUILD_DIR": _ensure_chipflow_root() / 'build',
189208
"EXE": EXE,
190209
}
191210
for k,v in VARIABLES.items():

0 commit comments

Comments
 (0)